77
88import json
99
10+ def get_stateless_by_name (name ):
11+ return get_local_stateless_by_name (name )
12+
1013class StatelessApp (models .Model ):
1114 '''
12- A stateless Dash app. An instance of this model represents a dash app witout any specific state
15+ A stateless Dash app. An instance of this model represents a dash app without any specific state
1316 '''
1417 app_name = models .CharField (max_length = 100 , blank = False , null = False , unique = True )
1518 slug = models .SlugField (max_length = 110 , unique = True , blank = True )
@@ -22,18 +25,34 @@ def save(self, *args, **kwargs):
2225 self .slug = slugify (self .app_name )
2326 return super (StatelessApp , self ).save (* args ,** kwargs )
2427
28+ def as_dash_app (self ):
29+ dd = getattr (self ,'_stateless_dash_app_instance' ,None )
30+ if not dd :
31+ dd = get_stateless_by_name (self .app_name )
32+ setattr (self ,'_stateless_dash_app_instance' ,dd )
33+ return dd
34+
35+ def find_stateless_by_name (name ):
36+ try :
37+ dsa = StatelessApp .objects .get (app_name = name )
38+ return dsa .as_dash_app ()
39+ except :
40+ pass
41+
42+ da = get_stateless_by_name (name )
43+ dsa = StatelessApp (app_name = name )
44+ dsa .save ()
45+ return da
46+
2547class StatelessAppAdmin (admin .ModelAdmin ):
2648 list_display = ['app_name' ,'slug' ,]
2749 list_filter = ['app_name' ,'slug' ,]
2850
29- def get_stateless_by_name (name ):
30- return get_local_stateless_by_name (name )
31-
3251class DashApp (models .Model ):
3352 '''
3453 An instance of this model represents a dash application and its internal state
3554 '''
36- app_name = models .CharField ( max_length = 100 , blank = False , null = False , unique = False )
55+ stateless_app = models .ForeignKey ( StatelessApp , on_delete = models . PROTECT , unique = False , null = False , blank = False )
3756 instance_name = models .CharField (max_length = 100 , unique = True , blank = True , null = False )
3857 slug = models .SlugField (max_length = 110 , unique = True , blank = True )
3958 base_state = models .TextField (null = False , default = "{}" ) # If mandating postgresql then this could be a JSONField
@@ -46,19 +65,12 @@ def __str__(self):
4665
4766 def save (self , * args , ** kwargs ):
4867 if not self .instance_name :
49- existing_count = DashApp .objects .filter ( app_name = self . app_name ).count ()
50- self .instance_name = "%s-%i" % (self .app_name , existing_count + 1 )
68+ existing_count = DashApp .objects .all ( ).count ()
69+ self .instance_name = "%s-%i" % (self .stateless_app . app_name , existing_count + 1 )
5170 if not self .slug or len (self .slug ) < 2 :
5271 self .slug = slugify (self .instance_name )
5372 super (DashApp , self ).save (* args ,** kwargs )
5473
55- def _stateless_dash_app (self ):
56- dd = getattr (self ,'_stateless_dash_app_instance' ,None )
57- if not dd :
58- dd = get_stateless_by_name (self .app_name )
59- setattr (self ,'_stateless_dash_app_instance' ,dd )
60- return dd
61-
6274 def handle_current_state (self ):
6375 '''
6476 Check to see if the current hydrated state and the saved state are different.
@@ -104,7 +116,7 @@ def current_state(self):
104116 return cs
105117
106118 def as_dash_instance (self ):
107- dd = self ._stateless_dash_app ()
119+ dd = self .stateless_app . as_dash_app ()
108120 base = self .current_state ()
109121 return dd .do_form_dash_instance (replacements = base ,
110122 specific_identifier = self .slug )
@@ -113,7 +125,7 @@ def _get_base_state(self):
113125 '''
114126 Get the base state of the object, as defined by the app.layout code, as a python dict
115127 '''
116- base_app_inst = self ._stateless_dash_app ().as_dash_instance ()
128+ base_app_inst = self .stateless_app . as_dash_app ().as_dash_instance ()
117129
118130 # Get base layout response, from a base object
119131 base_resp = base_app_inst .locate_endpoint_function ('dash-layout' )()
@@ -135,21 +147,30 @@ def populate_values(self):
135147 @staticmethod
136148 def locate_item (id , stateless = False ):
137149 if stateless :
138- da = get_stateless_by_name (id )
150+ da = find_stateless_by_name (id )
139151 else :
140152 da = get_object_or_404 (DashApp ,slug = id )
141153
142154 app = da .as_dash_instance ()
143155 return da , app
144156
145157class DashAppAdmin (admin .ModelAdmin ):
146- list_display = ['instance_name' ,'app_name ' ,'slug' ,'creation' ,'update' ,'save_on_change' ,]
147- list_filter = ['creation' ,'update' ,'save_on_change' ,'app_name ' ,]
158+ list_display = ['instance_name' ,'stateless_app ' ,'slug' ,'creation' ,'update' ,'save_on_change' ,]
159+ list_filter = ['creation' ,'update' ,'save_on_change' ,'stateless_app ' ,]
148160
149161 def _populate_values (self , request , queryset ):
150162 for da in queryset :
151163 da .populate_values ()
152164 da .save ()
153- _populate_values .short_description = "Populate app"
165+ _populate_values .short_description = "Populate app instance"
166+
167+ def _clone (self , request , queryset ):
168+ for da in queryset :
169+ nda = DashApp (stateless_app = da .stateless_app ,
170+ base_state = da .base_state ,
171+ save_on_change = da .save_on_change )
172+ nda .save ()
173+
174+ _clone .short_description = "Clone app instance"
154175
155- actions = ['_populate_values' ,]
176+ actions = ['_populate_values' ,'_clone' , ]
0 commit comments