diff --git a/jdav_web/startpage/admin.py b/jdav_web/startpage/admin.py index e950659..4289ace 100644 --- a/jdav_web/startpage/admin.py +++ b/jdav_web/startpage/admin.py @@ -1,11 +1,15 @@ -from django.contrib import admin -from django.conf import settings from django import forms -from django.utils.translation import gettext_lazy as _ +from django.conf import settings +from django.contrib import admin from django.db.models import TextField from django.forms import Textarea +from django.utils.translation import gettext_lazy as _ -from .models import Post, Image, Section, MemberOnPost, Link +from .models import Image +from .models import Link +from .models import MemberOnPost +from .models import Post +from .models import Section class ImageInline(admin.TabularInline): @@ -19,37 +23,42 @@ class MemberOnPostInline(admin.TabularInline): class PostForm(forms.ModelForm): - urlname = forms.RegexField(regex=r'^{pattern}+$'.format(pattern=settings.STARTPAGE_URL_NAME_PATTERN), - label=_('URL'), - error_messages={'invalid': _('The url may only consist of letters, numerals, _, -, :, * and spaces.')}) + urlname = forms.RegexField( + regex=r"^{pattern}+$".format(pattern=settings.STARTPAGE_URL_NAME_PATTERN), + label=_("URL"), + error_messages={ + "invalid": _("The url may only consist of letters, numerals, _, -, :, * and spaces.") + }, + ) @admin.register(Post) class PostAdmin(admin.ModelAdmin): inlines = [ImageInline, MemberOnPostInline] - list_display = ['title', 'date', 'section', 'absolute_urlname'] - list_filter = ['section'] - search_fields = ['title'] + list_display = ["title", "date", "section", "absolute_urlname"] + list_filter = ["section"] + search_fields = ["title"] form = PostForm class SectionForm(forms.ModelForm): - urlname = forms.RegexField(regex=r'^{pattern}+$'.format(pattern=settings.STARTPAGE_URL_NAME_PATTERN), - label=_('URL'), - error_messages={'invalid': _('The url may only consist of letters, numerals, _, -, :, * and spaces.')}) + urlname = forms.RegexField( + regex=r"^{pattern}+$".format(pattern=settings.STARTPAGE_URL_NAME_PATTERN), + label=_("URL"), + error_messages={ + "invalid": _("The url may only consist of letters, numerals, _, -, :, * and spaces.") + }, + ) + @admin.register(Section) class SectionAdmin(admin.ModelAdmin): - list_display = ['title', 'absolute_urlname'] + list_display = ["title", "absolute_urlname"] form = SectionForm @admin.register(Link) class LinkAdmin(admin.ModelAdmin): - list_display = ['title', 'url', 'visible'] - - formfield_overrides = { - TextField: {'widget': Textarea(attrs={'rows': 2, 'cols': 40})} - } - + list_display = ["title", "url", "visible"] + formfield_overrides = {TextField: {"widget": Textarea(attrs={"rows": 2, "cols": 40})}} diff --git a/jdav_web/startpage/apps.py b/jdav_web/startpage/apps.py index 836dc89..5b14f04 100644 --- a/jdav_web/startpage/apps.py +++ b/jdav_web/startpage/apps.py @@ -2,4 +2,4 @@ from django.apps import AppConfig class StartpageConfig(AppConfig): - name = 'startpage' + name = "startpage" diff --git a/jdav_web/startpage/models.py b/jdav_web/startpage/models.py index a04bd08..7e2e950 100644 --- a/jdav_web/startpage/models.py +++ b/jdav_web/startpage/models.py @@ -1,53 +1,61 @@ import os from django.db import models -from django.utils.translation import gettext_lazy as _ +from django.urls import NoReverseMatch +from django.urls import reverse from django.utils import timezone -from django.urls import reverse, NoReverseMatch -from utils import RestrictedFileField -from members.models import Group, Member - +from django.utils.translation import gettext_lazy as _ from markdownx.models import MarkdownxField +from members.models import Group +from members.models import Member +from utils import RestrictedFileField class Section(models.Model): """ A section of the website. """ - title = models.CharField(verbose_name=_('Title'), max_length=50) - urlname = models.CharField(verbose_name=_('URL'), max_length=25) - website_text = MarkdownxField(verbose_name=_('website text'), default='', blank=True) - show_in_navigation = models.BooleanField(verbose_name=_('Show in navigation'), default=True) + + title = models.CharField(verbose_name=_("Title"), max_length=50) + urlname = models.CharField(verbose_name=_("URL"), max_length=25) + website_text = MarkdownxField(verbose_name=_("website text"), default="", blank=True) + show_in_navigation = models.BooleanField(verbose_name=_("Show in navigation"), default=True) class Meta: - verbose_name = _('Section') - verbose_name_plural = _('Sections') - unique_together = ['urlname'] + verbose_name = _("Section") + verbose_name_plural = _("Sections") + unique_together = ["urlname"] def __str__(self): return self.title def absolute_urlname(self): try: - return reverse('startpage:section', args=(self.urlname,)) + return reverse("startpage:section", args=(self.urlname,)) except NoReverseMatch: - return _('deactivated') - absolute_urlname.short_description = 'URL' + return _("deactivated") + + absolute_urlname.short_description = "URL" class Post(models.Model): """ A post with title, markdown and images. """ - title = models.CharField(verbose_name=_('Title'), default='', max_length=50) - urlname = models.CharField(verbose_name=_('URL'), default='', max_length=50) - date = models.DateField(default=timezone.localdate, verbose_name=_('Date'), null=True, blank=True) - website_text = MarkdownxField(verbose_name=_('website text'), default='', blank=True) - groups = models.ManyToManyField(Group, verbose_name=_('Groups'), blank=True) - detailed = models.BooleanField(verbose_name=_('detailed'), default=False) + title = models.CharField(verbose_name=_("Title"), default="", max_length=50) + urlname = models.CharField(verbose_name=_("URL"), default="", max_length=50) + date = models.DateField( + default=timezone.localdate, verbose_name=_("Date"), null=True, blank=True + ) + website_text = MarkdownxField(verbose_name=_("website text"), default="", blank=True) + + groups = models.ManyToManyField(Group, verbose_name=_("Groups"), blank=True) + detailed = models.BooleanField(verbose_name=_("detailed"), default=False) - section = models.ForeignKey(Section, verbose_name=_('section'), on_delete=models.CASCADE, null=True, blank=False) + section = models.ForeignKey( + Section, verbose_name=_("section"), on_delete=models.CASCADE, null=True, blank=False + ) def __str__(self): """String represenation""" @@ -56,53 +64,56 @@ class Post(models.Model): class Meta: verbose_name = _("Post") verbose_name_plural = _("Posts") - unique_together = ['section', 'urlname'] + unique_together = ["section", "urlname"] def absolute_section(self): if self.section is None: - return 'Aktuelles' + return "Aktuelles" else: return self.section.title - absolute_section.short_description = _('Section') + + absolute_section.short_description = _("Section") def absolute_urlname(self): try: if self.section is None: - return reverse('startpage:post', args=('aktuelles', self.urlname)) + return reverse("startpage:post", args=("aktuelles", self.urlname)) else: - return reverse('startpage:post', args=(self.section.urlname, self.urlname)) + return reverse("startpage:post", args=(self.section.urlname, self.urlname)) except NoReverseMatch: - return _('deactivated') - absolute_urlname.short_description = 'URL' + return _("deactivated") + + absolute_urlname.short_description = "URL" class Image(models.Model): """ An image on a post. """ + post = models.ForeignKey(Post, on_delete=models.CASCADE) # file (not naming it file because of builtin) - f = RestrictedFileField(_('file'), - upload_to='images', - blank=True, - max_upload_size=10) + f = RestrictedFileField(_("file"), upload_to="images", blank=True, max_upload_size=10) def __str__(self): return os.path.basename(self.f.name) if self.f.name else str(_("Empty")) class Meta: - verbose_name = _('image') - verbose_name_plural = _('images') + verbose_name = _("image") + verbose_name_plural = _("images") class MemberOnPost(models.Model): """ One or multiple members on a post. """ - members = models.ManyToManyField(Member, verbose_name=_('Member'), blank=True) - post = models.ForeignKey(Post, verbose_name=_('Member'), on_delete=models.CASCADE, related_name='people') - description = models.TextField(_('Description'), default='', blank=True) - tag = models.CharField(_('Tag'), max_length=20, default='', blank=True) + + members = models.ManyToManyField(Member, verbose_name=_("Member"), blank=True) + post = models.ForeignKey( + Post, verbose_name=_("Member"), on_delete=models.CASCADE, related_name="people" + ) + description = models.TextField(_("Description"), default="", blank=True) + tag = models.CharField(_("Tag"), max_length=20, default="", blank=True) class Meta: verbose_name = _("Person") @@ -114,23 +125,23 @@ class Link(models.Model): Link to external resources that should be shown on the internal startpage. """ - title = models.CharField(_('Title'), max_length=100, default='', blank=True) - description = models.TextField(_('Description'), default='', blank=True) + title = models.CharField(_("Title"), max_length=100, default="", blank=True) + description = models.TextField(_("Description"), default="", blank=True) url = models.URLField(max_length=250) - icon = RestrictedFileField(verbose_name=_('Link Icon'), - upload_to='icons', - blank=True, - max_upload_size=5, - content_types=['image/jpeg', - 'image/png', - 'image/gif']) + icon = RestrictedFileField( + verbose_name=_("Link Icon"), + upload_to="icons", + blank=True, + max_upload_size=5, + content_types=["image/jpeg", "image/png", "image/gif"], + ) - visible = models.BooleanField(verbose_name=_('Visible'), default=True) + visible = models.BooleanField(verbose_name=_("Visible"), default=True) class Meta: - verbose_name = _('Link') - verbose_name_plural = _('Links') + verbose_name = _("Link") + verbose_name_plural = _("Links") def __str__(self): return self.title diff --git a/jdav_web/startpage/tests.py b/jdav_web/startpage/tests.py index eaaa0b2..23a8c3d 100644 --- a/jdav_web/startpage/tests.py +++ b/jdav_web/startpage/tests.py @@ -1,93 +1,137 @@ import os -from django.test import TestCase, Client, RequestFactory -from django.urls import reverse, NoReverseMatch -from django.conf import settings -from django.templatetags.static import static -from django.utils import timezone -from django.utils.translation import gettext_lazy as _ -from django.core.files.uploadedfile import SimpleUploadedFile -from django.template import Template, Context, TemplateSyntaxError, VariableDoesNotExist +from importlib import reload from unittest import mock from unittest.mock import Mock -from importlib import reload -from members.models import Member, Group, DIVERSE +from django.conf import settings +from django.core.files.uploadedfile import SimpleUploadedFile +from django.template import Context +from django.template import TemplateSyntaxError +from django.test import Client +from django.test import RequestFactory +from django.test import TestCase +from django.urls import NoReverseMatch +from django.urls import reverse +from django.utils import timezone +from django.utils.translation import gettext_lazy as _ +from members.models import DIVERSE +from members.models import Group +from members.models import Member from startpage import urls -from startpage.views import redirect, handler500 -from startpage.templatetags.markdown_extras import RenderAsTemplateNode, render_as_template +from startpage.templatetags.markdown_extras import render_as_template +from startpage.templatetags.markdown_extras import RenderAsTemplateNode +from startpage.views import handler500 +from startpage.views import redirect -from .models import Post, Section, Image, Link, MemberOnPost +from .models import Image +from .models import Link +from .models import Post +from .models import Section class BasicTestCase(TestCase): def setUp(self): - orga = Section.objects.create(title='Organisation', urlname='orga', website_text='Section is a about everything.') - recent = Section.objects.create(title='Recent', urlname=settings.RECENT_SECTION, website_text='Recently recent.') - reports = Section.objects.create(title='Reports', urlname=settings.REPORTS_SECTION, website_text='Reporty reports.') - Post.objects.create(title='Climbing is fun', urlname='climbing-is-fun', website_text='Climbing is fun!', - section=recent) - Post.objects.create(title='Last trip', urlname='last-trip', website_text='A fun trip.', - section=reports) + orga = Section.objects.create( + title="Organisation", urlname="orga", website_text="Section is a about everything." + ) + recent = Section.objects.create( + title="Recent", urlname=settings.RECENT_SECTION, website_text="Recently recent." + ) + reports = Section.objects.create( + title="Reports", urlname=settings.REPORTS_SECTION, website_text="Reporty reports." + ) + Post.objects.create( + title="Climbing is fun", + urlname="climbing-is-fun", + website_text="Climbing is fun!", + section=recent, + ) + Post.objects.create( + title="Last trip", urlname="last-trip", website_text="A fun trip.", section=reports + ) file = SimpleUploadedFile("post_image.jpg", b"file_content", content_type="image/jpeg") - staff_post = Post.objects.create(title='Staff', urlname='staff', website_text='This is our staff: Peter.', - section=orga) + staff_post = Post.objects.create( + title="Staff", urlname="staff", website_text="This is our staff: Peter.", section=orga + ) self.image_with_file = Image.objects.create(post=staff_post, f=file) file = SimpleUploadedFile("member_image.jpg", b"file_content", content_type="image/jpeg") - m = Member.objects.create(prename='crazy', lastname='cool', birth_date=timezone.now().date(), - email=settings.TEST_MAIL, gender=DIVERSE, - image=file) - crazy_group = Group.objects.create(name='CrazyClimbers', show_website=True) + m = Member.objects.create( + prename="crazy", + lastname="cool", + birth_date=timezone.now().date(), + email=settings.TEST_MAIL, + gender=DIVERSE, + image=file, + ) + crazy_group = Group.objects.create(name="CrazyClimbers", show_website=True) m.group.add(crazy_group) m.save() - Group.objects.create(name='SuperClimbers', show_website=False) - crazy_post = Post.objects.create(title='The crazy climbers', urlname='crazy', website_text='foobar', - section=orga) + Group.objects.create(name="SuperClimbers", show_website=False) + crazy_post = Post.objects.create( + title="The crazy climbers", urlname="crazy", website_text="foobar", section=orga + ) crazy_post.groups.add(crazy_group) crazy_post.save() - self.post_no_section = Post.objects.create(title='No Section', urlname='no-section', section=None) + self.post_no_section = Post.objects.create( + title="No Section", urlname="no-section", section=None + ) self.image_no_file = Image.objects.create(post=staff_post) - self.test_link = Link.objects.create(title='Test Link', url='https://example.com') + self.test_link = Link.objects.create(title="Test Link", url="https://example.com") class ModelsTestCase(BasicTestCase): def test_str(self): - orga = Section.objects.get(urlname='orga') - self.assertEqual(str(orga), orga.title, 'String representation does not match title.') - post = Post.objects.get(urlname='staff', section=orga) - self.assertEqual(post.absolute_section(), orga.title, 'Displayed section of post does not match section title.') - self.assertEqual(str(post), post.title, 'String representation does not match title.') + orga = Section.objects.get(urlname="orga") + self.assertEqual(str(orga), orga.title, "String representation does not match title.") + post = Post.objects.get(urlname="staff", section=orga) + self.assertEqual( + post.absolute_section(), + orga.title, + "Displayed section of post does not match section title.", + ) + self.assertEqual(str(post), post.title, "String representation does not match title.") def test_absolute_urlnames(self): - orga = Section.objects.get(urlname='orga') + orga = Section.objects.get(urlname="orga") recent = Section.objects.get(urlname=settings.RECENT_SECTION) reports = Section.objects.get(urlname=settings.REPORTS_SECTION) - self.assertEqual(orga.absolute_urlname(), '/de/orga') - - post1 = Post.objects.get(urlname='staff', section=orga) - self.assertEqual(post1.absolute_urlname(), '/de/orga/staff') - self.assertEqual(post1.absolute_urlname(), reverse('startpage:post', args=(orga.urlname, 'staff'))) - post2 = Post.objects.get(urlname='climbing-is-fun', section=recent) - self.assertEqual(post2.absolute_urlname(), - '/de/{name}/climbing-is-fun'.format(name=settings.RECENT_SECTION)) - self.assertEqual(post2.absolute_urlname(), reverse('startpage:post', args=(recent.urlname, 'climbing-is-fun'))) - post3 = Post.objects.get(urlname='last-trip', section=reports) - self.assertEqual(post3.absolute_urlname(), - '/de/{name}/last-trip'.format(name=settings.REPORTS_SECTION)) - self.assertEqual(post3.absolute_urlname(), reverse('startpage:post', args=(reports.urlname, 'last-trip'))) + self.assertEqual(orga.absolute_urlname(), "/de/orga") + + post1 = Post.objects.get(urlname="staff", section=orga) + self.assertEqual(post1.absolute_urlname(), "/de/orga/staff") + self.assertEqual( + post1.absolute_urlname(), reverse("startpage:post", args=(orga.urlname, "staff")) + ) + post2 = Post.objects.get(urlname="climbing-is-fun", section=recent) + self.assertEqual( + post2.absolute_urlname(), + "/de/{name}/climbing-is-fun".format(name=settings.RECENT_SECTION), + ) + self.assertEqual( + post2.absolute_urlname(), + reverse("startpage:post", args=(recent.urlname, "climbing-is-fun")), + ) + post3 = Post.objects.get(urlname="last-trip", section=reports) + self.assertEqual( + post3.absolute_urlname(), "/de/{name}/last-trip".format(name=settings.REPORTS_SECTION) + ) + self.assertEqual( + post3.absolute_urlname(), reverse("startpage:post", args=(reports.urlname, "last-trip")) + ) def test_post_absolute_section_none(self): """Test Post.absolute_section when section is None""" - self.assertEqual(self.post_no_section.absolute_section(), 'Aktuelles') + self.assertEqual(self.post_no_section.absolute_section(), "Aktuelles") def test_post_absolute_urlname_no_section(self): """Test Post.absolute_urlname when section is None""" - expected_url = reverse('startpage:post', args=('aktuelles', 'no-section')) + expected_url = reverse("startpage:post", args=("aktuelles", "no-section")) self.assertEqual(self.post_no_section.absolute_urlname(), expected_url) def test_image_str_without_file(self): """Test Image.__str__ when no file is associated""" - self.assertEqual(str(self.image_no_file), str(_('Empty'))) + self.assertEqual(str(self.image_no_file), str(_("Empty"))) def test_image_str_with_file(self): """Test Image.__str__ when file is associated""" @@ -97,133 +141,135 @@ class ModelsTestCase(BasicTestCase): def test_link_str(self): """Test Link.__str__ method""" - self.assertEqual(str(self.test_link), 'Test Link') + self.assertEqual(str(self.test_link), "Test Link") def test_section_absolute_urlname_no_reverse_match(self): """Test Section.absolute_urlname when NoReverseMatch occurs""" - section = Section.objects.get(urlname='orga') - with mock.patch('startpage.models.reverse', side_effect=NoReverseMatch): - self.assertEqual(section.absolute_urlname(), str(_('deactivated'))) + section = Section.objects.get(urlname="orga") + with mock.patch("startpage.models.reverse", side_effect=NoReverseMatch): + self.assertEqual(section.absolute_urlname(), str(_("deactivated"))) def test_post_absolute_urlname_no_reverse_match(self): """Test Post.absolute_urlname when NoReverseMatch occurs""" - post = Post.objects.get(urlname='staff') - with mock.patch('startpage.models.reverse', side_effect=NoReverseMatch): - self.assertEqual(post.absolute_urlname(), str(_('deactivated'))) + post = Post.objects.get(urlname="staff") + with mock.patch("startpage.models.reverse", side_effect=NoReverseMatch): + self.assertEqual(post.absolute_urlname(), str(_("deactivated"))) class ViewTestCase(BasicTestCase): def test_index(self): c = Client() - url = reverse('startpage:index') + url = reverse("startpage:index") response = c.get(url) - self.assertEqual(response.status_code, 200, 'Response code is not 200 for index.') + self.assertEqual(response.status_code, 200, "Response code is not 200 for index.") def test_posts_no_category(self): c = Client() - url = reverse('startpage:post', args=(settings.RECENT_SECTION, 'climbing-is-fun')) + url = reverse("startpage:post", args=(settings.RECENT_SECTION, "climbing-is-fun")) response = c.get(url) - self.assertEqual(response.status_code, 200, 'Response code is not 200 for climbing post.') + self.assertEqual(response.status_code, 200, "Response code is not 200 for climbing post.") def test_posts_orga(self): c = Client() - url = reverse('startpage:post', args=('orga', 'staff')) + url = reverse("startpage:post", args=("orga", "staff")) response = c.get(url) - self.assertEqual(response.status_code, 200, 'Response code is not 200 for staff post.') + self.assertEqual(response.status_code, 200, "Response code is not 200 for staff post.") def test_section(self): c = Client() - url = reverse('startpage:section', args=('orga',)) + url = reverse("startpage:section", args=("orga",)) response = c.get(url) - self.assertEqual(response.status_code, 200, 'Response code is not 200 for section page.') + self.assertEqual(response.status_code, 200, "Response code is not 200 for section page.") def test_section_recent(self): c = Client() - url = reverse('startpage:' + settings.RECENT_SECTION) + url = reverse("startpage:" + settings.RECENT_SECTION) response = c.get(url) - self.assertEqual(response.status_code, 200, 'Response code is not 200 for section page.') + self.assertEqual(response.status_code, 200, "Response code is not 200 for section page.") def test_section_reports(self): c = Client() - url = reverse('startpage:' + settings.REPORTS_SECTION) + url = reverse("startpage:" + settings.REPORTS_SECTION) response = c.get(url) - self.assertEqual(response.status_code, 200, 'Response code is not 200 for section page.') + self.assertEqual(response.status_code, 200, "Response code is not 200 for section page.") def test_404(self): c = Client() - response = c.get('/de/asdfasdfasdf') - self.assertEqual(response.status_code, 404, 'Response code is not 404 when page not found.') + response = c.get("/de/asdfasdfasdf") + self.assertEqual(response.status_code, 404, "Response code is not 404 when page not found.") def test_impressum(self): c = Client() - response = c.get('/de/impressum') - self.assertEqual(response.status_code, 200, 'Response code is not 200 for impressum.') + response = c.get("/de/impressum") + self.assertEqual(response.status_code, 200, "Response code is not 200 for impressum.") def test_gruppen(self): c = Client() - url = reverse('startpage:gruppe_detail', args=('CrazyClimbers',)) + url = reverse("startpage:gruppe_detail", args=("CrazyClimbers",)) response = c.get(url) - self.assertEqual(response.status_code, 200, 'Response code is not 200 for group.') + self.assertEqual(response.status_code, 200, "Response code is not 200 for group.") def test_gruppen_404(self): c = Client() - url = reverse('startpage:gruppe_detail', args=('SuperClimbers',)) + url = reverse("startpage:gruppe_detail", args=("SuperClimbers",)) response = c.get(url) - self.assertEqual(response.status_code, 404, 'Response code is not 404 for group.') - url = reverse('startpage:gruppe_detail', args=('SuperClimbersNotExisting',)) + self.assertEqual(response.status_code, 404, "Response code is not 404 for group.") + url = reverse("startpage:gruppe_detail", args=("SuperClimbersNotExisting",)) response = c.get(url) - self.assertEqual(response.status_code, 404, 'Response code is not 404 for group.') + self.assertEqual(response.status_code, 404, "Response code is not 404 for group.") def test_post_with_groups(self): c = Client() - url = reverse('startpage:post', args=('orga', 'crazy')) + url = reverse("startpage:post", args=("orga", "crazy")) response = c.get(url) self.assertEqual(response.status_code, 200) def test_post_image(self): c = Client() url = self.image_with_file.f.url - response = c.get('/de' + url) - self.assertEqual(response.status_code, 200, 'Images on posts should be visible without login.') + response = c.get("/de" + url) + self.assertEqual( + response.status_code, 200, "Images on posts should be visible without login." + ) def test_urlpatterns_with_redirect_url(self): """Test URL patterns when STARTPAGE_REDIRECT_URL is not empty""" # Mock settings to have a non-empty STARTPAGE_REDIRECT_URL - with mock.patch.object(settings, 'STARTPAGE_REDIRECT_URL', 'https://example.com'): + with mock.patch.object(settings, "STARTPAGE_REDIRECT_URL", "https://example.com"): # Reload the urls module to trigger the conditional urlpatterns creation reload(urls) # Check that urlpatterns contains the redirect view - url_names = [pattern.name for pattern in urls.urlpatterns if hasattr(pattern, 'name')] - self.assertIn('index', url_names) + url_names = [pattern.name for pattern in urls.urlpatterns if hasattr(pattern, "name")] + self.assertIn("index", url_names) self.assertEqual(len(urls.urlpatterns), 2) # Should have index and impressum only def test_redirect_view(self): """Test redirect view functionality""" - request = RequestFactory().get('/') - with mock.patch.object(settings, 'STARTPAGE_REDIRECT_URL', 'https://example.com'): + request = RequestFactory().get("/") + with mock.patch.object(settings, "STARTPAGE_REDIRECT_URL", "https://example.com"): response = redirect(request) self.assertEqual(response.status_code, 302) - self.assertEqual(response.url, 'https://example.com') + self.assertEqual(response.url, "https://example.com") def test_handler500(self): """Test custom 500 error handler""" - request = RequestFactory().get('/') + request = RequestFactory().get("/") response = handler500(request) self.assertEqual(response.status_code, 500) class MarkdownExtrasTestCase(TestCase): def test_render_as_template_node_variable_does_not_exist(self): - node = RenderAsTemplateNode('nonexistent_var', 'result') + node = RenderAsTemplateNode("nonexistent_var", "result") context = Context({}) result = node.render(context) - self.assertEqual(result, '') + self.assertEqual(result, "") def test_render_as_template_no_arguments(self): token = Mock() - token.contents = 'render_as_template' + token.contents = "render_as_template" parser = Mock() with self.assertRaises(TemplateSyntaxError): render_as_template(parser, token) @@ -237,7 +283,7 @@ class MarkdownExtrasTestCase(TestCase): def test_render_as_template_unquoted_argument(self): token = Mock() - token.contents = 'render_as_template content as result' + token.contents = "render_as_template content as result" parser = Mock() with self.assertRaises(TemplateSyntaxError): render_as_template(parser, token) diff --git a/jdav_web/startpage/urls.py b/jdav_web/startpage/urls.py index 56d1eeb..9a58537 100644 --- a/jdav_web/startpage/urls.py +++ b/jdav_web/startpage/urls.py @@ -5,23 +5,36 @@ from . import views app_name = "startpage" -if settings.STARTPAGE_REDIRECT_URL != '': +if settings.STARTPAGE_REDIRECT_URL != "": urlpatterns = [ - re_path(r'^$', views.redirect, name='index'), - re_path(r'^impressum/?$', views.static_view('startpage/impressum.html'), name='impressum'), + re_path(r"^$", views.redirect, name="index"), + re_path(r"^impressum/?$", views.static_view("startpage/impressum.html"), name="impressum"), ] else: urlpatterns = [ - re_path(r'^$', views.index, name='index'), - re_path(r'^impressum/?$', views.static_view('startpage/impressum.html'), name='impressum'), - re_path(r'^aktuelles/?$', views.aktuelles, name='aktuelles'), - re_path(r'^berichte/?$', views.berichte, name='berichte'), - re_path(r'^gruppen/?$', views.static_view('startpage/gruppen.html'), name='gruppen'), - re_path(r'^gruppen/faq/?$', views.static_view('startpage/gruppen/faq.html'), name='faq'), - re_path(r'^gruppen/(?P{pattern}+)/?$'.format(pattern=settings.STARTPAGE_URL_NAME_PATTERN), - views.gruppe_detail, name='gruppe_detail'), - re_path(r'^(?P{pattern}+)/(?P{pattern}+)/?$'.format(pattern=settings.STARTPAGE_URL_NAME_PATTERN), - views.post, name='post'), - re_path(r'^(?P{pattern}+)/?$'.format(pattern=settings.STARTPAGE_URL_NAME_PATTERN), - views.section, name='section'), + re_path(r"^$", views.index, name="index"), + re_path(r"^impressum/?$", views.static_view("startpage/impressum.html"), name="impressum"), + re_path(r"^aktuelles/?$", views.aktuelles, name="aktuelles"), + re_path(r"^berichte/?$", views.berichte, name="berichte"), + re_path(r"^gruppen/?$", views.static_view("startpage/gruppen.html"), name="gruppen"), + re_path(r"^gruppen/faq/?$", views.static_view("startpage/gruppen/faq.html"), name="faq"), + re_path( + r"^gruppen/(?P{pattern}+)/?$".format( + pattern=settings.STARTPAGE_URL_NAME_PATTERN + ), + views.gruppe_detail, + name="gruppe_detail", + ), + re_path( + r"^(?P{pattern}+)/(?P{pattern}+)/?$".format( + pattern=settings.STARTPAGE_URL_NAME_PATTERN + ), + views.post, + name="post", + ), + re_path( + r"^(?P{pattern}+)/?$".format(pattern=settings.STARTPAGE_URL_NAME_PATTERN), + views.section, + name="section", + ), ] diff --git a/jdav_web/startpage/views.py b/jdav_web/startpage/views.py index 780ae44..8fa3528 100644 --- a/jdav_web/startpage/views.py +++ b/jdav_web/startpage/views.py @@ -1,20 +1,20 @@ -from django.shortcuts import redirect as django_redirect, get_object_or_404 from django import shortcuts from django.conf import settings -from django.urls import reverse -from django.http import HttpResponseNotFound, Http404 -from itertools import chain - +from django.http import Http404 +from django.shortcuts import get_object_or_404 +from django.shortcuts import redirect as django_redirect from members.models import Group -from .models import Post, Section + +from .models import Post +from .models import Section # render shortcut adding additional context variables, needed for navbar def render(request, template_path, context={}): - context['groups'] = Group.objects.filter(show_website=True).order_by('name') - context['sections'] = Section.objects.all() + context["groups"] = Group.objects.filter(show_website=True).order_by("name") + context["sections"] = Section.objects.all() try: - context['root_section'] = Section.objects.get(urlname=settings.ROOT_SECTION) + context["root_section"] = Section.objects.get(urlname=settings.ROOT_SECTION) except Section.DoesNotExist: pass return shortcuts.render(request, template_path, context) @@ -22,10 +22,12 @@ def render(request, template_path, context={}): def index(request): context = { - 'recent_posts': Post.objects.filter(section__urlname=settings.RECENT_SECTION).order_by('-date'), - 'reports': Post.objects.filter(section__urlname=settings.REPORTS_SECTION).order_by('-date'), + "recent_posts": Post.objects.filter(section__urlname=settings.RECENT_SECTION).order_by( + "-date" + ), + "reports": Post.objects.filter(section__urlname=settings.REPORTS_SECTION).order_by("-date"), } - return render(request, 'startpage/index.html', context) + return render(request, "startpage/index.html", context) def redirect(request): @@ -36,6 +38,7 @@ def redirect(request): def static_view(template_path): def view(request): return render(request, template_path) + return view @@ -48,58 +51,58 @@ def gruppe_detail(request, group_name): raise Http404 context = { - 'group': group, - 'people': group.leiters.all(), + "group": group, + "people": group.leiters.all(), } - return render(request, 'startpage/gruppen/detail.html', context) + return render(request, "startpage/gruppen/detail.html", context) def aktuelles(request): section = get_object_or_404(Section, urlname=settings.RECENT_SECTION) posts = Post.objects.filter(section=section) context = { - 'posts': posts, + "posts": posts, } - return render(request, 'startpage/aktuelles.html', context) + return render(request, "startpage/aktuelles.html", context) def berichte(request): section = get_object_or_404(Section, urlname=settings.REPORTS_SECTION) posts = Post.objects.filter(section=section) context = { - 'posts': posts, + "posts": posts, } - return render(request, 'startpage/berichte.html', context) + return render(request, "startpage/berichte.html", context) def post(request, section_name, post_name): section = get_object_or_404(Section, urlname=section_name) post = get_object_or_404(Post, section=section, urlname=post_name) context = { - 'post': post, - 'section': section, - 'people': [m for group in post.groups.all() for m in group.member_set.all()], + "post": post, + "section": section, + "people": [m for group in post.groups.all() for m in group.member_set.all()], } - return render(request, 'startpage/post.html', context) + return render(request, "startpage/post.html", context) def section(request, section_name): - assert section_name != 'aktuelles' - assert section_name != 'berichte' + assert section_name != "aktuelles" + assert section_name != "berichte" section = get_object_or_404(Section, urlname=section_name) context = { - 'section': section, + "section": section, } - return render(request, 'startpage/section.html', context) + return render(request, "startpage/section.html", context) def handler404(request, exception): - response = render(request, 'startpage/404.html') + response = render(request, "startpage/404.html") response.status_code = 404 return response def handler500(request): - response = render(request, 'startpage/500.html') + response = render(request, "startpage/500.html") response.status_code = 500 return response