class GeoPageWithLeaflet(Page): address = models.CharField( max_length=250, help_text=_("Search powered by Nominatim"), blank=True, null=True, ) location = models.PointField(srid=4326, null=True, blank=True) content_panels = Page.content_panels + [ InlinePanel("related_locations", label="Related locations"), ] location_panels = [ MultiFieldPanel( [ GeoAddressPanel("address", geocoder=geocoders.NOMINATIM), LeafletPanel("location", address_field="address"), ], heading="Location", ) ] edit_handler = TabbedInterface([ ObjectList(content_panels, heading="Content"), ObjectList(location_panels, heading="Location"), ObjectList(Page.settings_panels, heading="Settings", classname="settings"), ])
class GeoPage(Page): address = models.CharField(max_length=250, blank=True, null=True) location = models.PointField(srid=4326, null=True, blank=True) content_panels = Page.content_panels + [ InlinePanel("related_locations", label="Related locations"), ] location_panels = [ MultiFieldPanel( [ GeoAddressPanel("address", geocoder=geocoders.GOOGLE_MAPS), GoogleMapsPanel("location", address_field="address"), ], heading="Location", ) ] edit_handler = TabbedInterface([ ObjectList(content_panels, heading="Content"), ObjectList(location_panels, heading="Location"), ObjectList(Page.settings_panels, heading="Settings", classname="settings"), ])
def get_setting_edit_handler(model): if hasattr(model, "edit_handler"): edit_handler = model.edit_handler else: panels = extract_panel_definitions_from_model_class(model, ["site"]) edit_handler = ObjectList(panels) return edit_handler.bind_to_model(model)
def get_edit_handler(self, instance=None, request=None): """ Returns the appropriate edit_handler for this modeladmin class. edit_handlers can be defined either on the model itself or on the modeladmin (as property edit_handler or panels). Falls back to extracting panel / edit handler definitions from the model class. """ if hasattr(self, "edit_handler"): edit_handler = self.edit_handler elif hasattr(self, "panels"): panels = self.panels edit_handler = ObjectList(panels) elif hasattr(self.model, "edit_handler"): edit_handler = self.model.edit_handler elif hasattr(self.model, "panels"): panels = self.model.panels edit_handler = ObjectList(panels) else: try: fields_to_exclude = self.get_form_fields_exclude() except TypeError: fields_to_exclude = self.get_form_fields_exclude(request=None) warn( "%s.get_form_fields_exclude should not accept a request argument" % type(self).__name__, category=RemovedInWagtail50Warning, ) panels = extract_panel_definitions_from_model_class( self.model, exclude=fields_to_exclude) edit_handler = ObjectList(panels) return edit_handler
def get_snippet_edit_handler(model): if model not in SNIPPET_EDIT_HANDLERS: if hasattr(model, "edit_handler"): # use the edit handler specified on the page class edit_handler = model.edit_handler else: panels = extract_panel_definitions_from_model_class(model) edit_handler = ObjectList(panels) SNIPPET_EDIT_HANDLERS[model] = edit_handler.bind_to_model(model) return SNIPPET_EDIT_HANDLERS[model]
def get_setting_edit_handler(model): if hasattr(model, "edit_handler"): edit_handler = model.edit_handler else: if issubclass(model, BaseSiteSetting): panels = extract_panel_definitions_from_model_class(model, ["site"]) elif issubclass(model, BaseGenericSetting): panels = extract_panel_definitions_from_model_class(model) else: raise NotImplementedError edit_handler = ObjectList(panels) return edit_handler.bind_to_model(model)
class VisitorAdmin(ModelAdmin): model = Visitor panels = [ FieldPanel("last_name"), FieldPanel("phone_number"), FieldPanel("address"), ] edit_handler = TabbedInterface([ ObjectList(panels), ])
def get_workflow_edit_handler(): """ Returns an edit handler which provides the "name" and "tasks" fields for workflow. """ # Note. It's a bit of a hack that we use edit handlers here. Ideally, it should be # made easier to reuse the inline panel templates for any formset. # Since this form is internal, we're OK with this for now. We might want to revisit # this decision later if we decide to allow custom fields on Workflows. panels = [ FieldPanel("name", heading=_("Give your workflow a name")), InlinePanel( "workflow_tasks", [ FieldPanel("task", widget=AdminTaskChooser(show_clear_link=False)), ], heading=_("Add tasks to your workflow"), label=_("Task"), icon="thumbtack", ), ] edit_handler = ObjectList(panels, base_form_class=WagtailAdminModelForm) return edit_handler.bind_to_model(Workflow)
def get_edit_handler(self, instance, request): """ Returns the appropriate edit_handler for this modeladmin class. edit_handlers can be defined either on the model itself or on the modeladmin (as property edit_handler or panels). Falls back to extracting panel / edit handler definitions from the model class. """ if hasattr(self, "edit_handler"): edit_handler = self.edit_handler elif hasattr(self, "panels"): panels = self.panels edit_handler = ObjectList(panels) elif hasattr(self.model, "edit_handler"): edit_handler = self.model.edit_handler elif hasattr(self.model, "panels"): panels = self.model.panels edit_handler = ObjectList(panels) else: fields_to_exclude = self.get_form_fields_exclude(request=request) panels = extract_panel_definitions_from_model_class( self.model, exclude=fields_to_exclude) edit_handler = ObjectList(panels) return edit_handler
class AdvertWithTabbedInterface(models.Model): url = models.URLField(null=True, blank=True) text = models.CharField(max_length=255) something_else = models.CharField(max_length=255) advert_panels = [ FieldPanel("url"), FieldPanel("text"), ] other_panels = [ FieldPanel("something_else"), ] edit_handler = TabbedInterface([ ObjectList(advert_panels, heading="Advert"), ObjectList(other_panels, heading="Other"), ]) def __str__(self): return self.text class Meta: ordering = ("text", )
def test_model_admin_panel_edit_handler_priority(self): """verifies that model admin panels are preferred over model panels""" # check if Person panel or edit_handler definition is used for # form creation, since PersonAdmin has neither panels nor an # edit_handler defined model_admin = PersonAdmin() edit_handler = model_admin.get_edit_handler() edit_handler = edit_handler.bind_to_model(model_admin.model) form_class = edit_handler.get_form_class() form = form_class() self.assertEqual(list(form.fields), ["first_name", "last_name", "phone_number"]) # now add a panel definition to the PersonAdmin and verify that # panel definition from PersonAdmin is used to construct the form # and NOT the panel or edit_handler definition from the Person model model_admin = PersonAdmin() model_admin.panels = [ FieldPanel("last_name"), FieldPanel("phone_number"), FieldPanel("address"), ] edit_handler = model_admin.get_edit_handler() edit_handler = edit_handler.bind_to_model(model_admin.model) form_class = edit_handler.get_form_class() form = form_class() self.assertEqual(list(form.fields), ["last_name", "phone_number", "address"]) # now add a edit_handler definition to the PersonAdmin and verify that # edit_handler definition from PersonAdmin is used to construct the # form and NOT the panel or edit_handler definition from the # Person model model_admin = PersonAdmin() model_admin.edit_handler = TabbedInterface( [ ObjectList( [ FieldPanel("phone_number"), FieldPanel("address"), ] ), ] ) edit_handler = model_admin.get_edit_handler() edit_handler = edit_handler.bind_to_model(model_admin.model) form_class = edit_handler.get_form_class() form = form_class() self.assertEqual(list(form.fields), ["phone_number", "address"])
class Person(models.Model): """model used to test model.edit_handlers usage in get_edit_handler""" first_name = models.CharField(max_length=255) last_name = models.CharField(max_length=255) phone_number = models.CharField(max_length=255) address = models.CharField(max_length=255) panels = [ FieldPanel("first_name"), FieldPanel("last_name"), FieldPanel("phone_number"), ] edit_handler = TabbedInterface([ ObjectList(panels), ]) def __str__(self): return self.first_name
class TabbedSettings(TestSetting): edit_handler = TabbedInterface([ ObjectList([FieldPanel("title")], heading="First tab"), ObjectList([FieldPanel("email")], heading="Second tab"), ])
FieldPanel("seo_title"), FieldPanel("slug"), InlinePanel("advert_placements", label="Adverts"), ] promote_panels = [] class StandardChild(Page): pass # Test overriding edit_handler with a custom one StandardChild.edit_handler = TabbedInterface( [ ObjectList(StandardChild.content_panels, heading="Content"), ObjectList(StandardChild.promote_panels, heading="Promote"), ObjectList(StandardChild.settings_panels, heading="Settings", classname="settings"), ObjectList([], heading="Dinosaurs"), ], base_form_class=WagtailAdminPageForm, ) class BusinessIndex(Page): """Can be placed anywhere, can only have Business children""" subpage_types = ["tests.BusinessChild", "tests.BusinessSubIndex"]
def test_preview_with_custom_edit_handler(self): """ The test is based on TestPreview.test_preview_on_create_with_m2m_field, except that the "categories" FieldPanel is only visible to superusers. Non-superusers should not be able to set "categories" for the preview. """ class SuperuserEventCategoriesObjectList(ObjectList): def on_request_bound(self): new_children = [] for child in self.children: # skip the "categories" FieldPanel for non-superusers if (isinstance(child, FieldPanel) and child.field_name == "categories" and not self.request.user.is_superuser): continue new_child = child.bind_to( model=self.model, instance=self.instance, request=self.request, form=self.form, ) new_children.append(new_child) self.children = new_children new_tabbed_interface = TabbedInterface([ SuperuserEventCategoriesObjectList(EventPage.content_panels), ObjectList(EventPage.promote_panels), ]) with mock.patch.object(EventPage, "edit_handler", new=new_tabbed_interface, create=True): # Non-superusers should not see categories panel, so even though "post_data" contains "categories", # it should not be considered for the preview request. self.login(username="******", password="******") preview_url = reverse( "wagtailadmin_pages:preview_on_add", args=("tests", "eventpage", self.home_page.id), ) response = self.client.post(preview_url, self.post_data) # Check the JSON response self.assertEqual(response.status_code, 200) self.assertJSONEqual(response.content.decode(), {"is_valid": True}) # Check the user can refresh the preview preview_session_key = "wagtail-preview-tests-eventpage-{}".format( self.home_page.id) self.assertIn(preview_session_key, self.client.session) response = self.client.get(preview_url) # Check the HTML response self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, "tests/event_page.html") self.assertContains(response, "Beach party") self.assertNotContains(response, "<li>Parties</li>") self.assertNotContains(response, "<li>Holidays</li>") # Since superusers see the "categories" panel, the posted data should be used for the preview. self.login(username="******", password="******") response = self.client.post(preview_url, self.post_data) # Check the JSON response self.assertEqual(response.status_code, 200) self.assertJSONEqual(response.content.decode(), {"is_valid": True}) # Check the user can refresh the preview preview_session_key = "wagtail-preview-tests-eventpage-{}".format( self.home_page.id) self.assertIn(preview_session_key, self.client.session) response = self.client.get(preview_url) # Check the HTML response self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, "tests/event_page.html") self.assertContains(response, "Beach party") self.assertContains(response, "<li>Parties</li>") self.assertContains(response, "<li>Holidays</li>")