Blackify everything

main
Jaap Joris Vens 2021-07-04 01:59:48 +02:00
rodzic cd8151b2ce
commit 98de86f49d
19 zmienionych plików z 441 dodań i 327 usunięć

Wyświetl plik

@ -1,2 +1,2 @@
__version__ = "1.0.5"
__version__ = "1.0.6"
default_app_config = "cms.apps.CmsConfig"

Wyświetl plik

@ -1,58 +1,85 @@
import os, re, argparse, shutil, example, cms
import argparse
import os
import re
import shutil
from pip._internal.operations import freeze as pip
import cms
import example
def main():
parser = argparse.ArgumentParser(description='SimpleCMS')
parser.add_argument('project_name', nargs='?', default='.')
parser = argparse.ArgumentParser(description="SimpleCMS")
parser.add_argument("project_name", nargs="?", default=".")
project_name = parser.parse_args().project_name
if project_name == '.':
if project_name == ".":
project_dir = os.getcwd()
project_name = os.path.basename(project_dir)
else:
project_dir = os.path.join(os.getcwd(), project_name)
if re.match(r'^\w+$', project_name):
if input(f'Do you want to create a new project in `{project_dir}` ?\033[1D') in 'Yy':
if re.match(r"^\w+$", project_name):
if (
input(f"Do you want to create a new project in `{project_dir}` ?\033[1D")
in "Yy"
):
create_project(project_name, project_dir)
else:
print(f'Invalid project name: {project_name}')
print(f"Invalid project name: {project_name}")
def create_project(project_name, project_dir):
os.makedirs(project_dir, exist_ok=True)
with open(os.path.join(project_dir, 'requirements.txt'), 'w') as f:
with open(os.path.join(project_dir, "requirements.txt"), "w") as f:
for line in pip.freeze():
if 'django_simplecms' in line:
line = f'django-simplecms=={cms.__version__}'
if "django_simplecms" in line:
line = f"django-simplecms=={cms.__version__}"
print(line, file=f)
shutil.copytree(os.path.dirname(example.__file__),os.path.join(project_dir, project_name), dirs_exist_ok=True)
with open(os.open(os.path.join(project_dir, 'manage.py'), os.O_CREAT|os.O_WRONLY, 0o755), 'w') as f:
print('#!/usr/bin/env python',
'import os, sys',
f"os.environ.setdefault('DJANGO_SETTINGS_MODULE', '{project_name}.settings')",
'from django.core.management import execute_from_command_line',
'execute_from_command_line(sys.argv)',
sep='\n', file=f)
with open(os.path.join(project_dir, project_name, 'wsgi.py'), 'w') as f:
print('import os',
'from django.core.wsgi import get_wsgi_application',
f"os.environ.setdefault('DJANGO_SETTINGS_MODULE', '{project_name}.settings')",
'application = get_wsgi_application()',
sep='\n', file=f)
with open(os.path.join(project_dir, '.gitignore'), 'w') as f:
print('*.pyc\n__pycache__/', file=f)
shutil.copytree(
os.path.dirname(example.__file__),
os.path.join(project_dir, project_name),
dirs_exist_ok=True,
)
with open(
os.open(
os.path.join(project_dir, "manage.py"), os.O_CREAT | os.O_WRONLY, 0o755
),
"w",
) as f:
print(
"#!/usr/bin/env python",
"import os, sys",
f"os.environ.setdefault('DJANGO_SETTINGS_MODULE', '{project_name}.settings')",
"from django.core.management import execute_from_command_line",
"execute_from_command_line(sys.argv)",
sep="\n",
file=f,
)
with open(os.path.join(project_dir, project_name, "wsgi.py"), "w") as f:
print(
"import os",
"from django.core.wsgi import get_wsgi_application",
f"os.environ.setdefault('DJANGO_SETTINGS_MODULE', '{project_name}.settings')",
"application = get_wsgi_application()",
sep="\n",
file=f,
)
with open(os.path.join(project_dir, ".gitignore"), "w") as f:
print("*.pyc\n__pycache__/", file=f)
print(f'Successfully created project "{project_name}"',
'',
'Things to do next:',
'- create a database',
'- ./manage.py makemigrations',
'- ./manage.py migrate',
'- ./manage.py createsuperuser',
'- ./manage.py runserver',
sep='\n')
print(
f'Successfully created project "{project_name}"',
"",
"Things to do next:",
"- create a database",
"- ./manage.py makemigrations",
"- ./manage.py migrate",
"- ./manage.py createsuperuser",
"- ./manage.py runserver",
sep="\n",
)
if __name__ == '__main__':
if __name__ == "__main__":
main()

