33from django .utils .text import slugify
44from django .shortcuts import get_object_or_404
55
6- from .dash_wrapper import get_stateless_by_name
6+ from .dash_wrapper import get_local_stateless_by_name
77
88import json
99
10+ def get_stateless_by_name (name ):
11+ return get_local_stateless_by_name (name )
12+
13+ class StatelessApp (models .Model ):
14+ '''
15+ A stateless Dash app. An instance of this model represents a dash app without any specific state
16+ '''
17+ app_name = models .CharField (max_length = 100 , blank = False , null = False , unique = True )
18+ slug = models .SlugField (max_length = 110 , unique = True , blank = True )
19+
20+ def __str__ (self ):
21+ return self .app_name
22+
23+ def save (self , * args , ** kwargs ):
24+ if not self .slug or len (self .slug ) < 2 :
25+ self .slug = slugify (self .app_name )
26+ return super (StatelessApp , self ).save (* args ,** kwargs )
27+
28+ def as_dash_app (self ):
29+ '''
30+ Return a DjangoDash instance of the dash application
31+ '''
32+ dd = getattr (self ,'_stateless_dash_app_instance' ,None )
33+ if not dd :
34+ dd = get_stateless_by_name (self .app_name )
35+ setattr (self ,'_stateless_dash_app_instance' ,dd )
36+ return dd
37+
38+ def find_stateless_by_name (name ):
39+ try :
40+ dsa = StatelessApp .objects .get (app_name = name )
41+ return dsa .as_dash_app ()
42+ except :
43+ pass
44+
45+ da = get_stateless_by_name (name )
46+ dsa = StatelessApp (app_name = name )
47+ dsa .save ()
48+ return da
49+
50+ class StatelessAppAdmin (admin .ModelAdmin ):
51+ list_display = ['app_name' ,'slug' ,]
52+ list_filter = ['app_name' ,'slug' ,]
53+
1054class DashApp (models .Model ):
1155 '''
1256 An instance of this model represents a dash application and its internal state
1357 '''
14- app_name = models .CharField ( max_length = 100 , blank = False , null = False , unique = False )
58+ stateless_app = models .ForeignKey ( StatelessApp , on_delete = models . PROTECT , unique = False , null = False , blank = False )
1559 instance_name = models .CharField (max_length = 100 , unique = True , blank = True , null = False )
1660 slug = models .SlugField (max_length = 110 , unique = True , blank = True )
1761 base_state = models .TextField (null = False , default = "{}" ) # If mandating postgresql then this could be a JSONField
@@ -24,19 +68,12 @@ def __str__(self):
2468
2569 def save (self , * args , ** kwargs ):
2670 if not self .instance_name :
27- existing_count = DashApp .objects .filter ( app_name = self . app_name ).count ()
28- self .instance_name = "%s-%i" % (self .app_name , existing_count + 1 )
71+ existing_count = DashApp .objects .all ( ).count ()
72+ self .instance_name = "%s-%i" % (self .stateless_app . app_name , existing_count + 1 )
2973 if not self .slug or len (self .slug ) < 2 :
3074 self .slug = slugify (self .instance_name )
3175 super (DashApp , self ).save (* args ,** kwargs )
3276
33- def _stateless_dash_app (self ):
34- dd = getattr (self ,'_stateless_dash_app_instance' ,None )
35- if not dd :
36- dd = get_stateless_by_name (self .app_name )
37- setattr (self ,'_stateless_dash_app_instance' ,dd )
38- return dd
39-
4077 def handle_current_state (self ):
4178 '''
4279 Check to see if the current hydrated state and the saved state are different.
@@ -82,16 +119,16 @@ def current_state(self):
82119 return cs
83120
84121 def as_dash_instance (self ):
85- dd = self ._stateless_dash_app ()
122+ dd = self .stateless_app . as_dash_app ()
86123 base = self .current_state ()
87- return dd .form_dash_instance (replacements = base ,
88- specific_identifier = self .slug )
124+ return dd .do_form_dash_instance (replacements = base ,
125+ specific_identifier = self .slug )
89126
90127 def _get_base_state (self ):
91128 '''
92129 Get the base state of the object, as defined by the app.layout code, as a python dict
93130 '''
94- base_app_inst = self ._stateless_dash_app ().as_dash_instance ()
131+ base_app_inst = self .stateless_app . as_dash_app ().as_dash_instance ()
95132
96133 # Get base layout response, from a base object
97134 base_resp = base_app_inst .locate_endpoint_function ('dash-layout' )()
@@ -113,21 +150,30 @@ def populate_values(self):
113150 @staticmethod
114151 def locate_item (id , stateless = False ):
115152 if stateless :
116- da = get_stateless_by_name (id )
153+ da = find_stateless_by_name (id )
117154 else :
118155 da = get_object_or_404 (DashApp ,slug = id )
119156
120157 app = da .as_dash_instance ()
121158 return da , app
122159
123160class DashAppAdmin (admin .ModelAdmin ):
124- list_display = ['instance_name' ,'app_name ' ,'slug' ,'creation' ,'update' ,'save_on_change' ,]
125- list_filter = ['creation' ,'update' ,'save_on_change' ,'app_name ' ,]
161+ list_display = ['instance_name' ,'stateless_app ' ,'slug' ,'creation' ,'update' ,'save_on_change' ,]
162+ list_filter = ['creation' ,'update' ,'save_on_change' ,'stateless_app ' ,]
126163
127164 def _populate_values (self , request , queryset ):
128165 for da in queryset :
129166 da .populate_values ()
130167 da .save ()
131- _populate_values .short_description = "Populate app"
168+ _populate_values .short_description = "Populate app instance"
169+
170+ def _clone (self , request , queryset ):
171+ for da in queryset :
172+ nda = DashApp (stateless_app = da .stateless_app ,
173+ base_state = da .base_state ,
174+ save_on_change = da .save_on_change )
175+ nda .save ()
176+
177+ _clone .short_description = "Clone app instance"
132178
133- actions = ['_populate_values' ,]
179+ actions = ['_populate_values' ,'_clone' , ]
0 commit comments