kopia lustrzana https://github.com/rtts/django-simplecms
Blackify everything
rodzic
cd8151b2ce
commit
98de86f49d
|
@ -1,2 +1,2 @@
|
|||
__version__ = "1.0.5"
|
||||
__version__ = "1.0.6"
|
||||
default_app_config = "cms.apps.CmsConfig"
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
75
cms/forms.py
75
cms/forms.py
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
28
cms/urls.py
28
cms/urls.py
|
@ -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"),
|
||||
]
|
||||
|
|
168
cms/views.py
168
cms/views.py
|
@ -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
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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")),
|
||||
]
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
[tool.isort]
|
||||
line_length = 88
|
61
setup.py
61
setup.py
|
@ -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",
|
||||
],
|
||||
)
|
||||
|
|
Ładowanie…
Reference in New Issue