Wyświetl plik

@ -1,10 +1,11 @@
from django.apps import AppConfig
from django.utils.translation import gettext_lazy as _
from django.utils.module_loading import autodiscover_modules
from django.utils.translation import gettext_lazy as _
class CmsConfig(AppConfig):
name = 'cms'
verbose_name = _('Content Management System')
name = "cms"
verbose_name = _("Content Management System")
def ready(self):
autodiscover_modules('views')
autodiscover_modules("views")

Wyświetl plik

@ -1,17 +1,20 @@
from cms import registry
def page_model(cls):
'''Decorator to register the Page model'''
"""Decorator to register the Page model"""
registry.page_class = cls
return cls
def section_model(cls):
'''Decorator to register the Section model'''
"""Decorator to register the Section model"""
registry.section_class = cls
return cls
def section_view(cls):
'''Decorator to register a view for a specific section'''
"""Decorator to register a view for a specific section"""
registry.view_per_type[cls.__name__.lower()] = cls
registry.section_types.append((cls.__name__.lower(), cls.verbose_name))
return cls

Wyświetl plik

@ -1,27 +1,28 @@
from django import forms
from django.conf import settings
from django.db.models import Prefetch
from django.contrib.contenttypes.models import ContentType
from django.core.mail import EmailMessage
from django.utils.translation import gettext_lazy as _
from . import registry
class PageForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.label_suffix = ''
self.label_suffix = ""
self.formsets = [forms.inlineformset_factory(
parent_model=registry.page_class,
model=registry.section_class,
form=SectionForm,
extra=1,
)(
data=self.data if self.is_bound else None,
files=self.files if self.is_bound else None,
instance=self.instance,
)]
self.formsets = [
forms.inlineformset_factory(
parent_model=registry.page_class,
model=registry.section_class,
form=SectionForm,
extra=1,
)(
data=self.data if self.is_bound else None,
files=self.files if self.is_bound else None,
instance=self.instance,
)
]
self.formsets[0][0].empty_permitted = True
def is_valid(self):
@ -44,17 +45,18 @@ class PageForm(forms.ModelForm):
class Meta:
model = registry.page_class
fields = '__all__'
fields = "__all__"
class SectionForm(forms.ModelForm):
type = forms.ChoiceField()
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.label_suffix = ''
self.fields['DELETE'] = forms.BooleanField(label=_('Delete'), required=False)
self.fields['type'].choices = registry.get_types()
self.fields['type'].initial = registry.get_types()[0][0]
self.label_suffix = ""
self.fields["DELETE"] = forms.BooleanField(label=_("Delete"), required=False)
self.fields["type"].choices = registry.get_types()
self.fields["type"].initial = registry.get_types()[0][0]
# Populate the 'formsets' attribute if the Section was
# extendend with one_to_many fields
@ -64,14 +66,14 @@ class SectionForm(forms.ModelForm):
formset = forms.inlineformset_factory(
parent_model=registry.section_class,
model=field.related_model,
fields='__all__',
fields="__all__",
extra=1,
)(
instance=self.instance,
data=self.data if self.is_bound else None,
files=self.files if self.is_bound else None,
prefix=f'{self.prefix}-{field.name}',
form_kwargs={'label_suffix': self.label_suffix},
prefix=f"{self.prefix}-{field.name}",
form_kwargs={"label_suffix": self.label_suffix},
)
formset.name = field.name
self.formsets.append(formset)
@ -79,19 +81,19 @@ class SectionForm(forms.ModelForm):
def is_valid(self):
result = super().is_valid()
for formset in self.formsets:
result = result and formset.is_valid() # AND
result = result and formset.is_valid() # AND
return result
def has_changed(self):
result = super().has_changed()
for formset in self.formsets:
result = result or formset.has_changed() # OR
result = result or formset.has_changed() # OR
return result
def save(self, commit=True):
section = super().save(commit=commit)
if self.cleaned_data['DELETE']:
if self.cleaned_data["DELETE"]:
section.delete()
if section.page.slug and not section.page.sections.exists():
section.page.delete()
@ -106,25 +108,28 @@ class SectionForm(forms.ModelForm):
class Meta:
model = registry.section_class
exclude = ['page']
exclude = ["page"]
class ContactForm(forms.Form):
sender = forms.EmailField(label=_('Your email address'))
spam_protection = forms.CharField(label=_('Your message'), widget=forms.Textarea())
message = forms.CharField(label=_('Your message'), widget=forms.Textarea(), initial='Hi there!')
sender = forms.EmailField(label=_("Your email address"))
spam_protection = forms.CharField(label=_("Your message"), widget=forms.Textarea())
message = forms.CharField(
label=_("Your message"), widget=forms.Textarea(), initial="Hi there!"
)
def save(self):
body = self.cleaned_data.get('spam_protection')
body = self.cleaned_data.get("spam_protection")
if len(body.split()) < 7:
return
spamcheck = self.cleaned_data.get('message')
if spamcheck != 'Hi there!':
spamcheck = self.cleaned_data.get("message")
if spamcheck != "Hi there!":
return
email = EmailMessage(
to = settings.DEFAULT_TO_EMAIL,
body = body,
subject = _('Contact form'),
headers = {'Reply-To': self.cleaned_data.get('sender')},
to=settings.DEFAULT_TO_EMAIL,
body=body,
subject=_("Contact form"),
headers={"Reply-To": self.cleaned_data.get("sender")},
)
email.send()

