Fix Module slug generation
This commit is contained in:
parent
101670355e
commit
f398839765
|
|
@ -3,12 +3,14 @@ from django.db import models
|
|||
from django.utils import timezone
|
||||
from django.utils.translation import gettext as _
|
||||
from wagtail.admin.forms import WagtailAdminPageForm
|
||||
from wagtail.admin.panels import FieldPanel, TabbedInterface, ObjectList
|
||||
from wagtail.admin.panels import FieldPanel, TabbedInterface, ObjectList, TitleFieldPanel
|
||||
from wagtail.fields import RichTextField
|
||||
|
||||
from django.conf import settings
|
||||
from core.constants import DEFAULT_RICH_TEXT_FEATURES
|
||||
from core.wagtail_utils import StrictHierarchyPage, get_default_settings
|
||||
from users.models import SchoolClass
|
||||
from django.utils.text import slugify
|
||||
|
||||
EXACT = "exact"
|
||||
|
||||
|
|
@ -54,9 +56,10 @@ class ModuleCategory(models.Model):
|
|||
class ModulePageForm(WagtailAdminPageForm):
|
||||
def clean(self):
|
||||
cleaned_data = super().clean()
|
||||
print("cleaning")
|
||||
if "slug" in self.cleaned_data:
|
||||
page_slug = cleaned_data["slug"]
|
||||
if not Module._slug_is_available(page_slug, self.instance):
|
||||
if not Module._slug_is_available(page_slug, self.parent_page, self.instance):
|
||||
self.add_error(
|
||||
"slug",
|
||||
forms.ValidationError(
|
||||
|
|
@ -97,7 +100,7 @@ class Module(StrictHierarchyPage):
|
|||
solutions_enabled_for = models.ManyToManyField(SchoolClass)
|
||||
|
||||
content_panels = [
|
||||
FieldPanel("title", classname="full title"),
|
||||
TitleFieldPanel("title", classname="full title"),
|
||||
FieldPanel("meta_title", classname="full title"),
|
||||
FieldPanel("level"),
|
||||
FieldPanel("category"),
|
||||
|
|
@ -106,7 +109,7 @@ class Module(StrictHierarchyPage):
|
|||
FieldPanel("teaser"),
|
||||
FieldPanel("intro"),
|
||||
]
|
||||
base_form_class = ModulePageForm
|
||||
# base_form_class = ModulePageForm
|
||||
|
||||
edit_handler = TabbedInterface(
|
||||
[ObjectList(content_panels, heading="Content"), get_default_settings()]
|
||||
|
|
@ -181,11 +184,42 @@ class Module(StrictHierarchyPage):
|
|||
return f"{self.meta_title} - {self.title}"
|
||||
|
||||
@staticmethod
|
||||
def _slug_is_available(slug, page):
|
||||
# modeled after `Page._slug_is_available`
|
||||
modules = Module.objects.filter(slug=slug).not_page(page)
|
||||
def _slug_is_available(slug, parent_page, page=None):
|
||||
"""
|
||||
|
||||
return not modules.exists()
|
||||
# modeled after `Page._slug_is_available`
|
||||
|
||||
Determine whether the given slug is available for use on a child page of
|
||||
parent_page. If 'page' is passed, the slug is intended for use on that page
|
||||
(and so it will be excluded from the duplicate check).
|
||||
"""
|
||||
if parent_page is None:
|
||||
# the root page's slug can be whatever it likes...
|
||||
return True
|
||||
|
||||
modules = Module.objects.all()
|
||||
if page:
|
||||
modules = modules.not_page(page)
|
||||
|
||||
return not modules.filter(slug=slug).exists()
|
||||
|
||||
def _get_autogenerated_slug(self, base_slug):
|
||||
# modeled after `Page._get_autogenerated_slug`
|
||||
candidate_slug = base_slug
|
||||
suffix = 1
|
||||
parent_page = self.get_parent()
|
||||
|
||||
while not self._slug_is_available(candidate_slug, parent_page, self):
|
||||
# try with incrementing suffix until we find a slug which is available
|
||||
suffix += 1
|
||||
candidate_slug = "%s-%d" % (base_slug, suffix)
|
||||
return candidate_slug
|
||||
|
||||
def full_clean(self, *args, **kwargs):
|
||||
super().full_clean(*args, **kwargs)
|
||||
|
||||
if not self._slug_is_available(self.slug, self.get_parent(), self):
|
||||
self.slug = self._get_autogenerated_slug(self.slug)
|
||||
|
||||
|
||||
class RecentModule(models.Model):
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
from django.test import TestCase, RequestFactory
|
||||
from unittest import skip
|
||||
from graphene.test import Client
|
||||
from graphql_relay import to_global_id
|
||||
|
||||
from api.schema import schema
|
||||
from api.utils import get_object
|
||||
from books.models import ContentBlock, Chapter
|
||||
from books.factories import ModuleFactory, ModuleLevelFactory, TopicFactory
|
||||
from core.factories import UserFactory
|
||||
from users.models import User
|
||||
|
||||
|
||||
class TestModuleCreation(TestCase):
|
||||
"""
|
||||
Since the modules url in the frontend is not /topic/module but /module the slug has to be unique.
|
||||
This test checks if the slug is generated correctly.
|
||||
"""
|
||||
|
||||
def test_create_new_module_generates_slug(self):
|
||||
topic = TopicFactory(title="Berufslehre")
|
||||
module = ModuleFactory(title="Modul 1", parent=topic)
|
||||
self.assertEqual("modul-1", module.slug)
|
||||
|
||||
def test_create_new_module_different_topic(self):
|
||||
topic = TopicFactory(title="Berufslehre")
|
||||
module = ModuleFactory(title="Modul 1", parent=topic)
|
||||
|
||||
topic2 = TopicFactory(title="Geld und Macht")
|
||||
module2 = ModuleFactory(title="Modul 1", parent=topic2)
|
||||
self.assertEqual("modul-1", module.slug)
|
||||
self.assertEqual("modul-1-2", module2.slug, )
|
||||
|
|
@ -2,6 +2,7 @@ from django.contrib import admin
|
|||
from wagtail.admin.panels import CommentPanel
|
||||
from wagtail.admin.panels import FieldPanel, ObjectList
|
||||
from wagtail.models import Page
|
||||
from wagtail.admin.widgets.slug import SlugInput
|
||||
|
||||
|
||||
class StrictHierarchyPage(Page):
|
||||
|
|
@ -41,4 +42,4 @@ def wagtail_parent_filter(parent_cls, child_cls):
|
|||
|
||||
|
||||
def get_default_settings():
|
||||
return ObjectList([FieldPanel("slug", read_only=True), CommentPanel()], heading="Settings")
|
||||
return ObjectList([FieldPanel("slug", widget=SlugInput), CommentPanel()], heading="Settings")
|
||||
|
|
|
|||
Loading…
Reference in New Issue