Skip to content
This repository has been archived by the owner on Jan 19, 2022. It is now read-only.

Commit

Permalink
Merge pull request #51 from Wtower/improve-render
Browse files Browse the repository at this point in the history
Improve render
  • Loading branch information
Wtower committed Apr 2, 2016
2 parents b6df0a9 + bc752cb commit 2e27437
Show file tree
Hide file tree
Showing 34 changed files with 785 additions and 748 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,11 @@ coverage.xml
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
.idea/

### Fish vf
.venv

### Django
media/
tests/media/ninecms/basic/image/*/

# Libraries
ninecms/static/ninecms/bootstrap/
Expand Down
24 changes: 24 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# http://docs.travis-ci.com/user/languages/python/

language: python

python:
- 3.4
- 3.5

install:
- pip install -r requirements.txt
- pip install coveralls

script:
coverage run manage.py test

after_success:
coveralls

notifications:
email:
on_success: change
on_failure: change

sudo: false
52 changes: 52 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,58 @@
CHANGELOG
=========

Future: v0.6.1
--------------

Estimated release date: May 16 2016

Update date: Wed Mar 30 2016

Planned changes

- Add migration 14 #46

- remove PageLayoutElements model
- make ContenBlock name unique not null

**:warning: Changes that require manual migration actions:**

- Upgrade to v0.6.0 prior to upgrading to future versions #45

Development: v0.6.0
-------------------

Estimated release date: Apr 16 2016

Update date: Wed Mar 30 2016

Planned changes

- Improve page rendering #45

- remove theme suggestions
- use template blocks and only provide proper context
- deprecate page layout elements
- remove front-end libraries #43

- Admin: add m2m related fields on both ends:

- page types / blocks
- nodes / terms

- Integrate tests #44
- Use Python path functions in image styles #48
- Fix #47 setup fails
- Use Travis and Coveralls #35

What's new

All changes

**:warning: Changes that require manual migration actions:**

- Change all templates that use image styles to pass the actual ImageFieldFile rather than a url #48

v0.5.4
------

Expand Down
10 changes: 10 additions & 0 deletions manage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env python
import os
import sys

if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "tests.settings_test")

from django.core.management import execute_from_command_line

execute_from_command_line(sys.argv)
35 changes: 13 additions & 22 deletions ninecms/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,14 @@
from ninecms import models, forms, views


class PageLayoutElementInline(admin.StackedInline):
""" Page Layout Element stacked inline to be displayed in Page Types """
model = models.PageLayoutElement
extra = 0


# noinspection PyMethodMayBeStatic
@admin.register(models.PageType)
class PageTypeAdmin(admin.ModelAdmin):
""" Get a list of Page Types """
list_display = ('name', 'description', 'url_pattern', 'elements', 'operations')
list_editable = ('description', 'url_pattern')
search_fields = ['name']
inlines = [PageLayoutElementInline]
form = forms.PageTypeForm
save_as = True

def elements(self, obj):
Expand Down Expand Up @@ -262,13 +256,15 @@ def get_fieldsets(self, request, obj=None):
("Body", {'fields': ('highlight', 'summary', 'body', 'link')}),
("Node management", {'fields': ('status', 'promote', 'sticky', 'redirect', 'user',
'created', 'original_translation', 'weight')}),
("Terms", {'fields': ('terms',)}),
)
else:
return (
("Node", {'fields': ('page_type', 'language', 'title')}),
("Body", {'fields': ('highlight', 'summary', 'body', 'link')}),
("Node management", {'fields': ('status', 'promote', 'sticky', 'user',
'created', 'original_translation', 'weight')}),
("Terms", {'fields': ('terms',)}),
)

def get_changeform_initial_data(self, request):
Expand Down Expand Up @@ -329,40 +325,35 @@ def formfield_for_choice_field(self, db_field, request=None, **kwargs):
@admin.register(models.ContentBlock)
class ContentBlockAdmin(admin.ModelAdmin):
""" Get a list of blocks """
list_display = ('description', 'type', 'node', 'menu_item', 'signal', 'elements')
list_display = ('name', 'type', 'node', 'menu_item', 'signal', 'page_types_list')
list_filter = ['type']
filter_vertical = ('page_types', )

def description(self, obj):
""" Return a custom column with the block's description
:param obj: a block object
:return: column output
"""
return str(obj)

def elements(self, obj):
def page_types_list(self, obj):
""" Return a custom column with page types in which each block is an element
If page type is immediately repeated (same block more than once in one page type), add '+' instead
:param obj: a block object
:return: column output
"""
r = []
prev = 0
for element in obj.pagelayoutelement_set.all():
if element.page_type.id != prev:
for page_type in obj.page_types.all():
if page_type.id != prev:
r.append('<a href="%s">%s</a>' % (
reverse('admin:ninecms_pagetype_change', args=(element.page_type.id,)), element.page_type))
reverse('admin:ninecms_pagetype_change', args=(page_type.id,)), page_type))
else:
r[-1] += '+'
prev = element.page_type.id
prev = page_type.id
return ', '.join(r)
elements.allow_tags = True
elements.short_description = _("Page types")
page_types_list.allow_tags = True
page_types_list.short_description = _("Page types")


@admin.register(models.TaxonomyTerm)
class TaxonomyTermAdmin(MPTTModelAdmin):
""" Get a list of Taxonomy Terms """
list_display = ('name', 'description_node', 'weight')
filter_vertical = ('nodes', )

admin.site.site_header = _("9cms administration")
admin.site.site_title = "9cms"
Expand Down
107 changes: 93 additions & 14 deletions ninecms/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,88 @@

from django import forms
from django.forms.models import inlineformset_factory
from django.contrib.admin.widgets import FilteredSelectMultiple
from django.contrib.auth.models import Group
from django.utils.translation import ugettext_lazy as _
from ninecms.models import Node, Image, File, Video
from ninecms.models import Node, Image, File, Video, ContentBlock, PageType, TaxonomyTerm
from ninecms.utils.sanitize import sanitize, ModelSanitizeForm


class PageTypeForm(forms.ModelForm):
""" Override default page type form to show related blocks
https://www.lasolution.be/blog/related-manytomanyfield-django-admin-site.html
https://github.com/django/django/blob/master/django/contrib/admin/widgets.py#L24
"""
# @todo make parent generic class for reverse related m2m fields (use a new meta prop)
blocks = forms.ModelMultipleChoiceField(
ContentBlock.objects.all(),
widget=FilteredSelectMultiple("Blocks", True),
required=False,
)

def __init__(self, *args, **kwargs):
""" Initialize form
:param args
:param kwargs
:return: None
"""
super(PageTypeForm, self).__init__(*args, **kwargs)
if self.instance.pk:
self.initial['blocks'] = self.instance.blocks.values_list('pk', flat=True)
# from django.db.models import ManyToManyRel
# from django.contrib import admin
# rel = ManyToManyRel(ContentBlock, PageType)
# self.fields['blocks'].widget = RelatedFieldWidgetWrapper(self.fields['blocks'].widget, rel, admin.site)

def save(self, *args, **kwargs):
""" Handle saving of related blocks
:param args
:param kwargs
:return: instance
"""
instance = super(PageTypeForm, self).save(*args, **kwargs)
if instance.pk:
for block in instance.blocks.all():
if block not in self.cleaned_data['blocks']:
instance.blocks.remove(block)
for block in self.cleaned_data['blocks']:
if block not in instance.blocks.all():
instance.blocks.add(block)
return instance

class Meta:
""" Meta class """
model = PageType
fields = ['name', 'description', 'guidelines', 'url_pattern']


class ContentTypePermissionsForm(forms.Form):
""" Content type permissions form """
add_node = forms.ModelMultipleChoiceField(
queryset=Group.objects.all(),
widget=forms.CheckboxSelectMultiple,
required=False
)
change_node = forms.ModelMultipleChoiceField(
queryset=Group.objects.all(),
widget=forms.CheckboxSelectMultiple,
required=False
)
delete_node = forms.ModelMultipleChoiceField(
queryset=Group.objects.all(),
widget=forms.CheckboxSelectMultiple,
required=False
)


class ContentNodeEditForm(forms.ModelForm):
""" Node edit or create form """
terms = forms.ModelMultipleChoiceField(
TaxonomyTerm.objects.all(),
widget=FilteredSelectMultiple("Terms", True),
required=False,
)

def __init__(self, *args, **kwargs):
""" Get user object to check if has full_html permission
Checks if current_user is already set (eg from ModelAdmin)
Expand All @@ -26,6 +100,8 @@ def __init__(self, *args, **kwargs):
except AttributeError:
self.current_user = kwargs.pop('user', None)
super(ContentNodeEditForm, self).__init__(*args, **kwargs)
if self.instance.pk:
self.initial['terms'] = self.instance.terms.values_list('pk', flat=True)

def clean(self):
""" Override clean form to bleach
Expand All @@ -41,6 +117,22 @@ def clean(self):
cleaned_data[field] = sanitize(cleaned_data[field], full_html=full_html)
return cleaned_data

def save(self, *args, **kwargs):
""" Handle saving of related terms
:param args
:param kwargs
:return: instance
"""
instance = super(ContentNodeEditForm, self).save(*args, **kwargs)
if instance.pk:
for term in instance.terms.all():
if term not in self.cleaned_data['terms']:
instance.terms.remove(term)
for term in self.cleaned_data['terms']:
if term not in instance.terms.all():
instance.terms.add(term)
return instance

class Meta:
""" Form model and fields """
model = Node
Expand Down Expand Up @@ -135,16 +227,3 @@ def clean(self):
if 'q' in cleaned_data:
cleaned_data['q'] = sanitize(cleaned_data['q'], allow_html=False)
return cleaned_data


class ContentTypePermissionsForm(forms.Form):
""" Content type permissions form """
add_node = forms.ModelMultipleChoiceField(queryset=Group.objects.all(),
widget=forms.CheckboxSelectMultiple,
required=False)
change_node = forms.ModelMultipleChoiceField(queryset=Group.objects.all(),
widget=forms.CheckboxSelectMultiple,
required=False)
delete_node = forms.ModelMultipleChoiceField(queryset=Group.objects.all(),
widget=forms.CheckboxSelectMultiple,
required=False)
4 changes: 2 additions & 2 deletions ninecms/management/commands/check_updates.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from django.core.management import BaseCommand
from django.core.cache import caches
from django.core.mail import mail_admins
from django.template import loader, Context
from django.template import loader
from django.utils.translation import ugettext as _
from ninecms.utils.status import Capturing
# noinspection PyPackageRequirements
Expand All @@ -31,4 +31,4 @@ def handle(self, *args, **options):
else: # pragma: nocover
cache.set('updates', updates, 7 * 24 * 60 * 60) # 1wk
t = loader.get_template('ninecms/mail_updates.txt')
mail_admins(_("New updates available"), t.render(Context({'updates': updates})))
mail_admins(_("New updates available"), t.render({'updates': updates}))
Loading

0 comments on commit 2e27437

Please sign in to comment.