Wyświetl plik

@ -1,7 +1,9 @@
import os
from sass import compile
from django.conf import settings
from django.middleware import cache
from sass import compile
def locate(filename):
for path, dirs, files in os.walk(os.getcwd(), followlinks=True):
@ -9,38 +11,44 @@ def locate(filename):
if f == filename:
yield os.path.join(path, filename)
class FetchFromCacheMiddleware(cache.FetchFromCacheMiddleware):
'''Minor change to the original middleware that prevents caching of
"""Minor change to the original middleware that prevents caching of
requests that have a `sessionid` cookie. This should be the
Django default, IMHO.
'''
"""
def process_request(self, request):
if 'sessionid' not in request.COOKIES:
if "sessionid" not in request.COOKIES:
return super().process_request(request)
class SassMiddleware:
'''Simple SASS middleware that intercepts requests for .css files and
"""Simple SASS middleware that intercepts requests for .css files and
tries to compile the corresponding SCSS file.
'''
"""
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
if settings.DEBUG and request.path.endswith('.css'):
css_file = request.path.rsplit('/',1)[1]
if settings.DEBUG and request.path.endswith(".css"):
css_file = request.path.rsplit("/", 1)[1]
sass_file = css_file[:-4]
sass_paths = locate(sass_file)
for sass_path in list(sass_paths):
if os.path.exists(sass_path):
css_path = sass_path + '.css'
map_path = css_path + '.map'
css = compile(filename=sass_path, output_style='nested')
css, mapping = compile(filename=sass_path, source_map_filename=map_path)
with open(css_path, 'w') as f:
css_path = sass_path + ".css"
map_path = css_path + ".map"
css = compile(filename=sass_path, output_style="nested")
css, mapping = compile(
filename=sass_path, source_map_filename=map_path
)
with open(css_path, "w") as f:
f.write(css)
with open(map_path, 'w') as f:
with open(map_path, "w") as f:
f.write(mapping)
response = self.get_response(request)

Wyświetl plik

@ -10,6 +10,8 @@ from . import fields, mixins
class Model(models.Model):
"""Felt cute, might delete later."""
id = models.BigAutoField(primary_key=True)
class Meta:
abstract = True

Wyświetl plik

@ -3,15 +3,17 @@ section_class = None
section_types = []
view_per_type = {}
def get_types():
return section_types
def get_view(section, request):
return view_per_type[section.type](request)
def get_fields_per_type():
fields_per_type = {}
for name, view in view_per_type.items():
fields_per_type[name] = ['title', 'type', 'number'] + view.fields
fields_per_type[name] = ["title", "type", "number"] + view.fields
return fields_per_type

Wyświetl plik

@ -1,18 +1,17 @@
from markdown import markdown as md
from django import template
from django.shortcuts import reverse
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _
from markdown import markdown as md
from cms import registry
MARKDOWN_EXTENSIONS = ['extra', 'smarty']
MARKDOWN_EXTENSIONS = ["extra", "smarty"]
register = template.Library()
@register.simple_tag(takes_context=True)
def eval(context, expr):
'''USE WITH CAUTION!!!
"""USE WITH CAUTION!!!
This template tag runs its argument through Django's templating
system using the current context, placing all power into the
@ -20,49 +19,61 @@ def eval(context, expr):
Also, it applies Markdown.
'''
"""
result = template.Template(expr).render(context)
return mark_safe(md(result, extensions=MARKDOWN_EXTENSIONS))
@register.simple_tag(takes_context=True)
def editsection(context, inner):
'''Renders a simple link to edit the current section'''
section = context['section']
user = context['request'].user
"""Renders a simple link to edit the current section"""
section = context["section"]
user = context["request"].user
app_label = section._meta.app_label
model_name = section._meta.model_name
if user.has_perm(f'{app_label}.change_{model_name}'):
if user.has_perm(f"{app_label}.change_{model_name}"):
slug = section.page.slug
number = section.number
url = reverse('cms:updatesection', args=[slug, number]) if slug else reverse('cms:updatesection', args=[number])
url = (
reverse("cms:updatesection", args=[slug, number])
if slug
else reverse("cms:updatesection", args=[number])
)
return mark_safe(f'<a class="edit section" href="{url}">{inner}</a>')
return ''
return ""
@register.simple_tag(takes_context=True)
def editpage(context, inner):
'''Renders a simple link to edit the current page'''
page = context['page']
user = context['request'].user
"""Renders a simple link to edit the current page"""
page = context["page"]
user = context["request"].user
app_label = page._meta.app_label
model_name = page._meta.model_name
if user.has_perm(f'{app_label}.change_{model_name}'):
if user.has_perm(f"{app_label}.change_{model_name}"):
slug = page.slug
url = reverse('cms:updatepage', args=[slug]) if slug else reverse('cms:updatepage')
url = (
reverse("cms:updatepage", args=[slug])
if slug
else reverse("cms:updatepage")
)
return mark_safe(f'<a class="edit page" href="{url}">{inner}</a>')
return ''
return ""
@register.tag('include_section')
@register.tag("include_section")
def do_include(parser, token):
'''Renders the section with its own context'''
"""Renders the section with its own context"""
_, section = token.split_contents()
return IncludeSectionNode(section)
class IncludeSectionNode(template.Node):
def __init__(self, section):
self.section = template.Variable(section)
self.csrf_token = template.Variable('csrf_token')
self.request = template.Variable('request')
self.perms = template.Variable('perms')
self.csrf_token = template.Variable("csrf_token")
self.request = template.Variable("request")
self.perms = template.Variable("perms")
super().__init__()
def render(self, context):
@ -73,13 +84,13 @@ class IncludeSectionNode(template.Node):
view = registry.get_view(section, request)
initial_context = {
'csrf_token': csrf_token,
'section': section,
'request': request,
'perms': perms,
"csrf_token": csrf_token,
"section": section,
"request": request,
"perms": perms,
}
if hasattr(section, 'invalid_form'):
initial_context['form'] = section.invalid_form
if hasattr(section, "invalid_form"):
initial_context["form"] = section.invalid_form
section_context = view.get_context_data(**initial_context)
t = context.template.engine.get_template(view.template_name)

Wyświetl plik

@ -1,15 +1,23 @@
from django.urls import path
from .views import PageView, CreatePage, UpdatePage, CreateSection, UpdateSection
app_name = 'cms'
from .views import CreatePage, CreateSection, PageView, UpdatePage, UpdateSection
app_name = "cms"
urlpatterns = [
path('new/', CreatePage.as_view(), name='createpage'),
path('edit/', UpdatePage.as_view(), kwargs={'slug': ''}, name='updatepage'),
path('edit/<int:number>/', UpdateSection.as_view(), kwargs={'slug': ''}, name='updatesection'),
path('<slug:slug>/edit/', UpdatePage.as_view(), name='updatepage'),
path('<slug:slug>/edit/new/', CreateSection.as_view(), name='createsection'),
path('<slug:slug>/edit/<int:number>/', UpdateSection.as_view(), name='updatesection'),
path('', PageView.as_view(), name='page'),
path('<slug:slug>/', PageView.as_view(), name='page'),
path("new/", CreatePage.as_view(), name="createpage"),
path("edit/", UpdatePage.as_view(), kwargs={"slug": ""}, name="updatepage"),
path(
"edit/<int:number>/",
UpdateSection.as_view(),
kwargs={"slug": ""},
name="updatesection",
),
path("<slug:slug>/edit/", UpdatePage.as_view(), name="updatepage"),
path("<slug:slug>/edit/new/", CreateSection.as_view(), name="createsection"),
path(
"<slug:slug>/edit/<int:number>/", UpdateSection.as_view(), name="updatesection"
),
path("", PageView.as_view(), name="page"),
path("<slug:slug>/", PageView.as_view(), name="page"),
]

Wyświetl plik

