Last active
June 6, 2024 15:59
-
-
Save cnk/46b2755a210255af107f03da0b6b98dd to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class RedirectPage(Page): | |
destination = models.CharField( | |
'Destination URL', | |
max_length=512, | |
help_text="If you want to redirect to an arbitrary URL, input it here. If redirecting off-site, the URL must " | |
"start with https://. If you want to redirect to a page on your site, use the Page field, instead.", | |
blank=True, | |
) | |
page = models.ForeignKey( | |
'wagtailcore.Page', # noqa | |
null=True, | |
blank=True, | |
on_delete=models.SET_NULL, | |
related_name='+', | |
help_text='If you want to redirect to another Page on your site, choose it here.' | |
) | |
document = models.ForeignKey( | |
get_document_model(), | |
null=True, | |
blank=True, | |
on_delete=models.SET_NULL, | |
related_name='+', | |
help_text='If you want to redirect to a Document on your site, choose it here.' | |
) | |
################### | |
# EDIT FORM CONFIG | |
################### | |
content_panels = Page.content_panels + [ | |
MultiFieldPanel( | |
heading='Targets', | |
children=[ | |
FieldPanel('destination'), | |
FieldPanel('page'), | |
FieldPanel('document'), | |
] | |
) | |
] | |
page_description = 'When users click this page in the menu, they are redirected to a custom URL of your choice.' | |
class Meta: | |
verbose_name = 'Redirect Page' | |
verbose_name_plural = 'Redirect Pages' | |
def clean(self): | |
""" | |
Prevent RedirectPages from being saved unless they've got exactly one of either destination, page, or document. | |
""" | |
# int(bool(thing)) converts truthy values to 1 and falsey values to 0. | |
target_count = int(bool(self.destination)) + int(bool(self.page)) + int(bool(self.document)) | |
if target_count != 1: | |
raise ValidationError('RedirectPages must have a single target: either destination, page, or document.') | |
@property | |
def redirect_target_url(self): | |
# For historical reasons, we prioritize Document over Page, and both over Destination. | |
# This cannot have any meaningful effect on newly-saved RedirectPages, as we no longer allow users to set more | |
# than one of them. But existing RedirectPages with multiple values must continue to function as they always | |
# have, until they get saved again and are forced to set only one value. | |
if self.document: | |
return self.document.url | |
if self.page: | |
return self.page.specific.relative_url() # noqa | |
return self.destination | |
def serve(self, request, *args, **kwargs): # noqa | |
""" | |
Rather than a normal page, RedirectPages serve a redirect to the destination URL, Page, or Document. | |
NOTE: Most of the time, visitors will not activate this method, because the menu code serves the | |
redirect_target_url to them directly. | |
""" | |
response = redirect(self.redirect_target_url, permanent=True) | |
return self.add_cache_control_headers(response) | |
@property | |
def preview_modes(self): | |
""" | |
Disable previewing of RedirectPages, since they don't have anything to preview. | |
""" | |
return [] | |
def get_url(self, request=None, current_site=None): | |
""" | |
We override this method to make our menu render the destination URL for this RedirectPage, instead of the | |
Page's own URL. | |
""" | |
return self.redirect_target_url |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment