kopia lustrzana https://github.com/rtts/django-simplecms
Tidying up!
rodzic
0e221ccf33
commit
2382fd47f0
88
README.md
88
README.md
|
@ -3,13 +3,93 @@
|
||||||
*A super simple but very extensible content management system for
|
*A super simple but very extensible content management system for
|
||||||
Django websites.*
|
Django websites.*
|
||||||
|
|
||||||
This project provides the basic building blocks of *Pages* and
|
SimpleCMS provides the reusable Django app `cms` which contains
|
||||||
*Sections* and all the views needed to display and edit them.
|
everything you need to create websites that can be easily edited by
|
||||||
|
end users.
|
||||||
|
|
||||||
|
## How does it work?
|
||||||
|
|
||||||
|
Contrary to 'regular' Django websites, SimpleCMS allows you to write a
|
||||||
|
view for each *section*, rather than for each *page* on your website.
|
||||||
|
On which pages these sections appear, and in which order, is left to
|
||||||
|
the content editor rather than the programmer. After authenticating,
|
||||||
|
the editor can use the {page,section}{create,update} forms to fill the
|
||||||
|
website with various types of content.
|
||||||
|
|
||||||
|
Here's an example `views.py` of an app using SimpleCMS:
|
||||||
|
|
||||||
|
from cms.views import SectionView
|
||||||
|
from cms.decorators import section_view
|
||||||
|
|
||||||
|
@section_view
|
||||||
|
class HelloWorld(SectionView):
|
||||||
|
verbose_name = 'Hello world section'
|
||||||
|
fields = ['content']
|
||||||
|
template_name = 'hello.html'
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super()get_context_data(**kwargs)
|
||||||
|
context['message'] = 'Hello World!'
|
||||||
|
|
||||||
|
And here is the contents of `hello.html`:
|
||||||
|
|
||||||
|
<section type="helloworld">
|
||||||
|
<h1>{{message}}</h1>
|
||||||
|
{{section.content}}
|
||||||
|
</section>
|
||||||
|
|
||||||
|
Everytime a section needs to be rendered, your section view will be
|
||||||
|
called by SimpleCMS and return a response which will get inserted into
|
||||||
|
the final rendered page.
|
||||||
|
|
||||||
|
## The "Edit" Interface
|
||||||
|
|
||||||
|
Somewhat like the Django Admin site, SimpleCMS comes with its own
|
||||||
|
editing environment, albeit much simpler and only suitable for editing
|
||||||
|
pages and sections. After authenticating, the content editor can click
|
||||||
|
the "edit" button on any page of the website to alter, add or
|
||||||
|
rearrange sections.
|
||||||
|
|
||||||
|
For each section, the section type can be selected from a dropdown
|
||||||
|
menu. As you can see in `views.py` above, each section type comes with
|
||||||
|
its own list of editable fields. Client-side javascript will hide/show
|
||||||
|
the relevant fields based on the selected section type. All sections
|
||||||
|
are stored in the same database table.
|
||||||
|
|
||||||
|
## Batteries included!
|
||||||
|
|
||||||
|
SimpleCMS has been specifically crafted to fit my own personal needs
|
||||||
|
when building websites for customers. Therefore it includes a variety
|
||||||
|
of useful template tags, default *Page* and *Section* models, and all
|
||||||
|
the other boilerplate code needed for new projects.
|
||||||
|
|
||||||
|
One notable inclusion is the `eval` template tag. It will pass its
|
||||||
|
argument first through Django's templating system and then through
|
||||||
|
Markdown, making for instance the following possible. (Disclaimer: use
|
||||||
|
with caution!)
|
||||||
|
|
||||||
|
Welcome to **{% now 'Y' %}!**
|
||||||
|
|
||||||
|
Another useful feature is the automatic compilation of `SCSS` files to
|
||||||
|
`CSS` files using a custom middleware.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Use the provided helper command `simplecms` to quickly setup a new
|
Use the provided helper command `simplecms` to quickly setup a new
|
||||||
project:
|
project:
|
||||||
|
|
||||||
pip install https://github.com/rtts/django-simplecms.git
|
$ pip install https://github.com/rtts/django-simplecms.git
|
||||||
simplecms mysite
|
$ simplecms mysite
|
||||||
|
|
||||||
|
After the project files have been created, initialize the database and
|
||||||
|
create a superuser:
|
||||||
|
|
||||||
|
$ cd mysite
|
||||||
|
$ sudo su postgres -c "createuser mysite; createdb -O mysite mysite"
|
||||||
|
$ ./manage.py migrate
|
||||||
|
$ ./manage.py createsuperuser
|
||||||
|
|
||||||
|
Finally, run the development server and visit
|
||||||
|
http://localhost:8000/login/ in your browser to log in!
|
||||||
|
|
||||||
|
$ ./manage.py runserver
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
#!/bin/bash -e
|
|
||||||
|
|
||||||
test -z $1 && echo "Please provide a project name!" && exit 1
|
|
||||||
|
|
||||||
mkdir -p $1 && cd $1
|
|
||||||
pip3 freeze > requirements.txt
|
|
||||||
example_dir=$(python3 -c 'import os,example;print(os.path.dirname(example.__file__))')
|
|
||||||
cp -r $example_dir/{project,app,manage.py} .
|
|
||||||
sed -i s/example/$1/ project/settings.py
|
|
||||||
|
|
||||||
# Assume the user has sudo access to postgres
|
|
||||||
sudo su postgres -c "createuser $1; createdb -O $1 $1" || true
|
|
||||||
|
|
||||||
cat << EOF > .gitignore
|
|
||||||
*.pyc
|
|
||||||
__pycache__/
|
|
||||||
EOF
|
|
||||||
|
|
||||||
./manage.py makemigrations app
|
|
||||||
./manage.py migrate
|
|
||||||
./manage.py createsuperuser
|
|
||||||
./manage.py runserver --nostatic
|
|
|
@ -7,4 +7,4 @@ class CmsConfig(AppConfig):
|
||||||
verbose_name = _('Content Management System')
|
verbose_name = _('Content Management System')
|
||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
autodiscover_modules('cms')
|
autodiscover_modules('views')
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
#!/bin/bash -e
|
||||||
|
|
||||||
|
test -z $1 && echo "Please provide a project name!" && exit 1
|
||||||
|
mkdir "$1"
|
||||||
|
cd "$1"
|
||||||
|
pip3 freeze > requirements.txt
|
||||||
|
example_dir=$(python3 -c 'import os,example;print(os.path.dirname(example.__file__))')
|
||||||
|
cp -r "$example_dir" "$1"
|
||||||
|
cp "$example_dir"/../manage.py .
|
||||||
|
sed -i "s/example/$1/" manage.py
|
||||||
|
cat << EOF > .gitignore
|
||||||
|
*.pyc
|
||||||
|
__pycache__/
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat <<EOF
|
||||||
|
|
||||||
|
Successfully created project "$1"!
|
||||||
|
|
||||||
|
Things to do next:
|
||||||
|
- create a database
|
||||||
|
- ./manage.py migrate
|
||||||
|
- ./manage.py createsuperuser
|
||||||
|
- ./manage.py runserver --nostatic
|
||||||
|
|
||||||
|
EOF
|
|
@ -12,6 +12,6 @@ def section_model(cls):
|
||||||
|
|
||||||
def section_view(cls):
|
def section_view(cls):
|
||||||
'''Decorator to register a view for a specific section'''
|
'''Decorator to register a view for a specific section'''
|
||||||
registry.views_per_type[cls.__name__.lower()] = cls
|
registry.view_per_type[cls.__name__.lower()] = cls
|
||||||
registry.section_class.TYPES.append((cls.__name__.lower(), cls.verbose_name))
|
registry.section_types.append((cls.__name__.lower(), cls.verbose_name))
|
||||||
return cls
|
return cls
|
||||||
|
|
27
cms/forms.py
27
cms/forms.py
|
@ -11,20 +11,18 @@ class PageForm(forms.ModelForm):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.label_suffix = ''
|
self.label_suffix = ''
|
||||||
extra = 1 if self.instance.pk else 2
|
|
||||||
self.formsets = [forms.inlineformset_factory(
|
self.formsets = [forms.inlineformset_factory(
|
||||||
parent_model = registry.page_class,
|
parent_model=registry.page_class,
|
||||||
model = registry.section_class,
|
model=registry.section_class,
|
||||||
form = SectionForm,
|
form=SectionForm,
|
||||||
extra=extra,
|
extra=1,
|
||||||
)(
|
)(
|
||||||
data=self.data if self.is_bound else None,
|
data=self.data if self.is_bound else None,
|
||||||
files=self.files if self.is_bound else None,
|
files=self.files if self.is_bound else None,
|
||||||
instance=self.instance,
|
instance=self.instance,
|
||||||
form_kwargs={'label_suffix': self.label_suffix},
|
|
||||||
)]
|
)]
|
||||||
if not self.instance.pk:
|
self.formsets[0][0].empty_permitted = True
|
||||||
self.formsets[0][0].empty_permitted = False
|
|
||||||
|
|
||||||
def is_valid(self):
|
def is_valid(self):
|
||||||
return super().is_valid() and self.formsets[0].is_valid()
|
return super().is_valid() and self.formsets[0].is_valid()
|
||||||
|
@ -42,9 +40,6 @@ class PageForm(forms.ModelForm):
|
||||||
formset = self.formsets[0]
|
formset = self.formsets[0]
|
||||||
formset.instance = page
|
formset.instance = page
|
||||||
formset.save()
|
formset.save()
|
||||||
if page.slug and not page.sections.exists():
|
|
||||||
page.delete()
|
|
||||||
return None
|
|
||||||
return page
|
return page
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -58,12 +53,8 @@ class SectionForm(forms.ModelForm):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.label_suffix = ''
|
self.label_suffix = ''
|
||||||
self.fields['DELETE'] = forms.BooleanField(label=_('Delete'), required=False)
|
self.fields['DELETE'] = forms.BooleanField(label=_('Delete'), required=False)
|
||||||
extra = 1 if self.instance.pk else 2
|
self.fields['type'].choices = registry.get_types()
|
||||||
|
self.fields['type'].initial = registry.get_types()[0][0]
|
||||||
# Repopulate the 'choices' attribute of the type field from
|
|
||||||
# the child model.
|
|
||||||
self.fields['type'].choices = self._meta.model.TYPES
|
|
||||||
self.fields['type'].initial = self._meta.model.TYPES[0][0]
|
|
||||||
|
|
||||||
# Populate the 'formsets' attribute if the Section was
|
# Populate the 'formsets' attribute if the Section was
|
||||||
# extendend with one_to_many fields
|
# extendend with one_to_many fields
|
||||||
|
@ -74,7 +65,7 @@ class SectionForm(forms.ModelForm):
|
||||||
parent_model=registry.section_class,
|
parent_model=registry.section_class,
|
||||||
model=field.related_model,
|
model=field.related_model,
|
||||||
fields='__all__',
|
fields='__all__',
|
||||||
extra=extra,
|
extra=1,
|
||||||
)(
|
)(
|
||||||
instance=self.instance,
|
instance=self.instance,
|
||||||
data=self.data if self.is_bound else None,
|
data=self.data if self.is_bound else None,
|
||||||
|
|
|
@ -1,27 +1,35 @@
|
||||||
import os
|
import os
|
||||||
from django.conf import settings
|
|
||||||
from django.apps import apps
|
|
||||||
from sass import compile
|
from sass import compile
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
def locate(filename):
|
||||||
|
for path, dirs, files in os.walk(os.getcwd()):
|
||||||
|
for f in files:
|
||||||
|
if f == filename:
|
||||||
|
return os.path.join(path, filename)
|
||||||
|
|
||||||
class SassMiddleware:
|
class SassMiddleware:
|
||||||
|
'''Simple SASS middleware that intercepts requests for .css files and
|
||||||
|
tries to compile the corresponding SCSS file.
|
||||||
|
|
||||||
|
'''
|
||||||
def __init__(self, get_response):
|
def __init__(self, get_response):
|
||||||
self.get_response = get_response
|
self.get_response = get_response
|
||||||
|
|
||||||
def __call__(self, request):
|
def __call__(self, request):
|
||||||
if settings.DEBUG and request.path.endswith('.css'):
|
if settings.DEBUG and request.path.endswith('.css'):
|
||||||
_, staticdir, appname, css_file = request.path.split('/', maxsplit=3)
|
css_file = request.path.rsplit('/',1)[1]
|
||||||
app_path = apps.get_app_config(appname).path
|
css_path = locate(css_file)
|
||||||
sass_file = css_file[:-4]
|
if css_path:
|
||||||
css_path = os.path.join(app_path, staticdir, appname, css_file)
|
sass_path = css_path[:-4]
|
||||||
sass_path = os.path.join(app_path, staticdir, appname, sass_file)
|
map_path = css_path + '.map'
|
||||||
map_path = css_path + '.map'
|
if os.path.exists(sass_path):
|
||||||
if os.path.exists(sass_path):
|
css = compile(filename=sass_path, output_style='nested')
|
||||||
css = compile(filename=sass_path, output_style='nested')
|
css, mapping = compile(filename=sass_path, source_map_filename=map_path)
|
||||||
css, mapping = compile(filename=sass_path, source_map_filename=map_path)
|
with open(css_path, 'w') as f:
|
||||||
with open(css_path, 'w') as f:
|
f.write(css)
|
||||||
f.write(css)
|
with open(map_path, 'w') as f:
|
||||||
with open(map_path, 'w') as f:
|
f.write(mapping)
|
||||||
f.write(mapping)
|
|
||||||
|
|
||||||
response = self.get_response(request)
|
response = self.get_response(request)
|
||||||
return response
|
return response
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
views_per_type = {}
|
|
||||||
page_class = None
|
page_class = None
|
||||||
section_class = None
|
section_class = None
|
||||||
|
section_types = []
|
||||||
|
view_per_type = {}
|
||||||
|
|
||||||
|
def get_types():
|
||||||
|
return section_types
|
||||||
|
|
||||||
def get_view(section, request):
|
def get_view(section, request):
|
||||||
'''Instantiate the registered view of a section'''
|
return view_per_type[section.type](request)
|
||||||
return views_per_type[section.type](request)
|
|
||||||
|
|
||||||
def get_fields_per_type():
|
def get_fields_per_type():
|
||||||
fields_per_type = {}
|
fields_per_type = {}
|
||||||
for name, view in views_per_type.items():
|
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
|
return fields_per_type
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ form.cms {
|
||||||
background: $background;
|
background: $background;
|
||||||
border: 0.5px solid #ccc;
|
border: 0.5px solid #ccc;
|
||||||
clear: both;
|
clear: both;
|
||||||
margin: 0.5em 0em;
|
margin: 0.25em 0em;
|
||||||
padding: 0.25em 0.5em;
|
padding: 0.25em 0.5em;
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
border-radius: 0.25em;
|
border-radius: 0.25em;
|
||||||
|
@ -60,7 +60,9 @@ form.cms {
|
||||||
}
|
}
|
||||||
|
|
||||||
div.formfield {
|
div.formfield {
|
||||||
margin: 0.25em 0;
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
overflow: hidden;
|
||||||
clear: both;
|
clear: both;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
@ -68,6 +70,7 @@ form.cms {
|
||||||
width: 77%;
|
width: 77%;
|
||||||
clear: none;
|
clear: none;
|
||||||
float: left;
|
float: left;
|
||||||
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
&.number {
|
&.number {
|
||||||
width: 20%;
|
width: 20%;
|
||||||
|
@ -108,6 +111,7 @@ form.cms {
|
||||||
}
|
}
|
||||||
|
|
||||||
input, select, textarea {
|
input, select, textarea {
|
||||||
|
height: 32px;
|
||||||
background: $background;
|
background: $background;
|
||||||
color: black;
|
color: black;
|
||||||
border: 0.5px solid #ccc;
|
border: 0.5px solid #ccc;
|
||||||
|
@ -130,6 +134,7 @@ form.cms {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
height: 15em;
|
height: 15em;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
|
overflow-y: hidden;
|
||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
padding-left: 3px;
|
padding-left: 3px;
|
||||||
|
|
|
@ -34,7 +34,7 @@ form.cms {
|
||||||
background: #fff6;
|
background: #fff6;
|
||||||
border: 0.5px solid #ccc;
|
border: 0.5px solid #ccc;
|
||||||
clear: both;
|
clear: both;
|
||||||
margin: 0.5em 0em;
|
margin: 0.25em 0em;
|
||||||
padding: 0.25em 0.5em;
|
padding: 0.25em 0.5em;
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
border-radius: 0.25em; }
|
border-radius: 0.25em; }
|
||||||
|
@ -44,13 +44,16 @@ form.cms {
|
||||||
width: 50px;
|
width: 50px;
|
||||||
cursor: pointer; }
|
cursor: pointer; }
|
||||||
form.cms div.formfield {
|
form.cms div.formfield {
|
||||||
margin: 0.25em 0;
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
overflow: hidden;
|
||||||
clear: both;
|
clear: both;
|
||||||
box-sizing: border-box; }
|
box-sizing: border-box; }
|
||||||
form.cms div.formfield.type, form.cms div.formfield.number, form.cms div.formfield.slug {
|
form.cms div.formfield.type, form.cms div.formfield.number, form.cms div.formfield.slug {
|
||||||
width: 77%;
|
width: 77%;
|
||||||
clear: none;
|
clear: none;
|
||||||
float: left; }
|
float: left;
|
||||||
|
margin-top: 0; }
|
||||||
form.cms div.formfield.number {
|
form.cms div.formfield.number {
|
||||||
width: 20%;
|
width: 20%;
|
||||||
float: right; }
|
float: right; }
|
||||||
|
@ -76,6 +79,7 @@ form.cms {
|
||||||
font-size: 12px !important;
|
font-size: 12px !important;
|
||||||
font-weight: 400 !important; }
|
font-weight: 400 !important; }
|
||||||
form.cms input, form.cms select, form.cms textarea {
|
form.cms input, form.cms select, form.cms textarea {
|
||||||
|
height: 32px;
|
||||||
background: #fff6;
|
background: #fff6;
|
||||||
color: black;
|
color: black;
|
||||||
border: 0.5px solid #ccc;
|
border: 0.5px solid #ccc;
|
||||||
|
@ -95,7 +99,8 @@ form.cms {
|
||||||
form.cms textarea {
|
form.cms textarea {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
height: 15em;
|
height: 15em;
|
||||||
line-height: 1.5; }
|
line-height: 1.5;
|
||||||
|
overflow-y: hidden; }
|
||||||
form.cms select {
|
form.cms select {
|
||||||
padding-left: 3px; }
|
padding-left: 3px; }
|
||||||
form.cms ul.errorlist {
|
form.cms ul.errorlist {
|
||||||
|
|
|
@ -5,5 +5,5 @@
|
||||||
"admin.scss"
|
"admin.scss"
|
||||||
],
|
],
|
||||||
"names": [],
|
"names": [],
|
||||||
"mappings": "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"
|
"mappings": "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"
|
||||||
}
|
}
|
|
@ -11,6 +11,7 @@
|
||||||
{% if form.errors %}
|
{% if form.errors %}
|
||||||
<div class="global_error">
|
<div class="global_error">
|
||||||
{% trans 'Please correct the error(s) below and save again' %}
|
{% trans 'Please correct the error(s) below and save again' %}
|
||||||
|
{{form.errors}}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
@ -75,8 +76,7 @@
|
||||||
function resizeTextareas() {
|
function resizeTextareas() {
|
||||||
let tx = document.getElementsByTagName('textarea');
|
let tx = document.getElementsByTagName('textarea');
|
||||||
for (let i = 0; i < tx.length; i++) {
|
for (let i = 0; i < tx.length; i++) {
|
||||||
tx[i].setAttribute('style', 'height:0;overflow-y:hidden;');
|
tx[i].style.height = (tx[i].scrollHeight) + 1 + 'px';
|
||||||
tx[i].style.height = (tx[i].scrollHeight) + 'px';
|
|
||||||
tx[i].addEventListener('input', function() {
|
tx[i].addEventListener('input', function() {
|
||||||
this.style.height = (this.scrollHeight) + 1 + 'px'; // why the 1???
|
this.style.height = (this.scrollHeight) + 1 + 'px'; // why the 1???
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 3.0.2 on 2020-03-22 11:11
|
# Generated by Django 3.0.2 on 2020-03-22 15:45
|
||||||
|
|
||||||
import cms.models
|
import cms.models
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -31,16 +31,6 @@ class Migration(migrations.Migration):
|
||||||
},
|
},
|
||||||
bases=(cms.models.Numbered, models.Model),
|
bases=(cms.models.Numbered, models.Model),
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
|
||||||
name='SectionImage',
|
|
||||||
fields=[
|
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('image', models.ImageField(upload_to='', verbose_name='Image')),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'ordering': ['pk'],
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='Section',
|
name='Section',
|
||||||
fields=[
|
fields=[
|
||||||
|
@ -62,4 +52,15 @@ class Migration(migrations.Migration):
|
||||||
},
|
},
|
||||||
bases=(cms.models.Numbered, models.Model),
|
bases=(cms.models.Numbered, models.Model),
|
||||||
),
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='SectionImage',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('image', models.ImageField(upload_to='', verbose_name='Image')),
|
||||||
|
('section', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='images', to='example.Section')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'ordering': ['pk'],
|
||||||
|
},
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
import swapper
|
|
||||||
from django.db import migrations
|
|
||||||
Page = swapper.load_model('cms', 'Page')
|
|
||||||
|
|
||||||
def add_homepage(apps, schema_editor):
|
|
||||||
if not Page.objects.exists():
|
|
||||||
Page(slug='', title='Homepage', number=1).save()
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
dependencies = [
|
|
||||||
('cms', '0001_initial'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.RunPython(add_homepage, migrations.RunPython.noop),
|
|
||||||
]
|
|
|
@ -19,7 +19,7 @@ class Section(BaseSection):
|
||||||
page = models.ForeignKey(Page, verbose_name=_('page'), related_name='sections', on_delete=models.PROTECT)
|
page = models.ForeignKey(Page, verbose_name=_('page'), related_name='sections', on_delete=models.PROTECT)
|
||||||
|
|
||||||
class SectionImage(models.Model):
|
class SectionImage(models.Model):
|
||||||
#section = models.ForeignKey(Section, related_name='images', on_delete=models.CASCADE)
|
section = models.ForeignKey(Section, related_name='images', on_delete=models.CASCADE)
|
||||||
image = models.ImageField(_('Image'))
|
image = models.ImageField(_('Image'))
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
|
@ -26,17 +26,13 @@ except ImportError:
|
||||||
DEBUG = True
|
DEBUG = True
|
||||||
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
|
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
|
||||||
|
|
||||||
def read(file):
|
|
||||||
with open(file) as f:
|
|
||||||
return f.read()
|
|
||||||
def write(file, content):
|
|
||||||
with open(file, 'w') as f:
|
|
||||||
f.write(content)
|
|
||||||
try:
|
try:
|
||||||
SECRET_KEY = read(KEYFILE)
|
with open(KEYFILE) as f:
|
||||||
|
SECRET_KEY = f.read()
|
||||||
except IOError:
|
except IOError:
|
||||||
SECRET_KEY = ''.join(random.choice(string.printable) for x in range(50))
|
SECRET_KEY = ''.join(random.choice(string.printable) for x in range(50))
|
||||||
write(KEYFILE, SECRET_KEY)
|
with open(KEYFILE, 'w') as f:
|
||||||
|
f.write(SECRET_KEY)
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
PROJECT_NAME,
|
PROJECT_NAME,
|
||||||
|
@ -45,12 +41,13 @@ INSTALLED_APPS = [
|
||||||
'django.contrib.contenttypes',
|
'django.contrib.contenttypes',
|
||||||
'django.contrib.sessions',
|
'django.contrib.sessions',
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
|
||||||
'cms',
|
'cms',
|
||||||
'embed_video',
|
'embed_video',
|
||||||
'easy_thumbnails',
|
'easy_thumbnails',
|
||||||
'django_extensions',
|
'django_extensions',
|
||||||
]
|
]
|
||||||
|
if not DEBUG:
|
||||||
|
INSTALLED_APPS += ['django.contrib.staticfiles']
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
'cms.middleware.SassMiddleware',
|
'cms.middleware.SassMiddleware',
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
{% block title %}Awesome Website{% endblock %}
|
{% block title %}Awesome Website{% endblock %}
|
||||||
|
|
||||||
{% block extrahead %}
|
{% block extrahead %}
|
||||||
<link rel="stylesheet" href="{% static 'app/hamburgers.css' %}">
|
<link rel="stylesheet" href="{% static 'hamburgers.css' %}">
|
||||||
<link rel="stylesheet" href="{% static 'app/main1.scss.css' %}">
|
<link rel="stylesheet" href="{% static 'main1.scss.css' %}">
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block header %}
|
{% block header %}
|
||||||
|
|
|
@ -1,30 +1,30 @@
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
from cms.views import SectionView, SectionFormView
|
from cms.views import SectionView, SectionFormView
|
||||||
from cms.decorators import section_view
|
from cms.decorators import section_view
|
||||||
from cms.forms import ContactForm
|
from cms.forms import ContactForm
|
||||||
from django.utils.translation import gettext_lazy as _
|
|
||||||
|
|
||||||
@section_view
|
@section_view
|
||||||
class Text(SectionView):
|
class Text(SectionView):
|
||||||
verbose_name = _('Text')
|
verbose_name = _('Text')
|
||||||
fields = ['title', 'content']
|
fields = ['content']
|
||||||
template_name = 'app/sections/text.html'
|
template_name = 'text.html'
|
||||||
|
|
||||||
@section_view
|
@section_view
|
||||||
class Images(SectionView):
|
class Images(SectionView):
|
||||||
verbose_name = _('Images')
|
verbose_name = _('Image(s)')
|
||||||
fields = ['title', 'images']
|
fields = ['images']
|
||||||
template_name = 'app/sections/images.html'
|
template_name = 'images.html'
|
||||||
|
|
||||||
@section_view
|
@section_view
|
||||||
class Video(SectionView):
|
class Video(SectionView):
|
||||||
verbose_name = _('Video')
|
verbose_name = _('Video')
|
||||||
fields = ['title', 'video']
|
fields = ['video']
|
||||||
template_name = 'app/sections/video.html'
|
template_name = 'video.html'
|
||||||
|
|
||||||
@section_view
|
@section_view
|
||||||
class Contact(SectionFormView):
|
class Contact(SectionFormView):
|
||||||
verbose_name = _('Contact')
|
verbose_name = _('Contact')
|
||||||
fields = ['title']
|
fields = []
|
||||||
form_class = ContactForm
|
form_class = ContactForm
|
||||||
success_url = '/thanks/'
|
success_url = '/thanks/'
|
||||||
template_name = 'app/sections/contact.html'
|
template_name = 'contact.html'
|
4
setup.py
4
setup.py
|
@ -3,13 +3,13 @@ from setuptools import setup, find_packages
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name = 'django-simplecms',
|
name = 'django-simplecms',
|
||||||
version = '3.0.0',
|
version = '1.0.0',
|
||||||
url = 'https://github.com/rtts/django-simplecms',
|
url = 'https://github.com/rtts/django-simplecms',
|
||||||
author = 'Jaap Joris Vens',
|
author = 'Jaap Joris Vens',
|
||||||
author_email = 'jj@rtts.eu',
|
author_email = 'jj@rtts.eu',
|
||||||
license = 'GPL3',
|
license = 'GPL3',
|
||||||
packages = find_packages(),
|
packages = find_packages(),
|
||||||
scripts = ['bin/simplecms'],
|
scripts = ['cms/bin/simplecms'],
|
||||||
include_package_data = True,
|
include_package_data = True,
|
||||||
install_requires = [
|
install_requires = [
|
||||||
'django',
|
'django',
|
||||||
|
|
Ładowanie…
Reference in New Issue