1616from .errors import UnicornViewError
1717from .message import ComponentRequest , Return
1818from .serializer import loads
19+ from .utils import generate_checksum
1920
2021
2122logger = logging .getLogger (__name__ )
@@ -227,10 +228,12 @@ def message(request: HttpRequest, component_name: str = None) -> JsonResponse:
227228
228229 is_reset_called = False
229230 return_data = None
231+ partials = []
230232
231233 for action in component_request .action_queue :
232234 action_type = action .get ("type" )
233235 payload = action .get ("payload" , {})
236+ partials .append (action .get ("partial" ))
234237
235238 if action_type == "syncInput" :
236239 property_name = payload .get ("name" )
@@ -290,6 +293,8 @@ def message(request: HttpRequest, component_name: str = None) -> JsonResponse:
290293 instance .save ()
291294 pk = instance .pk
292295 elif action_type == "callMethod" :
296+ print ("payload" , payload )
297+
293298 call_method_name = payload .get ("name" , "" )
294299 assert call_method_name , "Missing 'name' key for callMethod"
295300
@@ -366,14 +371,61 @@ def message(request: HttpRequest, component_name: str = None) -> JsonResponse:
366371 component .validate (model_names = model_names_to_validate )
367372
368373 rendered_component = component .render ()
374+ partial_doms = []
375+
376+ if partials and all (partials ):
377+ soup = BeautifulSoup (rendered_component , features = "html.parser" )
378+
379+ for partial in partials :
380+ partial_found = False
381+ only_id = False
382+ only_key = False
383+
384+ target = partial .get ("target" )
385+
386+ if not target :
387+ target = partial .get ("key" )
388+
389+ if target :
390+ only_key = True
391+
392+ if not target :
393+ target = partial .get ("id" )
394+
395+ if target :
396+ only_id = True
397+
398+ assert target , "Partial target is required"
399+
400+ if not only_id :
401+ for element in soup .find_all ():
402+ if (
403+ "unicorn:key" in element .attrs
404+ and element .attrs ["unicorn:key" ] == target
405+ ):
406+ partial_doms .append ({"key" : target , "dom" : str (element )})
407+ partial_found = True
408+ break
409+
410+ if not partial_found and not only_key :
411+ for element in soup .find_all ():
412+ if "id" in element .attrs and element .attrs ["id" ] == target :
413+ partial_doms .append ({"id" : target , "dom" : str (element )})
414+ partial_found = True
415+ break
369416
370417 res = {
371418 "id" : component_request .id ,
372- "dom" : rendered_component ,
373419 "data" : component_request .data ,
374420 "errors" : component .errors ,
421+ "checksum" : generate_checksum (orjson .dumps (component_request .data )),
375422 }
376423
424+ if partial_doms :
425+ res .update ({"partials" : partial_doms })
426+ else :
427+ res .update ({"dom" : rendered_component })
428+
377429 if return_data :
378430 res .update (
379431 {"return" : return_data .get_data (),}
@@ -396,9 +448,9 @@ def message(request: HttpRequest, component_name: str = None) -> JsonResponse:
396448 parent_component .get_frontend_context_variables ()
397449 )
398450
399- dom = parent_component .render ()
451+ parent_dom = parent_component .render ()
400452
401- soup = BeautifulSoup (dom , features = "html.parser" )
453+ soup = BeautifulSoup (parent_dom , features = "html.parser" )
402454 checksum = None
403455
404456 # TODO: This doesn't create the same checksum for some reason
@@ -413,7 +465,7 @@ def message(request: HttpRequest, component_name: str = None) -> JsonResponse:
413465 {
414466 "parent" : {
415467 "id" : parent_component .component_id ,
416- "dom" : dom ,
468+ "dom" : parent_dom ,
417469 "checksum" : checksum ,
418470 "data" : loads (parent_frontend_context_variables ),
419471 "errors" : parent_component .errors ,
0 commit comments