@ -1,18 +1,20 @@
import json
from django.contrib.auth.mixins import UserPassesTestMixin
from django.http import Http404, HttpResponseBadRequest, HttpResponseRedirect
from django.shortcuts import redirect
from django.views.generic import base, detail, edit
from django.utils.decorators import method_decorator
from django.views.decorators.cache import never_cache
from django.contrib.auth.mixins import UserPassesTestMixin
from django.http import Http404, HttpResponse, HttpResponseRedirect, HttpResponseBadRequest
from django.views.generic import base, detail, edit
from . import registry
from .forms import PageForm, SectionForm
class SectionView:
'''Generic section view'''
template_name = 'cms/sections/section.html'
"""Generic section view"""
template_name = "cms/sections/section.html"
def __init__(self, request):
self.request = request
@ -20,14 +22,16 @@ class SectionView:
def get_context_data(self, **kwargs):
return kwargs
class SectionFormView(SectionView):
'''Generic section with associated form'''
"""Generic section with associated form"""
form_class = None
success_url = None
def get_context_data(self, **kwargs):
if 'form' not in kwargs:
kwargs['form'] = self.get_form()
if "form" not in kwargs:
kwargs["form"] = self.get_form()
return kwargs
def form_valid(self, form):
@ -37,56 +41,62 @@ class SectionFormView(SectionView):
def get_form_kwargs(self):
return {}
def get_form(self, method='get'):
def get_form(self, method="get"):
form_class = self.form_class
kwargs = self.get_form_kwargs()
if method == 'post':
kwargs.update({
'data': self.request.POST,
'files': self.request.FILES,
})
if method == "post":
kwargs.update(
{
"data": self.request.POST,
"files": self.request.FILES,
}
)
return form_class(**kwargs)
class PageView(detail.DetailView):
'''View of a page with heterogeneous sections'''
model = registry.page_class
template_name = 'cms/page.html'
def setup(self, *args, slug='', **kwargs):
'''Supply a default argument for slug'''
class PageView(detail.DetailView):
"""View of a page with heterogeneous sections"""
model = registry.page_class
template_name = "cms/page.html"
def setup(self, *args, slug="", **kwargs):
"""Supply a default argument for slug"""
super().setup(*args, slug=slug, **kwargs)
def get(self, request, *args, **kwargs):
'''Instantiate section views and render final response'''
"""Instantiate section views and render final response"""
try:
page = self.object = self.get_object()
except Http404:
app_label = registry.page_class._meta.app_label
model_name = registry.page_class._meta.model_name
if self.kwargs['slug'] == '':
page = registry.page_class(title='Homepage', slug='')
if self.kwargs["slug"] == "":
page = registry.page_class(title="Homepage", slug="")
page.save()
self.object = page
# Special case: Don't serve 404 pages to authorized users,
# but redirect to the edit page form with the slug pre-filled
elif (self.request.user.has_perm(f'{app_label}.change_{model_name}')):
return redirect('cms:updatepage', slug=self.kwargs['slug'])
elif self.request.user.has_perm(f"{app_label}.change_{model_name}"):
return redirect("cms:updatepage", slug=self.kwargs["slug"])
else:
raise
context = self.get_context_data(**kwargs)
sections = page.sections.all()
context.update({
'page': page,
'sections': sections,
})
context.update(
{
"page": page,
"sections": sections,
}
)
return self.render_to_response(context)
def post(self, request, **kwargs):
'''Call the post() method of the correct section view'''
"""Call the post() method of the correct section view"""
try:
pk = int(self.request.POST.get('section'))
except:
pk = int(self.request.POST.get("section"))
except Exception:
return HttpResponseBadRequest()
page = self.object = self.get_object()
@ -95,65 +105,73 @@ class PageView(detail.DetailView):
for section in sections:
if section.pk == pk:
view = registry.get_view(section, request)
form = view.get_form(method='post')
form = view.get_form(method="post")
if form.is_valid():
return view.form_valid(form)
section.invalid_form = form
context.update({
'page': page,
'sections': sections,
})
context.update(
{
"page": page,
"sections": sections,
}
)
return self.render_to_response(context)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
pages = registry.page_class.objects.filter(menu=True)
context.update({
'pages': pages,
})
context.update(
{
"pages": pages,
}
)
return context
@method_decorator(never_cache, name='dispatch')
class EditPage(UserPassesTestMixin, edit.ModelFormMixin, base.TemplateResponseMixin, base.View):
'''Base view with nested forms for editing the page and all its sections'''
@method_decorator(never_cache, name="dispatch")
class EditPage(
UserPassesTestMixin, edit.ModelFormMixin, base.TemplateResponseMixin, base.View
):
"""Base view with nested forms for editing the page and all its sections"""
model = registry.page_class
form_class = PageForm
template_name = 'cms/edit.html'
template_name = "cms/edit.html"
def test_func(self):
'''Only allow users with the correct permissions'''
"""Only allow users with the correct permissions"""
app_label = registry.page_class._meta.app_label
model_name = registry.page_class._meta.model_name
return self.request.user.has_perm(f'{app_label}.change_{model_name}')
return self.request.user.has_perm(f"{app_label}.change_{model_name}")
def get_form_kwargs(self):
'''Set the default slug to the current URL for new pages'''
"""Set the default slug to the current URL for new pages"""
kwargs = super().get_form_kwargs()
if 'slug' in self.kwargs:
kwargs.update({'initial': {'slug': self.kwargs['slug']}})
if "slug" in self.kwargs:
kwargs.update({"initial": {"slug": self.kwargs["slug"]}})
return kwargs
def get_context_data(self, **kwargs):
'''Populate the fields_per_type dict for use in javascript'''
"""Populate the fields_per_type dict for use in javascript"""
context = super().get_context_data(**kwargs)
context['fields_per_type'] = json.dumps(registry.get_fields_per_type())
context["fields_per_type"] = json.dumps(registry.get_fields_per_type())
return context
def get_object(self):
'''Prevent 404 by serving the new object form'''
"""Prevent 404 by serving the new object form"""
try:
return super().get_object()
except Http404:
return None
def get(self, *args, **kwargs):
'''Handle GET requests'''
"""Handle GET requests"""
self.object = self.get_object()
return self.render_to_response(self.get_context_data(**kwargs))
def post(self, *args, **kwargs):
'''Handle POST requests'''
"""Handle POST requests"""
self.object = self.get_object()
form = self.get_form()
@ -161,51 +179,59 @@ class EditPage(UserPassesTestMixin, edit.ModelFormMixin, base.TemplateResponseMi
page = form.save()
if page:
return HttpResponseRedirect(page.get_absolute_url())
return HttpResponseRedirect('/')
return HttpResponseRedirect("/")
return self.render_to_response(self.get_context_data(form=form, **kwargs))
class CreatePage(EditPage):
'''View for creating new pages'''
"""View for creating new pages"""
def get_object(self):
return registry.page_class()
class UpdatePage(EditPage):
'''View for editing existing pages'''
@method_decorator(never_cache, name='dispatch')
class EditSection(UserPassesTestMixin, edit.ModelFormMixin, base.TemplateResponseMixin, base.View):
class UpdatePage(EditPage):
"""View for editing existing pages"""
@method_decorator(never_cache, name="dispatch")
class EditSection(
UserPassesTestMixin, edit.ModelFormMixin, base.TemplateResponseMixin, base.View
):
model = registry.section_class
form_class = SectionForm
template_name = 'cms/edit.html'
template_name = "cms/edit.html"
def test_func(self):
'''Only allow users with the correct permissions'''
"""Only allow users with the correct permissions"""
app_label = registry.section_class._meta.app_label
model_name = registry.section_class._meta.model_name
return self.request.user.has_perm(f'{app_label}.change_{model_name}')
return self.request.user.has_perm(f"{app_label}.change_{model_name}")
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs.update({
'prefix': 'section',
})
kwargs.update(
{
"prefix": "section",
}
)
return kwargs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['fields_per_type'] = json.dumps(registry.get_fields_per_type())
context["fields_per_type"] = json.dumps(registry.get_fields_per_type())
return context
def get_object(self, queryset=None):
try:
self.page = registry.page_class.objects.get(slug=self.kwargs['slug'])
self.page = registry.page_class.objects.get(slug=self.kwargs["slug"])
except registry.page_class.DoesNotExist:
raise Http404()
return self.get_section()
def get_section(self):
try:
section = self.page.sections.get(number=self.kwargs['number'])
section = self.page.sections.get(number=self.kwargs["number"])
except self.page.sections.DoesNotExist:
raise Http404()
return section
@ -225,12 +251,14 @@ class EditSection(UserPassesTestMixin, edit.ModelFormMixin, base.TemplateRespons
elif self.page.sections.exists():
return HttpResponseRedirect(self.page.get_absolute_url())
else:
return HttpResponseRedirect('/')
return HttpResponseRedirect("/")
return self.render_to_response(self.get_context_data(form=form, **kwargs))
class CreateSection(EditSection):
def get_section(self):
return registry.section_class(page=self.page)
class UpdateSection(EditSection):
pass

Wyświetl plik

@ -1,26 +1,33 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
from cms.models import BasePage, BaseSection
from cms.decorators import page_model, section_model
from cms.models import BasePage, BaseSection
@page_model
class Page(BasePage):
'''Add custom fields here. Already existing fields: title, slug,
"""Add custom fields here. Already existing fields: title, slug,
number, menu
'''
"""
@section_model
class Section(BaseSection):
'''Add custom fields here. Already existing fields: title, type,
"""Add custom fields here. Already existing fields: title, type,
number, content, image, video, href
'''
page = models.ForeignKey(Page, related_name='sections', on_delete=models.PROTECT)
"""
page = models.ForeignKey(Page, related_name="sections", on_delete=models.PROTECT)
class SectionImage(models.Model):
section = models.ForeignKey(Section, related_name='images', on_delete=models.CASCADE)
image = models.ImageField(_('Image'))
section = models.ForeignKey(
Section, related_name="images", on_delete=models.CASCADE
)
image = models.ImageField(_("Image"))
class Meta:
ordering = ['pk']
ordering = ["pk"]

Wyświetl plik

@ -5,95 +5,95 @@ import sys
PROJECT_NAME = os.path.basename(os.path.dirname(os.path.abspath(__file__)))
DEBUG = 'runserver' in sys.argv
KEYFILE = f'/tmp/{PROJECT_NAME}.secret'
ADMINS = [('JJ Vens', 'jj@rtts.eu')]
DEFAULT_FROM_EMAIL = 'noreply@rtts.eu'
DEFAULT_TO_EMAIL = ['jj@rtts.eu']
ALLOWED_HOSTS = ['*']
ROOT_URLCONF = PROJECT_NAME + '.urls'
WSGI_APPLICATION = PROJECT_NAME + '.wsgi.application'
LANGUAGE_CODE = 'nl'
TIME_ZONE = 'Europe/Amsterdam'
DEBUG = "runserver" in sys.argv
KEYFILE = f"/tmp/{PROJECT_NAME}.secret"
ADMINS = [("JJ Vens", "jj@rtts.eu")]
DEFAULT_FROM_EMAIL = "noreply@rtts.eu"
DEFAULT_TO_EMAIL = ["jj@rtts.eu"]
ALLOWED_HOSTS = ["*"]
ROOT_URLCONF = PROJECT_NAME + ".urls"
WSGI_APPLICATION = PROJECT_NAME + ".wsgi.application"
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
LANGUAGE_CODE = "nl"
TIME_ZONE = "Europe/Amsterdam"
USE_I18N = True
USE_L10N = True
USE_TZ = True
STATIC_URL = '/static/'
STATIC_ROOT = '/srv/' + PROJECT_NAME + '/static'
MEDIA_URL = '/media/'
MEDIA_ROOT = '/srv/' + PROJECT_NAME + '/media'
LOGIN_REDIRECT_URL = '/'
LOGOUT_REDIRECT_URL = '/'
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
STATIC_URL = "/static/"
STATIC_ROOT = "/srv/" + PROJECT_NAME + "/static"
MEDIA_URL = "/media/"
MEDIA_ROOT = "/srv/" + PROJECT_NAME + "/media"
LOGIN_REDIRECT_URL = "/"
LOGOUT_REDIRECT_URL = "/"
if DEBUG:
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
CACHE_MIDDLEWARE_SECONDS = 0
try:
with open(KEYFILE) as f:
SECRET_KEY = f.read()
except IOError:
SECRET_KEY = ''.join(random.choice(string.printable) for x in range(50))
with open(KEYFILE, 'w') as f:
SECRET_KEY = "".join(random.choice(string.printable) for x in range(50))
with open(KEYFILE, "w") as f:
f.write(SECRET_KEY)
INSTALLED_APPS = [
PROJECT_NAME,
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'cms',
'embed_video',
'easy_thumbnails',
'django_extensions',
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"cms",
"embed_video",
"easy_thumbnails",
"django_extensions",
]
if not DEBUG:
INSTALLED_APPS += ['django.contrib.staticfiles']
INSTALLED_APPS += ["django.contrib.staticfiles"]
MIDDLEWARE = [
'django.middleware.cache.UpdateCacheMiddleware',
'cms.middleware.SassMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'tidy.middleware.TidyMiddleware',
'cms.middleware.FetchFromCacheMiddleware',
"django.middleware.cache.UpdateCacheMiddleware",
"cms.middleware.SassMiddleware",
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
"tidy.middleware.TidyMiddleware",
"cms.middleware.FetchFromCacheMiddleware",
]
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
},
]
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'USER': PROJECT_NAME,
'NAME': PROJECT_NAME,
"default": {
"ENGINE": "django.db.backends.postgresql",
"USER": PROJECT_NAME,
"NAME": PROJECT_NAME,
}
}
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
'LOCATION': '127.0.0.1:11211',
'KEY_PREFIX': PROJECT_NAME,
"default": {
"BACKEND": "django.core.cache.backends.memcached.PyLibMCCache",
"LOCATION": "127.0.0.1:11211",
"KEY_PREFIX": PROJECT_NAME,
}
}

Wyświetl plik

@ -1,16 +1,20 @@
from django.conf import settings
from django.contrib import admin
from django.urls import path, include
from django.conf.urls.static import static
from django.views.generic import RedirectView
from django.contrib import admin
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.urls import include, path
from django.views.generic import RedirectView
admin.site.site_header = admin.site.site_title = settings.PROJECT_NAME.replace('_', ' ').title()
urlpatterns = staticfiles_urlpatterns() + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
admin.site.site_header = admin.site.site_title = settings.PROJECT_NAME.replace(
"_", " "
).title()
urlpatterns = staticfiles_urlpatterns() + static(
settings.MEDIA_URL, document_root=settings.MEDIA_ROOT
)
urlpatterns += [
path('admin/', admin.site.urls),
path('accounts/', include('django.contrib.auth.urls')),
path('login/', RedirectView.as_view(url='/accounts/login/')),
path('logout/', RedirectView.as_view(url='/accounts/logout/')),
path('', include('cms.urls', namespace='cms')),
path("admin/", admin.site.urls),
path("accounts/", include("django.contrib.auth.urls")),
path("login/", RedirectView.as_view(url="/accounts/login/")),
path("logout/", RedirectView.as_view(url="/accounts/logout/")),
path("", include("cms.urls", namespace="cms")),
]

Wyświetl plik

@ -1,30 +1,35 @@
from django.utils.translation import gettext_lazy as _
from cms.views import SectionView, SectionFormView
from cms.decorators import section_view
from cms.forms import ContactForm
from cms.views import SectionFormView, SectionView
@section_view
class Text(SectionView):
verbose_name = _('Text')
fields = ['content']
template_name = 'text.html'
verbose_name = _("Text")
fields = ["content"]
template_name = "text.html"
@section_view
class Images(SectionView):
verbose_name = _('Image(s)')
fields = ['images']
template_name = 'images.html'
verbose_name = _("Image(s)")
fields = ["images"]
template_name = "images.html"
@section_view
class Video(SectionView):
verbose_name = _('Video')
fields = ['video']
template_name = 'video.html'
verbose_name = _("Video")
fields = ["video"]
template_name = "video.html"
@section_view
class Contact(SectionFormView):
verbose_name = _('Contact')
verbose_name = _("Contact")
fields = []
form_class = ContactForm
success_url = '/thanks/'
template_name = 'contact.html'
success_url = "/thanks/"
template_name = "contact.html"

Wyświetl plik

@ -11,6 +11,6 @@ import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'example.settings')
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "example.settings")
application = get_wsgi_application()

Wyświetl plik

@ -2,8 +2,8 @@
import os
import sys
if __name__ == '__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'example.settings')
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "example.settings")
try:
from django.core.management import execute_from_command_line
except ImportError as exc:

2
pyproject.toml 100644
Wyświetl plik

@ -0,0 +1,2 @@
[tool.isort]
line_length = 88

Wyświetl plik

@ -1,39 +1,40 @@
#!/usr/bin/env python
import cms
from setuptools import setup, find_packages
from setuptools import find_packages, setup
with open('README.md', 'r') as fh:
import cms
with open("README.md", "r") as fh:
long_description = fh.read()
setup(
name = 'django-simplecms',
description = 'Simple Django CMS',
version = cms.__version__,
author = 'Jaap Joris Vens',
author_email = 'jj+cms@rtts.eu',
url = 'https://github.com/rtts/django-simplecms',
long_description = long_description,
long_description_content_type = 'text/markdown',
packages = find_packages(),
entry_points = {
'console_scripts': ['simplecms=cms.__main__:main'],
name="django-simplecms",
description="Simple Django CMS",
version=cms.__version__,
author="Jaap Joris Vens",
author_email="jj+cms@rtts.eu",
url="https://github.com/rtts/django-simplecms",
long_description=long_description,
long_description_content_type="text/markdown",
packages=find_packages(),
entry_points={
"console_scripts": ["simplecms=cms.__main__:main"],
},
include_package_data = True,
classifiers = [
'Programming Language :: Python :: 3',
'License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)',
'Operating System :: OS Independent',
include_package_data=True,
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)",
"Operating System :: OS Independent",
],
python_requires = '>=3.8',
install_requires = [
'django',
'django-extensions',
'django-embed-video',
'django-tidy',
'easy-thumbnails',
'libsass',
'markdown',
'psycopg2',
'pylibmc',
python_requires=">=3.8",
install_requires=[
"django",
"django-extensions",
"django-embed-video",
"django-tidy",
"easy-thumbnails",
"libsass",
"markdown",
"psycopg2",
"pylibmc",
],
)