in nodelist: # check if this is a placeholder first if isinstance(node, Placeholder): placeholders.append(node.get_name()) elif isinstance(node, IncludeNode): ... placeholders += _scan_placeholders(...) # handle {% extends ... %} tags elif isinstance(node, ExtendsNode): placeholders += _extend_nodelist(node) # in block nodes we have to scan for super blocks elif isinstance(node, VariableNode) and current_block: ... placeholders += _scan_placeholders(...)
plugin_id): ... if not instance: # instance doesn't exist, call add view response = plugin_admin.add_view(request) else: # already saved before, call change view # we actually have the instance here, but since i won't override # change_view method, is better if it will be loaded again, so # just pass id to plugin_admin response = plugin_admin.change_view(request, str(plugin_id)) ... return response Now the plugin data are complete
It also uses PLUGIN_CONTEXT_PROCESSORS and PLUGIN_PROCESSORS (i.e. process_response in MIDDLEWARE ) Each step is heavily cached caching attributes on objects using Django cache
for each language (i.e.: 2 Page and 2xN Title instances exists for any page) each live/draft contains copy of placeholders which contain copy of plugins
PAGE" if self.publisher_public_id: # Ensure we have up to date mptt properties public_page = Page.objects.get(pk=self.publisher_public_id) else: public_page = Page(created_by=self.created_by) ... self._copy_attributes(public_page) # we need to set relate this new public copy to its draft page (self public_page.publisher_public = self public_page.publisher_is_draft = False # Ensure that the page is in the right position and save it self._publisher_save_public(public_page) public_page = public_page.reload()
THE PUBLIC PAGE old_titles = dict(target.title_set.filter(language=language).values_list( for title in self.title_set.filter(language=language): old_pk = title.pk # this creates a new instance or recycle the old live title.pk = old_titles.pop(title.language, None) title.page = target title.publisher_is_draft = target.publisher_is_draft title.publisher_public_id = old_pk if published: title.publisher_state = PUBLISHER_STATE_DEFAULT else: title.publisher_state = PUBLISHER_STATE_PENDING title.published = published title._publisher_keep_state = True title.save()
PUBLISHED LANGUAGE for ph in self.get_placeholders(): plugins = ph.get_plugins_list(language) found = False for target_ph in target.placeholders.all(): if target_ph.slot == ph.slot: ph = target_ph found = True break if not found: ph.pk = None # make a new instance ph.save() new_phs.append(ph) if plugins: copy_plugins_to(plugins, ph, no_signals=True)
you have to class MyCMSPlugin(CMSPlugin): title = models.CharField(max_length=255) ... ORM operations on plugins would be very expensive (e.g.: building the list of plugins assigned to a placeholder) Abstract Base class vs. Multi-table inheritance
plugins # make a map of plugin types, needed later for downcasting for plugin in queryset: plugin_types_map[plugin.plugin_type].append(plugin.pk) for plugin_type, pks in plugin_types_map.items(): ... # get all the plugins of type cls.model plugin_qs = cls.get_render_queryset().filter(pk__in=pks) # put them in a map to replace base CMSPlugins with downcasted for instance in plugin_qs: plugin_lookup[instance.pk] = instance ... # make the equivalent list of qs, but with downcasted instances return [plugin_lookup.get(plugin.pk, plugin) for plugin in queryset]
data are set) # get the "real" plugin plugin_instance, cls = self.get_plugin_instance() # set up some basic attributes on the new_plugin new_plugin = CMSPlugin() new_plugin.placeholder = target_placeholder parent_cache[self.pk] = new_plugin if self.parent: parent = parent_cache[self.parent_id] parent = CMSPlugin.objects.get(pk=parent.pk) new_plugin.parent_id = parent.pk new_plugin.parent = parent new_plugin.language = target_language new_plugin.plugin_type = self.plugin_type # This triggers the tree setup for the "generic" plugin new_plugin.save()
that if plugin_instance: # get a new instance so references do not get mixed up plugin_instance = plugin_instance.__class__.objects.get( pk=plugin_instance.pk ) plugin_instance.placeholder = target_placeholder # assign the pk of the generic plugin plugin_instance.pk = new_plugin.pk plugin_instance.id = new_plugin.pk # this is the OneToOne field plugin_instance.cmsplugin_ptr = new_plugin plugin_instance.language = target_language # tree information saved before plugin_instance.parent = new_plugin.parent plugin_instance.depth = new_plugin.depth plugin_instance.path = new_plugin.path
None: urlconf = settings.ROOT_URLCONF if urlconf in sys.modules: reload(sys.modules[urlconf]) clear_app_resolvers() clear_url_caches() get_app_patterns() if new_revision is not None: set_local_revision(new_revision)