Commit f3dce909 by Christina Roberts Committed by GitHub

Merge pull request #24 from edx/christina/1_11_upgrade

Updates for Django 1.11.
parents 144a8162 f749c67a
from django.contrib.contenttypes.models import ContentType
from django.db.models import Model
from django.utils.translation import ugettext as _
import models
_disable_notifications = False
def notify(message, key, target_object=None, url=None):
"""
Notify subscribing users of a new event. Key can be any kind of string,
just make sure to reuse it where applicable! Object_id is some identifier
of an object, for instance if a user subscribes to a specific comment thread,
you could write:
notify("there was a response to your comment", "comment_response",
target_object=PostersObject,
url=reverse('comments:view', args=(PostersObject.id,)))
The below example notifies everyone subscribing to the "new_comments" key
with the message "New comment posted".
notify("New comment posted", "new_comments")
"""
if _disable_notifications:
return 0
if target_object:
if not isinstance(target_object, Model):
raise TypeError(_(u"You supplied a target_object that's not an instance of a django Model."))
object_id = target_object.id
else:
object_id = None
objects = models.Notification.create_notifications(key, object_id=object_id,
message=message, url=url)
return len(objects)
\ No newline at end of file
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.db import models from django.db import models
from django.db.models import Q from django.db.models import Q, Model
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
...@@ -8,6 +8,8 @@ from django.contrib.contenttypes.models import ContentType ...@@ -8,6 +8,8 @@ from django.contrib.contenttypes.models import ContentType
from django_notify import settings from django_notify import settings
_disable_notifications = False
class NotificationType(models.Model): class NotificationType(models.Model):
""" """
Notification types are added on-the-fly by the Notification types are added on-the-fly by the
...@@ -105,3 +107,36 @@ class Notification(models.Model): ...@@ -105,3 +107,36 @@ class Notification(models.Model):
db_table = settings.DB_TABLE_PREFIX + '_notification' db_table = settings.DB_TABLE_PREFIX + '_notification'
verbose_name = _(u'notification') verbose_name = _(u'notification')
verbose_name_plural = _(u'notifications') verbose_name_plural = _(u'notifications')
def notify(message, key, target_object=None, url=None):
"""
Notify subscribing users of a new event. Key can be any kind of string,
just make sure to reuse it where applicable! Object_id is some identifier
of an object, for instance if a user subscribes to a specific comment thread,
you could write:
notify("there was a response to your comment", "comment_response",
target_object=PostersObject,
url=reverse('comments:view', args=(PostersObject.id,)))
The below example notifies everyone subscribing to the "new_comments" key
with the message "New comment posted".
notify("New comment posted", "new_comments")
"""
if _disable_notifications:
return 0
if target_object:
if not isinstance(target_object, Model):
raise TypeError(_(u"You supplied a target_object that's not an instance of a django Model."))
object_id = target_object.id
else:
object_id = None
objects = Notification.create_notifications(key, object_id=object_id,
message=message, url=url)
return len(objects)
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.conf.urls import patterns, url from django.conf.urls import url
from django_notify import views
urlpatterns = patterns('', urlpatterns = [
url('^json/get/$', 'django_notify.views.get_notifications', name='json_get', kwargs={}), url('^json/get/$', views.get_notifications, name='json_get', kwargs={}),
url('^json/mark-read/$', 'django_notify.views.mark_read', name='json_mark_read_base', kwargs={}), url('^json/mark-read/$', views.mark_read, name='json_mark_read_base', kwargs={}),
url('^json/mark-read/(\d+)/$', 'django_notify.views.mark_read', name='json_mark_read', kwargs={}), url('^json/mark-read/(\d+)/$', views.mark_read, name='json_mark_read', kwargs={}),
url('^goto/(?P<notification_id>\d+)/$', 'django_notify.views.goto', name='goto', kwargs={}), url('^goto/(?P<notification_id>\d+)/$', views.goto, name='goto', kwargs={}),
url('^goto/$', 'django_notify.views.goto', name='goto_base', kwargs={}), url('^goto/$', views.goto, name='goto_base', kwargs={}),
) ]
def get_pattern(app_name="notify", namespace="notify"): def get_pattern(app_name="notify", namespace="notify"):
"""Every url resolution takes place as "notify:view_name". """Every url resolution takes place as "notify:view_name".
......
django<1.9 django>=1.8,<2.0
South==1.0.1 Markdown>=2.6,<2.7
Markdown<2.3.0 django-sekizai>=0.10
django-sekizai<0.7 django-mptt>=0.8.6,<0.9
django-mptt<0.8 sorl-thumbnail>=12,<13
sorl-thumbnail<13 six>=1.10.0,<2.0.0
\ No newline at end of file
...@@ -29,7 +29,7 @@ package_data = dict( ...@@ -29,7 +29,7 @@ package_data = dict(
setup( setup(
name = "django-wiki", name = "django-wiki",
version = "0.0.10", version="0.0.11",
author = "Benjamin Bach", author = "Benjamin Bach",
author_email = "benjamin@overtag.dk", author_email = "benjamin@overtag.dk",
description = ("A wiki system written for the Django framework."), description = ("A wiki system written for the Django framework."),
...@@ -39,7 +39,7 @@ setup( ...@@ -39,7 +39,7 @@ setup(
long_description=read('README.md'), long_description=read('README.md'),
zip_safe = False, zip_safe = False,
install_requires=[ install_requires=[
'Django>=1.4', 'Django>=1.8',
'markdown', 'markdown',
'django-sekizai', 'django-sekizai',
'django-mptt', 'django-mptt',
......
...@@ -3,7 +3,6 @@ from os import path as os_path ...@@ -3,7 +3,6 @@ from os import path as os_path
PROJECT_PATH = os_path.abspath(os_path.split(__file__)[0]) PROJECT_PATH = os_path.abspath(os_path.split(__file__)[0])
DEBUG = True DEBUG = True
TEMPLATE_DEBUG = DEBUG
ADMINS = ( ADMINS = (
# ('Your Name', 'your_email@example.com'), # ('Your Name', 'your_email@example.com'),
...@@ -47,22 +46,9 @@ MEDIA_URL = '/media/' ...@@ -47,22 +46,9 @@ MEDIA_URL = '/media/'
STATIC_ROOT = os_path.join(PROJECT_PATH, 'static') STATIC_ROOT = os_path.join(PROJECT_PATH, 'static')
STATIC_URL = '/static/' STATIC_URL = '/static/'
STATICFILES_DIRS = (
)
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
)
SECRET_KEY = 'b^fv_)t39h%9p40)fnkfblo##jkr!$0)lkp6bpy!fi*f$4*92!' SECRET_KEY = 'b^fv_)t39h%9p40)fnkfblo##jkr!$0)lkp6bpy!fi*f$4*92!'
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
# 'django.template.loaders.eggs.Loader',
)
MIDDLEWARE_CLASSES = ( MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware', 'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware',
...@@ -79,22 +65,31 @@ ROOT_URLCONF = 'testproject.urls' ...@@ -79,22 +65,31 @@ ROOT_URLCONF = 'testproject.urls'
# Python dotted path to the WSGI application used by Django's runserver. # Python dotted path to the WSGI application used by Django's runserver.
WSGI_APPLICATION = 'testproject.wsgi.application' WSGI_APPLICATION = 'testproject.wsgi.application'
TEMPLATE_DIRS = ( TEMPLATES = [
'templates', {
) 'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
TEMPLATE_CONTEXT_PROCESSORS =( os_path.join(PROJECT_PATH, 'templates'),
'django.contrib.auth.context_processors.auth', ],
'django.core.context_processors.debug', 'APP_DIRS': True,
'django.core.context_processors.i18n', 'OPTIONS': {
'django.core.context_processors.media', 'context_processors': [
'django.core.context_processors.static', "django.contrib.auth.context_processors.auth",
'django.core.context_processors.tz', "django.template.context_processors.debug",
'django.contrib.messages.context_processors.messages', "django.template.context_processors.i18n",
'sekizai.context_processors.sekizai', "django.template.context_processors.media",
) "django.template.context_processors.static",
"django.template.context_processors.request",
"django.template.context_processors.tz",
"django.contrib.messages.context_processors.messages",
"sekizai.context_processors.sekizai",
],
'debug': DEBUG,
},
},
]
INSTALLED_APPS = ( INSTALLED_APPS = [
'django.contrib.humanize', 'django.contrib.humanize',
'django.contrib.auth', 'django.contrib.auth',
'django.contrib.contenttypes', 'django.contrib.contenttypes',
...@@ -114,7 +109,7 @@ INSTALLED_APPS = ( ...@@ -114,7 +109,7 @@ INSTALLED_APPS = (
'wiki.plugins.attachments', 'wiki.plugins.attachments',
'wiki.plugins.notifications', 'wiki.plugins.notifications',
'mptt', 'mptt',
) ]
# A sample logging configuration. The only tangible logging # A sample logging configuration. The only tangible logging
# performed by this configuration is to send an email to # performed by this configuration is to send an email to
...@@ -146,3 +141,6 @@ LOGGING = { ...@@ -146,3 +141,6 @@ LOGGING = {
} }
WIKI_ANONYMOUS_WRITE = True WIKI_ANONYMOUS_WRITE = True
# We disable this in edx-platform lms/envs/common.py, so disabling for test project also.
WIKI_USE_BOOTSTRAP_SELECT_WIDGET = False
from django.conf.urls import patterns, include, url from django.conf.urls import include, url
from django.conf import settings from django.conf import settings
from django.contrib.staticfiles.urls import staticfiles_urlpatterns from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.views.static import serve as static_serve
from django.contrib import admin from django.contrib import admin
admin.autodiscover() admin.autodiscover()
urlpatterns = patterns('', urlpatterns = [
url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
url(r'^admin/', include(admin.site.urls)), url(r'^admin/', include(admin.site.urls)),
url(r'^notify/', include('django_notify.urls', namespace='notify')), ]
)
if settings.DEBUG: if settings.DEBUG:
urlpatterns += staticfiles_urlpatterns() urlpatterns += staticfiles_urlpatterns()
urlpatterns += patterns('', urlpatterns += [
url(r'^media/(?P<path>.*)$', 'django.views.static.serve', { url(r'^media/(?P<path>.*)$', static_serve, {'document_root': settings.MEDIA_ROOT}),
'document_root': settings.MEDIA_ROOT, ]
}),
)
from wiki.urls import get_pattern as get_wiki_pattern from wiki.urls import get_pattern as get_wiki_pattern
from django_notify.urls import get_pattern as get_notify_pattern from django_notify.urls import get_pattern as get_notify_pattern
urlpatterns += patterns('',
(r'^notify/', get_notify_pattern()), urlpatterns += [
(r'', get_wiki_pattern()) url(r'^notify/', get_notify_pattern()),
) url(r'', get_wiki_pattern()),
\ No newline at end of file ]
...@@ -6,7 +6,6 @@ from django.core.urlresolvers import reverse_lazy ...@@ -6,7 +6,6 @@ from django.core.urlresolvers import reverse_lazy
URL_CASE_SENSITIVE = getattr(django_settings, 'WIKI_URL_CASE_SENSITIVE', False) URL_CASE_SENSITIVE = getattr(django_settings, 'WIKI_URL_CASE_SENSITIVE', False)
# Non-configurable (at the moment) # Non-configurable (at the moment)
APP_LABEL = 'wiki'
WIKI_LANGUAGE = 'markdown' WIKI_LANGUAGE = 'markdown'
# The editor class to use -- maybe a 3rd party or your own...? You can always # The editor class to use -- maybe a 3rd party or your own...? You can always
......
# Django 1.11 Widget.build_attrs has a different signature, designed for the new
# template based rendering. The previous version was more useful for our needs,
# so we restore that version.
# When support for Django < 1.11 is dropped, we should look at using the
# new template based rendering, at which point this probably won't be needed at all.
class BuildAttrsCompat(object):
def build_attrs_compat(self, extra_attrs=None, **kwargs):
"Helper function for building an attribute dictionary."
attrs = self.attrs.copy()
if extra_attrs is not None:
attrs.update(extra_attrs)
if kwargs is not None:
attrs.update(kwargs)
return attrs
...@@ -24,9 +24,9 @@ def response_forbidden(request, article, urlpath): ...@@ -24,9 +24,9 @@ def response_forbidden(request, article, urlpath):
if request.user.is_anonymous(): if request.user.is_anonymous():
return redirect(django_settings.LOGIN_URL) return redirect(django_settings.LOGIN_URL)
else: else:
c = RequestContext(request, {'article': article, return HttpResponseForbidden(
'urlpath' : urlpath}) render_to_string("wiki/permission_denied.html", context={'article': article, 'urlpath': urlpath},
return HttpResponseForbidden(render_to_string("wiki/permission_denied.html", context_instance=c)) request=request))
def get_article(func=None, can_read=True, can_write=False, def get_article(func=None, can_read=True, can_write=False,
deleted_contents=False, not_locked=False, deleted_contents=False, not_locked=False,
...@@ -75,8 +75,9 @@ def get_article(func=None, can_read=True, can_write=False, ...@@ -75,8 +75,9 @@ def get_article(func=None, can_read=True, can_write=False,
parent = models.URLPath.get_by_path(path) parent = models.URLPath.get_by_path(path)
return redirect(reverse("wiki:create", kwargs={'path': parent.path,}) + "?slug=%s" % pathlist[-1]) return redirect(reverse("wiki:create", kwargs={'path': parent.path,}) + "?slug=%s" % pathlist[-1])
except models.URLPath.DoesNotExist: except models.URLPath.DoesNotExist:
c = RequestContext(request, {'error_type' : 'ancestors_missing'}) return HttpResponseNotFound(
return HttpResponseNotFound(render_to_string("wiki/error.html", context_instance=c)) render_to_string("wiki/error.html", context={'error_type': 'ancestors_missing'},
request=request))
if urlpath.article: if urlpath.article:
# urlpath is already smart about prefetching items on article (like current_revision), so we don't have to # urlpath is already smart about prefetching items on article (like current_revision), so we don't have to
article = urlpath.article article = urlpath.article
......
...@@ -4,9 +4,11 @@ from django.utils.encoding import force_unicode ...@@ -4,9 +4,11 @@ from django.utils.encoding import force_unicode
from django.utils.html import conditional_escape from django.utils.html import conditional_escape
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from wiki.core.compat import BuildAttrsCompat
from wiki.editors.base import BaseEditor from wiki.editors.base import BaseEditor
class MarkItUpAdminWidget(forms.Widget):
class MarkItUpAdminWidget(BuildAttrsCompat, forms.Widget):
"""A simplified more fail-safe widget for the backend""" """A simplified more fail-safe widget for the backend"""
def __init__(self, attrs=None): def __init__(self, attrs=None):
# The 'rows' and 'cols' attributes are required for HTML correctness. # The 'rows' and 'cols' attributes are required for HTML correctness.
...@@ -18,11 +20,12 @@ class MarkItUpAdminWidget(forms.Widget): ...@@ -18,11 +20,12 @@ class MarkItUpAdminWidget(forms.Widget):
def render(self, name, value, attrs=None): def render(self, name, value, attrs=None):
if value is None: value = '' if value is None: value = ''
final_attrs = self.build_attrs(attrs, name=name) final_attrs = self.build_attrs_compat(attrs, name=name)
return mark_safe(u'<textarea%s>%s</textarea>' % (flatatt(final_attrs), return mark_safe(u'<textarea%s>%s</textarea>' % (flatatt(final_attrs),
conditional_escape(force_unicode(value)))) conditional_escape(force_unicode(value))))
class MarkItUpWidget(forms.Widget):
class MarkItUpWidget(BuildAttrsCompat, forms.Widget):
def __init__(self, attrs=None): def __init__(self, attrs=None):
# The 'rows' and 'cols' attributes are required for HTML correctness. # The 'rows' and 'cols' attributes are required for HTML correctness.
default_attrs = {'class': 'markItUp', default_attrs = {'class': 'markItUp',
...@@ -33,7 +36,7 @@ class MarkItUpWidget(forms.Widget): ...@@ -33,7 +36,7 @@ class MarkItUpWidget(forms.Widget):
def render(self, name, value, attrs=None): def render(self, name, value, attrs=None):
if value is None: value = '' if value is None: value = ''
final_attrs = self.build_attrs(attrs, name=name) final_attrs = self.build_attrs_compat(attrs, name=name)
return mark_safe(u'<div><textarea%s>%s</textarea></div>' % (flatatt(final_attrs), return mark_safe(u'<div><textarea%s>%s</textarea></div>' % (flatatt(final_attrs),
conditional_escape(force_unicode(value)))) conditional_escape(force_unicode(value))))
......
...@@ -16,6 +16,7 @@ from django.forms.widgets import HiddenInput ...@@ -16,6 +16,7 @@ from django.forms.widgets import HiddenInput
from wiki.core.plugins.base import PluginSettingsFormMixin from wiki.core.plugins.base import PluginSettingsFormMixin
from django.contrib.auth.models import User from django.contrib.auth.models import User
from wiki.core import permissions from wiki.core import permissions
from wiki.core.compat import BuildAttrsCompat
class SpamProtectionMixin(): class SpamProtectionMixin():
...@@ -100,7 +101,7 @@ class EditForm(forms.Form): ...@@ -100,7 +101,7 @@ class EditForm(forms.Form):
return cd return cd
class SelectWidgetBootstrap(forms.Select): class SelectWidgetBootstrap(BuildAttrsCompat, forms.Select):
""" """
http://twitter.github.com/bootstrap/components.html#buttonDropdowns http://twitter.github.com/bootstrap/components.html#buttonDropdowns
Needs bootstrap and jquery Needs bootstrap and jquery
...@@ -143,7 +144,7 @@ class SelectWidgetBootstrap(forms.Select): ...@@ -143,7 +144,7 @@ class SelectWidgetBootstrap(forms.Select):
def render(self, name, value, attrs=None, choices=()): def render(self, name, value, attrs=None, choices=()):
if value is None: value = '' if value is None: value = ''
final_attrs = self.build_attrs(attrs, name=name) final_attrs = self.build_attrs_compat(attrs, name=name)
output = ["""<div%(attrs)s>""" output = ["""<div%(attrs)s>"""
""" <button class="btn btn-group-label" type="button">%(label)s</button>""" """ <button class="btn btn-group-label" type="button">%(label)s</button>"""
""" <button class="btn dropdown-toggle" type="button" data-toggle="dropdown">""" """ <button class="btn dropdown-toggle" type="button" data-toggle="dropdown">"""
......
...@@ -2,11 +2,12 @@ ...@@ -2,11 +2,12 @@
from django.conf import settings as django_settings from django.conf import settings as django_settings
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
import warnings from six import string_types, text_type
# TODO: Don't use wildcards # TODO: Don't use wildcards
from article import * from article import *
from urlpath import * from urlpath import *
from django.utils.functional import lazy
# TODO: Should the below stuff be executed a more logical place? # TODO: Should the below stuff be executed a more logical place?
...@@ -29,8 +30,24 @@ if not 'django.contrib.humanize' in django_settings.INSTALLED_APPS: ...@@ -29,8 +30,24 @@ if not 'django.contrib.humanize' in django_settings.INSTALLED_APPS:
if not 'django.contrib.contenttypes' in django_settings.INSTALLED_APPS: if not 'django.contrib.contenttypes' in django_settings.INSTALLED_APPS:
raise ImproperlyConfigured('django-wiki: needs django.contrib.contenttypes in INSTALLED_APPS') raise ImproperlyConfigured('django-wiki: needs django.contrib.contenttypes in INSTALLED_APPS')
if not 'django.contrib.auth.context_processors.auth' in django_settings.TEMPLATE_CONTEXT_PROCESSORS: # Need to handle Django 1.8 'TEMPLATES', recognizing that users may still be
raise ImproperlyConfigured('django-wiki: needs django.contrib.auth.context_processors.auth in TEMPLATE_CONTEXT_PROCESSORS') # using 1.7 conventions/settings with 1.8.
TEMPLATE_CONTEXT_PROCESSORS = getattr(django_settings, 'TEMPLATE_CONTEXT_PROCESSORS', [])
if hasattr(django_settings, 'TEMPLATES'):
# Django 1.8 compat
backends = [b for b in django_settings.TEMPLATES if
b.get('BACKEND', '') == 'django.template.backends.django.DjangoTemplates']
if len(backends) == 1:
TEMPLATE_CONTEXT_PROCESSORS = backends[0].get('OPTIONS', {}).get('context_processors', [])
if 'django.contrib.auth.context_processors.auth' not in TEMPLATE_CONTEXT_PROCESSORS:
raise ImproperlyConfigured(
'django-wiki: needs django.contrib.auth.context_processors.auth in TEMPLATE_CONTEXT_PROCESSORS')
if not any(s in TEMPLATE_CONTEXT_PROCESSORS for s in ['django.core.context_processors.request',
'django.template.context_processors.request']):
raise ImproperlyConfigured(
'django-wiki: needs django.core.context_processors.request or django.template.context_processors.request in TEMPLATE_CONTEXT_PROCESSORS')
###################### ######################
...@@ -56,7 +73,7 @@ def reverse(*args, **kwargs): ...@@ -56,7 +73,7 @@ def reverse(*args, **kwargs):
return the result of calling reverse._transform_url(reversed_url) return the result of calling reverse._transform_url(reversed_url)
for every url in the wiki namespace. for every url in the wiki namespace.
""" """
if isinstance(args[0], basestring) and args[0].startswith('wiki:'): if isinstance(args[0], string_types) and args[0].startswith('wiki:'):
url_kwargs = kwargs.get('kwargs', {}) url_kwargs = kwargs.get('kwargs', {})
path = url_kwargs.get('path', False) path = url_kwargs.get('path', False)
# If a path is supplied then discard the article_id # If a path is supplied then discard the article_id
...@@ -72,6 +89,23 @@ def reverse(*args, **kwargs): ...@@ -72,6 +89,23 @@ def reverse(*args, **kwargs):
url = original_django_reverse(*args, **kwargs) url = original_django_reverse(*args, **kwargs)
return url return url
# Now we redefine reverse method # Now we redefine reverse method
urlresolvers.reverse = reverse reverse_lazy = lazy(reverse, text_type)
\ No newline at end of file urlresolvers.reverse = reverse
urlresolvers.reverse_lazy = reverse_lazy
# Patch up other locations of the reverse function
try:
from django.urls import base
from django import urls
from django import shortcuts
base.reverse = reverse
base.reverse_lazy = reverse_lazy
urls.reverse = reverse
urls.reverse_lazy = reverse_lazy
shortcuts.reverse = reverse
except ImportError:
pass
...@@ -169,7 +169,6 @@ class Article(models.Model): ...@@ -169,7 +169,6 @@ class Article(models.Model):
return _(u'Article without content (%(id)d)') % {'id': self.id} return _(u'Article without content (%(id)d)') % {'id': self.id}
class Meta: class Meta:
app_label = settings.APP_LABEL
permissions = ( permissions = (
("moderate", "Can edit all articles and lock/unlock/restore"), ("moderate", "Can edit all articles and lock/unlock/restore"),
("assign", "Can change ownership of any article"), ("assign", "Can change ownership of any article"),
...@@ -203,7 +202,6 @@ class ArticleForObject(models.Model): ...@@ -203,7 +202,6 @@ class ArticleForObject(models.Model):
is_mptt = models.BooleanField(default=False, editable=False) is_mptt = models.BooleanField(default=False, editable=False)
class Meta: class Meta:
app_label = settings.APP_LABEL
verbose_name = _(u'Article for object') verbose_name = _(u'Article for object')
verbose_name_plural = _(u'Articles for object') verbose_name_plural = _(u'Articles for object')
# Do not allow several objects # Do not allow several objects
...@@ -311,7 +309,6 @@ class ArticleRevision(BaseRevisionMixin, models.Model): ...@@ -311,7 +309,6 @@ class ArticleRevision(BaseRevisionMixin, models.Model):
self.article.save() self.article.save()
class Meta: class Meta:
app_label = settings.APP_LABEL
get_latest_by = 'revision_number' get_latest_by = 'revision_number'
ordering = ('created',) ordering = ('created',)
unique_together = ('article', 'revision_number') unique_together = ('article', 'revision_number')
......
...@@ -27,7 +27,6 @@ There are three kinds of plugin base models: ...@@ -27,7 +27,6 @@ There are three kinds of plugin base models:
from article import Article, ArticleRevision from article import Article, ArticleRevision
from wiki.conf import settings
class ArticlePlugin(models.Model): class ArticlePlugin(models.Model):
"""This is the mother of all plugins. Extending from it means a deletion """This is the mother of all plugins. Extending from it means a deletion
...@@ -55,10 +54,8 @@ class ArticlePlugin(models.Model): ...@@ -55,10 +54,8 @@ class ArticlePlugin(models.Model):
def purge(self): def purge(self):
"""Remove related contents completely, ie. media files.""" """Remove related contents completely, ie. media files."""
pass pass
class Meta:
app_label = settings.APP_LABEL
class ReusablePlugin(ArticlePlugin): class ReusablePlugin(ArticlePlugin):
"""Extend from this model if you have a plugin that may be related to many """Extend from this model if you have a plugin that may be related to many
articles. Please note that the ArticlePlugin.article ForeignKey STAYS! This articles. Please note that the ArticlePlugin.article ForeignKey STAYS! This
...@@ -101,9 +98,7 @@ class ReusablePlugin(ArticlePlugin): ...@@ -101,9 +98,7 @@ class ReusablePlugin(ArticlePlugin):
self.article = articles[0] self.article = articles[0]
super(ReusablePlugin, self).save(*args, **kwargs) super(ReusablePlugin, self).save(*args, **kwargs)
class Meta:
app_label = settings.APP_LABEL
class SimplePluginCreateError(Exception): pass class SimplePluginCreateError(Exception): pass
...@@ -148,9 +143,7 @@ class SimplePlugin(ArticlePlugin): ...@@ -148,9 +143,7 @@ class SimplePlugin(ArticlePlugin):
self.article_revision = new_revision self.article_revision = new_revision
super(SimplePlugin, self).save(*args, **kwargs) super(SimplePlugin, self).save(*args, **kwargs)
class Meta:
app_label = settings.APP_LABEL
class RevisionPlugin(ArticlePlugin): class RevisionPlugin(ArticlePlugin):
""" """
...@@ -188,8 +181,6 @@ class RevisionPlugin(ArticlePlugin): ...@@ -188,8 +181,6 @@ class RevisionPlugin(ArticlePlugin):
self.current_revision = new_revision self.current_revision = new_revision
if save: self.save() if save: self.save()
class Meta:
app_label = settings.APP_LABEL
class RevisionPluginRevision(BaseRevisionMixin, models.Model): class RevisionPluginRevision(BaseRevisionMixin, models.Model):
...@@ -226,7 +217,6 @@ class RevisionPluginRevision(BaseRevisionMixin, models.Model): ...@@ -226,7 +217,6 @@ class RevisionPluginRevision(BaseRevisionMixin, models.Model):
self.plugin.save() self.plugin.save()
class Meta: class Meta:
app_label = settings.APP_LABEL
get_latest_by = 'revision_number' get_latest_by = 'revision_number'
ordering = ('-created',) ordering = ('-created',)
......
...@@ -33,7 +33,6 @@ class URLPath(MPTTModel): ...@@ -33,7 +33,6 @@ class URLPath(MPTTModel):
INHERIT_PERMISSIONS = True INHERIT_PERMISSIONS = True
objects = managers.URLPathManager() objects = managers.URLPathManager()
_default_manager = objects
articles = fields.GenericRelation(ArticleForObject) articles = fields.GenericRelation(ArticleForObject)
...@@ -148,7 +147,6 @@ class URLPath(MPTTModel): ...@@ -148,7 +147,6 @@ class URLPath(MPTTModel):
verbose_name = _(u'URL path') verbose_name = _(u'URL path')
verbose_name_plural = _(u'URL paths') verbose_name_plural = _(u'URL paths')
unique_together = ('site', 'parent', 'slug') unique_together = ('site', 'parent', 'slug')
app_label = settings.APP_LABEL
def clean(self, *args, **kwargs): def clean(self, *args, **kwargs):
if self.slug and not self.parent: if self.slug and not self.parent:
......
...@@ -35,7 +35,6 @@ class Attachment(ReusablePlugin): ...@@ -35,7 +35,6 @@ class Attachment(ReusablePlugin):
class Meta: class Meta:
verbose_name = _(u'attachment') verbose_name = _(u'attachment')
verbose_name_plural = _(u'attachments') verbose_name_plural = _(u'attachments')
app_label = settings.APP_LABEL
def __unicode__(self): def __unicode__(self):
return "%s: %s" % (self.article.current_revision.title, self.original_filename) return "%s: %s" % (self.article.current_revision.title, self.original_filename)
...@@ -86,7 +85,6 @@ class AttachmentRevision(BaseRevisionMixin, models.Model): ...@@ -86,7 +85,6 @@ class AttachmentRevision(BaseRevisionMixin, models.Model):
verbose_name_plural = _(u'attachment revisions') verbose_name_plural = _(u'attachment revisions')
ordering = ('created',) ordering = ('created',)
get_latest_by = 'revision_number' get_latest_by = 'revision_number'
app_label = settings.APP_LABEL
def get_filename(self): def get_filename(self):
"""Used to retrieve the filename of a revision. """Used to retrieve the filename of a revision.
......
from django.conf import settings as django_settings from django.conf import settings as django_settings
APP_LABEL = 'wiki'
SLUG = "attachments" SLUG = "attachments"
# Allow anonymous users to upload (not nice on an open network) # Allow anonymous users to upload (not nice on an open network)
......
{% extends "wiki/article.html" %} {% extends "wiki/article.html" %}
{% load wiki_tags i18n humanize %} {% load wiki_tags i18n humanize %}
{% load url from future %}
{% block pagetitle %}{% trans "Delete" %} "{{ attachment.current_revision.get_filename }}"{% endblock %} {% block pagetitle %}{% trans "Delete" %} "{{ attachment.current_revision.get_filename }}"{% endblock %}
......
{% extends "wiki/article.html" %} {% extends "wiki/article.html" %}
{% load wiki_tags i18n humanize %} {% load wiki_tags i18n humanize %}
{% load url from future %}
{% block pagetitle %}{% trans "History of" %} "{{ attachment.current_revision.get_filename }}"{% endblock %} {% block pagetitle %}{% trans "History of" %} "{{ attachment.current_revision.get_filename }}"{% endblock %}
......
{% extends "wiki/article.html" %} {% extends "wiki/article.html" %}
{% load wiki_tags i18n humanize %} {% load wiki_tags i18n humanize %}
{% load url from future %}
{% block pagetitle %}{% trans "Attachments" %}: {{ article.current_revision.title }}{% endblock %} {% block pagetitle %}{% trans "Attachments" %}: {{ article.current_revision.title }}{% endblock %}
...@@ -32,7 +31,7 @@ ...@@ -32,7 +31,7 @@
<p> <p>
{% if not attachment.current_revision.deleted %} {% if not attachment.current_revision.deleted %}
<a href="{% url 'wiki:attachments_replace' path=urlpath.path article_id=article.id attachment_id=attachment.id %}" class="btn">{% trans "Replace" %}</a> <a href="{% url 'wiki:attachments_replace' path=urlpath.path article_id=article.id attachment_id=attachment.id %}" class="btn">{% trans "Replace" %}</a>
{% if attachment.article = article %} {% if 'attachment.article = article' %}
<a href="{% url 'wiki:attachments_delete' path=urlpath.path article_id=article.id attachment_id=attachment.id %}" class="btn">{% trans "Delete" %}</a> <a href="{% url 'wiki:attachments_delete' path=urlpath.path article_id=article.id attachment_id=attachment.id %}" class="btn">{% trans "Delete" %}</a>
{% else %} {% else %}
<a href="{% url 'wiki:attachments_delete' path=urlpath.path article_id=article.id attachment_id=attachment.id %}" class="btn">{% trans "Detach" %}</a> <a href="{% url 'wiki:attachments_delete' path=urlpath.path article_id=article.id attachment_id=attachment.id %}" class="btn">{% trans "Detach" %}</a>
......
{% extends "wiki/article.html" %} {% extends "wiki/article.html" %}
{% load wiki_tags i18n humanize %} {% load wiki_tags i18n humanize %}
{% load url from future %}
{% block pagetitle %}{% trans "Replace" %} "{{ attachment.current_revision.get_filename }}"{% endblock %} {% block pagetitle %}{% trans "Replace" %} "{{ attachment.current_revision.get_filename }}"{% endblock %}
......
{% extends "wiki/article.html" %} {% extends "wiki/article.html" %}
{% load wiki_tags i18n humanize %} {% load wiki_tags i18n humanize %}
{% load url from future %}
{% block pagetitle %}{% trans "Add file to" %} "{{ article.current_revision.title }}"{% endblock %} {% block pagetitle %}{% trans "Add file to" %} "{{ article.current_revision.title }}"{% endblock %}
......
...@@ -55,6 +55,11 @@ class AttachmentView(ArticleMixin, FormView): ...@@ -55,6 +55,11 @@ class AttachmentView(ArticleMixin, FormView):
return redirect("wiki:attachments_index", path=self.urlpath.path, article_id=self.article.id) return redirect("wiki:attachments_index", path=self.urlpath.path, article_id=self.article.id)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
# Needed since Django 1.9 because get_context_data is no longer called
# with the form instance
if 'form' not in kwargs:
kwargs['form'] = self.get_form()
kwargs['attachments'] = self.attachments kwargs['attachments'] = self.attachments
kwargs['search_form'] = forms.SearchForm() kwargs['search_form'] = forms.SearchForm()
kwargs['selected_tab'] = 'attachments' kwargs['selected_tab'] = 'attachments'
...@@ -127,6 +132,8 @@ class AttachmentReplaceView(ArticleMixin, FormView): ...@@ -127,6 +132,8 @@ class AttachmentReplaceView(ArticleMixin, FormView):
return {'description': self.attachment.current_revision.description} return {'description': self.attachment.current_revision.description}
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
if 'form' not in kwargs:
kwargs['form'] = self.get_form()
kwargs['attachment'] = self.attachment kwargs['attachment'] = self.attachment
kwargs['selected_tab'] = 'attachments' kwargs['selected_tab'] = 'attachments'
return super(AttachmentReplaceView, self).get_context_data(**kwargs) return super(AttachmentReplaceView, self).get_context_data(**kwargs)
...@@ -178,6 +185,8 @@ class AttachmentChangeRevisionView(ArticleMixin, View): ...@@ -178,6 +185,8 @@ class AttachmentChangeRevisionView(ArticleMixin, View):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs['selected_tab'] = 'attachments' kwargs['selected_tab'] = 'attachments'
if 'form' not in kwargs:
kwargs['form'] = self.get_form()
return ArticleMixin.get_context_data(self, **kwargs) return ArticleMixin.get_context_data(self, **kwargs)
class AttachmentAddView(ArticleMixin, View): class AttachmentAddView(ArticleMixin, View):
...@@ -231,6 +240,8 @@ class AttachmentDeleteView(ArticleMixin, FormView): ...@@ -231,6 +240,8 @@ class AttachmentDeleteView(ArticleMixin, FormView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs['attachment'] = self.attachment kwargs['attachment'] = self.attachment
kwargs['selected_tab'] = 'attachments' kwargs['selected_tab'] = 'attachments'
if 'form' not in kwargs:
kwargs['form'] = self.get_form()
return super(AttachmentDeleteView, self).get_context_data(**kwargs) return super(AttachmentDeleteView, self).get_context_data(**kwargs)
...@@ -265,4 +276,6 @@ class AttachmentSearchView(ArticleMixin, ListView): ...@@ -265,4 +276,6 @@ class AttachmentSearchView(ArticleMixin, ListView):
kwargs.update(kwargs_article) kwargs.update(kwargs_article)
kwargs.update(kwargs_listview) kwargs.update(kwargs_listview)
kwargs['selected_tab'] = 'attachments' kwargs['selected_tab'] = 'attachments'
if 'form' not in kwargs:
kwargs['form'] = self.get_form()
return kwargs return kwargs
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.conf.urls import patterns, url from django.conf.urls import url
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from wiki.core.plugins import registry from wiki.core.plugins import registry
...@@ -15,7 +15,7 @@ class AttachmentPlugin(BasePlugin): ...@@ -15,7 +15,7 @@ class AttachmentPlugin(BasePlugin):
#settings_form = 'wiki.plugins.notifications.forms.SubscriptionForm' #settings_form = 'wiki.plugins.notifications.forms.SubscriptionForm'
slug = settings.SLUG slug = settings.SLUG
urlpatterns = patterns('', urlpatterns = [
url(r'^$', views.AttachmentView.as_view(), name='attachments_index'), url(r'^$', views.AttachmentView.as_view(), name='attachments_index'),
url(r'^search/$', views.AttachmentSearchView.as_view(), name='attachments_search'), url(r'^search/$', views.AttachmentSearchView.as_view(), name='attachments_search'),
url(r'^add/(?P<attachment_id>\d+)/$', views.AttachmentAddView.as_view(), name='attachments_add'), url(r'^add/(?P<attachment_id>\d+)/$', views.AttachmentAddView.as_view(), name='attachments_add'),
...@@ -25,7 +25,7 @@ class AttachmentPlugin(BasePlugin): ...@@ -25,7 +25,7 @@ class AttachmentPlugin(BasePlugin):
url(r'^delete/(?P<attachment_id>\d+)/$', views.AttachmentDeleteView.as_view(), name='attachments_delete'), url(r'^delete/(?P<attachment_id>\d+)/$', views.AttachmentDeleteView.as_view(), name='attachments_delete'),
url(r'^download/(?P<attachment_id>\d+)/revision/(?P<revision_id>\d+)/$', views.AttachmentDownloadView.as_view(), name='attachments_download'), url(r'^download/(?P<attachment_id>\d+)/revision/(?P<revision_id>\d+)/$', views.AttachmentDownloadView.as_view(), name='attachments_download'),
url(r'^change/(?P<attachment_id>\d+)/revision/(?P<revision_id>\d+)/$', views.AttachmentChangeRevisionView.as_view(), name='attachments_revision_change'), url(r'^change/(?P<attachment_id>\d+)/revision/(?P<revision_id>\d+)/$', views.AttachmentChangeRevisionView.as_view(), name='attachments_revision_change'),
) ]
article_tab = (_(u'Attachments'), "icon-file") article_tab = (_(u'Attachments'), "icon-file")
article_view = views.AttachmentView().dispatch article_view = views.AttachmentView().dispatch
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.conf.urls import patterns
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from wiki.core.plugins import registry from wiki.core.plugins import registry
...@@ -8,7 +7,7 @@ from wiki.core.plugins.base import BasePlugin ...@@ -8,7 +7,7 @@ from wiki.core.plugins.base import BasePlugin
class HelpPlugin(BasePlugin): class HelpPlugin(BasePlugin):
slug = 'help' slug = 'help'
urlpatterns = patterns('',) urlpatterns = []
sidebar = {'headline': _('Help'), sidebar = {'headline': _('Help'),
'icon_class': 'icon-question-sign', 'icon_class': 'icon-question-sign',
......
...@@ -45,12 +45,16 @@ class ImagePreprocessor(markdown.preprocessors.Preprocessor): ...@@ -45,12 +45,16 @@ class ImagePreprocessor(markdown.preprocessors.Preprocessor):
caption_lines.append(line[4:]) caption_lines.append(line[4:])
line = None line = None
else: else:
html = render_to_string("wiki/plugins/images/render.html", html = render_to_string(
Context({'image': image, "wiki/plugins/images/render.html",
'caption': article_markdown("\n".join(caption_lines), context={
self.markdown.article, 'image': image,
extensions=self.markdown.registeredExtensions), 'caption': article_markdown("\n".join(caption_lines),
'align': alignment})) self.markdown.article,
extensions=self.markdown.registeredExtensions),
'align': alignment
}
)
line = html + line line = html + line
previous_line_was_image = False previous_line_was_image = False
if not line is None: if not line is None:
......
...@@ -39,7 +39,6 @@ class Image(RevisionPlugin): ...@@ -39,7 +39,6 @@ class Image(RevisionPlugin):
class Meta: class Meta:
verbose_name = _(u'image') verbose_name = _(u'image')
verbose_name_plural = _(u'images') verbose_name_plural = _(u'images')
app_label = settings.APP_LABEL
def __unicode__(self): def __unicode__(self):
title = (_(u'Image: %s') % self.current_revision.imagerevision.get_filename()) if self.current_revision else _(u'Current revision not set!!') title = (_(u'Image: %s') % self.current_revision.imagerevision.get_filename()) if self.current_revision else _(u'Current revision not set!!')
...@@ -91,7 +90,6 @@ class ImageRevision(RevisionPluginRevision): ...@@ -91,7 +90,6 @@ class ImageRevision(RevisionPluginRevision):
class Meta: class Meta:
verbose_name = _(u'image revision') verbose_name = _(u'image revision')
verbose_name_plural = _(u'image revisions') verbose_name_plural = _(u'image revisions')
app_label = settings.APP_LABEL
ordering = ('-created',) ordering = ('-created',)
def __unicode__(self): def __unicode__(self):
......
...@@ -12,5 +12,3 @@ IMAGE_PATH_OBSCURIFY = getattr(django_settings, 'WIKI_IMAGE_PATH_OBSCURIFY', Tru ...@@ -12,5 +12,3 @@ IMAGE_PATH_OBSCURIFY = getattr(django_settings, 'WIKI_IMAGE_PATH_OBSCURIFY', Tru
ANONYMOUS = getattr(django_settings, 'WIKI_ATTACHMENTS_ANONYMOUS', False) ANONYMOUS = getattr(django_settings, 'WIKI_ATTACHMENTS_ANONYMOUS', False)
SLUG = 'images' SLUG = 'images'
APP_LABEL = 'wiki'
\ No newline at end of file
{% extends "wiki/article.html" %} {% extends "wiki/article.html" %}
{% load wiki_tags i18n humanize thumbnail %} {% load wiki_tags i18n humanize thumbnail %}
{% load url from future %}
{% block pagetitle %}{% trans "Images" %}: {{ article.current_revision.title }}{% endblock %} {% block pagetitle %}{% trans "Images" %}: {{ article.current_revision.title }}{% endblock %}
......
{% extends "wiki/article.html" %} {% extends "wiki/article.html" %}
{% load wiki_tags i18n humanize thumbnail %} {% load wiki_tags i18n humanize thumbnail %}
{% load url from future %}
{% block pagetitle %}{% trans "Purge deletion" %}: {{ image }}{% endblock %} {% block pagetitle %}{% trans "Purge deletion" %}: {{ image }}{% endblock %}
......
{% extends "wiki/article.html" %} {% extends "wiki/article.html" %}
{% load wiki_tags i18n humanize thumbnail %} {% load wiki_tags i18n humanize thumbnail %}
{% load url from future %}
{% block pagetitle %}{% trans "Replace image" %}: {{ image }}{% endblock %} {% block pagetitle %}{% trans "Replace image" %}: {{ image }}{% endblock %}
......
{% load i18n wiki_tags wiki_images_tags humanize thumbnail %} {% load i18n wiki_tags wiki_images_tags humanize thumbnail %}
{% load url from future %}
<script type="text/javascript"> <script type="text/javascript">
function insert_image(image_id) { function insert_image(image_id) {
......
...@@ -92,6 +92,10 @@ class PurgeView(ArticleMixin, FormView): ...@@ -92,6 +92,10 @@ class PurgeView(ArticleMixin, FormView):
return redirect('wiki:images_index', article_id=self.article_id) return redirect('wiki:images_index', article_id=self.article_id)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
# Needed since Django 1.9 because get_context_data is no longer called
# with the form instance
if 'form' not in kwargs:
kwargs['form'] = self.get_form()
kwargs = ArticleMixin.get_context_data(self, **kwargs) kwargs = ArticleMixin.get_context_data(self, **kwargs)
kwargs.update(FormView.get_context_data(self, **kwargs)) kwargs.update(FormView.get_context_data(self, **kwargs))
return kwargs return kwargs
...@@ -141,6 +145,10 @@ class RevisionAddView(ArticleMixin, FormView): ...@@ -141,6 +145,10 @@ class RevisionAddView(ArticleMixin, FormView):
return kwargs return kwargs
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
# Needed since Django 1.9 because get_context_data is no longer called
# with the form instance
if 'form' not in kwargs:
kwargs['form'] = self.get_form()
kwargs = super(RevisionAddView, self).get_context_data(**kwargs) kwargs = super(RevisionAddView, self).get_context_data(**kwargs)
kwargs['image'] = self.image kwargs['image'] = self.image
return kwargs return kwargs
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.conf.urls import patterns, url from django.conf.urls import url
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from wiki.core.plugins import registry from wiki.core.plugins import registry
...@@ -39,15 +39,15 @@ class ImagePlugin(BasePlugin): ...@@ -39,15 +39,15 @@ class ImagePlugin(BasePlugin):
css = { css = {
'screen': 'wiki/colorbox/example1/colorbox.css' 'screen': 'wiki/colorbox/example1/colorbox.css'
} }
urlpatterns = patterns('', urlpatterns = [
url('^$', views.ImageView.as_view(), name='images_index'), url('^$', views.ImageView.as_view(), name='images_index'),
url('^delete/(?P<image_id>\d+)/$', views.DeleteView.as_view(), name='images_delete'), url('^delete/(?P<image_id>\d+)/$', views.DeleteView.as_view(), name='images_delete'),
url('^restore/(?P<image_id>\d+)/$', views.DeleteView.as_view(), name='images_restore', kwargs={'restore': True}), url('^restore/(?P<image_id>\d+)/$', views.DeleteView.as_view(), name='images_restore', kwargs={'restore': True}),
url('^purge/(?P<image_id>\d+)/$', views.PurgeView.as_view(), name='images_purge'), url('^purge/(?P<image_id>\d+)/$', views.PurgeView.as_view(), name='images_purge'),
url('^(?P<image_id>\d+)/revision/change/(?P<rev_id>\d+)/$', views.RevisionChangeView.as_view(), name='images_restore'), url('^(?P<image_id>\d+)/revision/change/(?P<rev_id>\d+)/$', views.RevisionChangeView.as_view(), name='images_restore'),
url('^(?P<image_id>\d+)/revision/add/$', views.RevisionAddView.as_view(), name='images_add_revision'), url('^(?P<image_id>\d+)/revision/add/$', views.RevisionAddView.as_view(), name='images_add_revision'),
) ]
markdown_extensions = [ImageExtension()] markdown_extensions = [ImageExtension()]
......
...@@ -95,6 +95,8 @@ class UrlizeExtension(markdown.Extension): ...@@ -95,6 +95,8 @@ class UrlizeExtension(markdown.Extension):
md.inlinePatterns['autolink'] = UrlizePattern(URLIZE_RE, md) md.inlinePatterns['autolink'] = UrlizePattern(URLIZE_RE, md)
def makeExtension(configs=None): def makeExtension(configs=None):
if configs is None:
configs = {}
return UrlizeExtension(configs=configs) return UrlizeExtension(configs=configs)
if __name__ == "__main__": if __name__ == "__main__":
......
{% load i18n %} {% load i18n %}
{% load url from future %}
<h4>{% trans "Link to another wiki page" %}</h4> <h4>{% trans "Link to another wiki page" %}</h4>
<p> <p>
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.conf.urls import patterns, url from django.conf.urls import url
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from wiki.conf import settings from wiki.conf import settings
...@@ -13,9 +13,9 @@ from django.core.urlresolvers import reverse_lazy ...@@ -13,9 +13,9 @@ from django.core.urlresolvers import reverse_lazy
class LinkPlugin(BasePlugin): class LinkPlugin(BasePlugin):
slug = 'links' slug = 'links'
urlpatterns = patterns('', urlpatterns = [
url(r'^json/query-urlpath/$', views.QueryUrlPath.as_view(), name='links_query_urlpath'), url(r'^json/query-urlpath/$', views.QueryUrlPath.as_view(), name='links_query_urlpath'),
) ]
sidebar = {'headline': _('Links'), sidebar = {'headline': _('Links'),
'icon_class': 'icon-bookmark', 'icon_class': 'icon-bookmark',
......
...@@ -3,8 +3,7 @@ from django.core.urlresolvers import reverse ...@@ -3,8 +3,7 @@ from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.db.models import signals from django.db.models import signals
from django_notify import notify from django_notify.models import notify, Subscription
from django_notify.models import Subscription
from wiki import models as wiki_models from wiki import models as wiki_models
from wiki.models.pluginbase import ArticlePlugin from wiki.models.pluginbase import ArticlePlugin
...@@ -19,10 +18,7 @@ class ArticleSubscription(ArticlePlugin, Subscription): ...@@ -19,10 +18,7 @@ class ArticleSubscription(ArticlePlugin, Subscription):
{'user': self.settings.user.username, {'user': self.settings.user.username,
'article': self.article.current_revision.title, 'article': self.article.current_revision.title,
'type': self.notification_type.label}) 'type': self.notification_type.label})
class Meta:
app_label = settings.APP_LABEL
def default_url(article, urlpath=None): def default_url(article, urlpath=None):
try: try:
......
#from django.conf import settings as django_settings
APP_LABEL = 'wiki'
\ No newline at end of file
{% extends "wiki/base.html" %} {% extends "wiki/base.html" %}
{% load i18n wiki_tags %} {% load i18n wiki_tags %}
{% load url from future %}
{% block pagetitle %}{% trans "Log in" %}{% endblock %} {% block pagetitle %}{% trans "Log in" %}{% endblock %}
{% block wiki_contents %} {% block wiki_contents %}
......
{% extends "wiki/base.html" %} {% extends "wiki/base.html" %}
{% load wiki_tags i18n %} {% load wiki_tags i18n %}
{% load url from future %}
{% block pagetitle %}{{ article.current_revision.title }}{% endblock %} {% block pagetitle %}{{ article.current_revision.title }}{% endblock %}
......
{% load sekizai_tags i18n %}{% load url from future %}<!DOCTYPE html> {% load sekizai_tags i18n %}<!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
......
{% extends "wiki/base.html" %} {% extends "wiki/base.html" %}
{% load wiki_tags i18n sekizai_tags %} {% load wiki_tags i18n sekizai_tags %}
{% load url from future %}
{% block pagetitle %}{% trans "Add new article" %}{% endblock %} {% block pagetitle %}{% trans "Add new article" %}{% endblock %}
......
{% extends "wiki/base.html" %} {% extends "wiki/base.html" %}
{% load wiki_tags i18n sekizai_tags %} {% load wiki_tags i18n sekizai_tags %}
{% load url from future %}
{% block pagetitle %}{% trans "Delete article" %}{% endblock %} {% block pagetitle %}{% trans "Delete article" %}{% endblock %}
......
{% extends "wiki/base.html" %} {% extends "wiki/base.html" %}
{% load wiki_tags i18n sekizai_tags %} {% load wiki_tags i18n sekizai_tags %}
{% load url from future %}
{% block pagetitle %}{% trans "Article deleted" %}{% endblock %} {% block pagetitle %}{% trans "Article deleted" %}{% endblock %}
......
{% extends "wiki/article.html" %} {% extends "wiki/article.html" %}
{% load wiki_tags i18n humanize %} {% load wiki_tags i18n humanize %}
{% load url from future %}
{% block pagetitle %}{% trans "Listing articles in" %} {{ article.current_revision.title }}{% endblock %} {% block pagetitle %}{% trans "Listing articles in" %} {{ article.current_revision.title }}{% endblock %}
......
{% extends "wiki/article.html" %} {% extends "wiki/article.html" %}
{% load wiki_tags i18n %} {% load wiki_tags i18n %}
{% load url from future %}
{% block pagetitle %}{% trans "Edit" %}: {{ article.current_revision.title }}{% endblock %} {% block pagetitle %}{% trans "Edit" %}: {{ article.current_revision.title }}{% endblock %}
......
{% extends "wiki/base.html" %} {% extends "wiki/base.html" %}
{% load wiki_tags i18n %} {% load wiki_tags i18n %}
{% load url from future %}
{% block pagetitle %}{{ article.current_revision.title }}{% endblock %} {% block pagetitle %}{{ article.current_revision.title }}{% endblock %}
......
{% extends "wiki/article.html" %} {% extends "wiki/article.html" %}
{% load wiki_tags i18n sekizai_tags %} {% load wiki_tags i18n sekizai_tags %}
{% load url from future %}
{% block pagetitle %}{% trans "History" %}: {{ article.current_revision.title }}{% endblock %} {% block pagetitle %}{% trans "History" %}: {{ article.current_revision.title }}{% endblock %}
......
{% load i18n %} {% load i18n %}
{% load url from future %}
<em> <em>
{% url 'wiki:signup' as signup_url %} {% url 'wiki:signup' as signup_url %}
{% url 'wiki:login' as login_url %} {% url 'wiki:login' as login_url %}
......
{% load i18n wiki_tags %}{% load url from future %} {% load i18n wiki_tags %}
{% with selected_tab as selected %} {% with selected_tab as selected %}
......
{% load i18n %}{% load url from future %} {% load i18n %}
{% if urlpath %} {% if urlpath %}
<div id="article-breadcrumbs"> <div id="article-breadcrumbs">
......
{% extends "wiki/base.html" %} {% extends "wiki/base.html" %}
{% load wiki_tags i18n %} {% load wiki_tags i18n %}
{% load url from future %}
{% block pagetitle %}Permission Denied{% endblock %} {% block pagetitle %}Permission Denied{% endblock %}
......
{% extends "wiki/article.html" %} {% extends "wiki/article.html" %}
{% load wiki_tags i18n %} {% load wiki_tags i18n %}
{% load url from future %}
{% block pagetitle %}{% trans "Settings" %}: {{ article.current_revision.title }}{% endblock %} {% block pagetitle %}{% trans "Settings" %}: {{ article.current_revision.title }}{% endblock %}
......
{% extends "wiki/article.html" %} {% extends "wiki/article.html" %}
{% load wiki_tags i18n humanize %} {% load wiki_tags i18n humanize %}
{% load url from future %}
{% block pagetitle %}{% trans "Source of" %} {{ article.current_revision.title }}{% endblock %} {% block pagetitle %}{% trans "Source of" %} {{ article.current_revision.title }}{% endblock %}
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.conf.urls import patterns, url, include from django.conf.urls import url, include
from wiki.views import article, accounts from wiki.views import article, accounts
from wiki.conf import settings from wiki.conf import settings
from wiki.core.plugins import registry from wiki.core.plugins import registry
urlpatterns = patterns('', urlpatterns = [
url('^$', article.ArticleView.as_view(), name='root', kwargs={'path': ''}), url(r'^$', article.ArticleView.as_view(), name='root', kwargs={'path': ''}),
url('^create-root/$', 'wiki.views.article.root_create', name='root_create'), url(r'^create-root/$', article.root_create, name='root_create'),
url('^_revision/diff/(?P<revision_id>\d+)/$', 'wiki.views.article.diff', name='diff'), url(r'^_revision/diff/(?P<revision_id>\d+)/$', article.diff, name='diff'),
) ]
if settings.ACCOUNT_HANDLING: if settings.ACCOUNT_HANDLING:
urlpatterns += patterns('', urlpatterns += [
url('^_accounts/sign-up/$', accounts.Signup.as_view(), name='signup'), url(r'^_accounts/sign-up/$', accounts.Signup.as_view(), name='signup'),
url('^_accounts/logout/$', accounts.Logout.as_view(), name='logout'), url(r'^_accounts/logout/$', accounts.Logout.as_view(), name='logout'),
url('^_accounts/login/$', accounts.Login.as_view(), name='login'), url(r'^_accounts/login/$', accounts.Login.as_view(), name='login'),
) ]
urlpatterns += patterns('', urlpatterns += [
# This one doesn't work because it don't know where to redirect after... # This one doesn't work because it don't know where to redirect after...
url('^_revision/change/(?P<article_id>\d+)/(?P<revision_id>\d+)/$', 'wiki.views.article.change_revision', name='change_revision'), url(r'^_revision/change/(?P<article_id>\d+)/(?P<revision_id>\d+)/$', article.change_revision,
url('^_revision/preview/(?P<article_id>\d+)/$', article.Preview.as_view(), name='preview_revision'), name='change_revision'),
url('^_revision/merge/(?P<article_id>\d+)/(?P<revision_id>\d+)/preview/$', 'wiki.views.article.merge', name='merge_revision_preview', kwargs={'preview': True}), url(r'^_revision/preview/(?P<article_id>\d+)/$', article.Preview.as_view(), name='preview_revision'),
url(r'^_revision/merge/(?P<article_id>\d+)/(?P<revision_id>\d+)/preview/$', article.merge,
name='merge_revision_preview', kwargs={'preview': True}),
# Paths decided by article_ids # Paths decided by article_ids
url('^(?P<article_id>\d+)/$', article.ArticleView.as_view(), name='get'), url(r'^(?P<article_id>\d+)/$', article.ArticleView.as_view(), name='get'),
url('^(?P<article_id>\d+)/delete/$', article.Delete.as_view(), name='delete'), url(r'^(?P<article_id>\d+)/delete/$', article.Delete.as_view(), name='delete'),
url('^(?P<article_id>\d+)/deleted/$', article.Deleted.as_view(), name='deleted'), url(r'^(?P<article_id>\d+)/deleted/$', article.Deleted.as_view(), name='deleted'),
url('^(?P<article_id>\d+)/edit/$', article.Edit.as_view(), name='edit'), url(r'^(?P<article_id>\d+)/edit/$', article.Edit.as_view(), name='edit'),
url('^(?P<article_id>\d+)/preview/$', article.Preview.as_view(), name='preview'), url(r'^(?P<article_id>\d+)/preview/$', article.Preview.as_view(), name='preview'),
url('^(?P<article_id>\d+)/history/$', article.History.as_view(), name='history'), url(r'^(?P<article_id>\d+)/history/$', article.History.as_view(), name='history'),
url('^(?P<article_id>\d+)/settings/$', article.Settings.as_view(), name='settings'), url(r'^(?P<article_id>\d+)/settings/$', article.Settings.as_view(), name='settings'),
url('^(?P<article_id>\d+)/source/$', article.Source.as_view(), name='source'), url(r'^(?P<article_id>\d+)/source/$', article.Source.as_view(), name='source'),
url('^(?P<article_id>\d+)/revision/change/(?P<revision_id>\d+)/$', 'wiki.views.article.change_revision', name='change_revision'), url(r'^(?P<article_id>\d+)/revision/change/(?P<revision_id>\d+)/$', article.change_revision,
url('^(?P<article_id>\d+)/revision/merge/(?P<revision_id>\d+)/$', 'wiki.views.article.merge', name='merge_revision'), name='change_revision'),
url('^(?P<article_id>\d+)/plugin/(?P<slug>\w+)/$', article.Plugin.as_view(), name='plugin'), url(r'^(?P<article_id>\d+)/revision/merge/(?P<revision_id>\d+)/$', article.merge, name='merge_revision'),
url(r'^(?P<article_id>\d+)/plugin/(?P<slug>\w+)/$', article.Plugin.as_view(), name='plugin'),
) ]
for plugin in registry.get_plugins().values(): for plugin in registry.get_plugins().values():
slug = getattr(plugin, 'slug', None) slug = getattr(plugin, 'slug', None)
plugin_urlpatterns = getattr(plugin, 'urlpatterns', None) plugin_urlpatterns = getattr(plugin, 'urlpatterns', None)
if slug and plugin_urlpatterns: if slug and plugin_urlpatterns:
urlpatterns += patterns('', urlpatterns += [
url('^(?P<article_id>\d+)/plugin/'+slug+'/', include(plugin_urlpatterns)), url(r'^(?P<article_id>\d+)/plugin/' + slug + '/', include(plugin_urlpatterns)),
url('^(?P<path>.+/|)_plugin/'+slug+'/', include(plugin_urlpatterns)), url(r'^(?P<path>.+/|)_plugin/' + slug + '/', include(plugin_urlpatterns)),
) ]
urlpatterns += patterns('', urlpatterns += [
# Paths decided by URLs # Paths decided by URLs
url('^(?P<path>.+/|)_create/$', article.Create.as_view(), name='create'), url(r'^(?P<path>.+/|)_create/$', article.Create.as_view(), name='create'),
url('^(?P<path>.+/|)_delete/$', article.Delete.as_view(), name='delete'), url(r'^(?P<path>.+/|)_delete/$', article.Delete.as_view(), name='delete'),
url('^(?P<path>.+/|)_deleted/$', article.Deleted.as_view(), name='deleted'), url(r'^(?P<path>.+/|)_deleted/$', article.Deleted.as_view(), name='deleted'),
url('^(?P<path>.+/|)_edit/$', article.Edit.as_view(), name='edit'), url(r'^(?P<path>.+/|)_edit/$', article.Edit.as_view(), name='edit'),
url('^(?P<path>.+/|)_preview/$', article.Preview.as_view(), name='preview'), url(r'^(?P<path>.+/|)_preview/$', article.Preview.as_view(), name='preview'),
url('^(?P<path>.+/|)_history/$', article.History.as_view(), name='history'), url(r'^(?P<path>.+/|)_history/$', article.History.as_view(), name='history'),
url('^(?P<path>.+/|)_dir/$', article.Dir.as_view(), name='dir'), url(r'^(?P<path>.+/|)_dir/$', article.Dir.as_view(), name='dir'),
url('^(?P<path>.+/|)_settings/$', article.Settings.as_view(), name='settings'), url(r'^(?P<path>.+/|)_settings/$', article.Settings.as_view(), name='settings'),
url('^(?P<path>.+/|)_source/$', article.Source.as_view(), name='source'), url(r'^(?P<path>.+/|)_source/$', article.Source.as_view(), name='source'),
url('^(?P<path>.+/|)_revision/change/(?P<revision_id>\d+)/$', 'wiki.views.article.change_revision', name='change_revision'), url(r'^(?P<path>.+/|)_revision/change/(?P<revision_id>\d+)/$', article.change_revision, name='change_revision'),
url('^(?P<path>.+/|)_revision/merge/(?P<revision_id>\d+)/$', 'wiki.views.article.merge', name='merge_revision'), url(r'^(?P<path>.+/|)_revision/merge/(?P<revision_id>\d+)/$', article.merge, name='merge_revision'),
url('^(?P<path>.+/|)_plugin/(?P<slug>\w+)/$', article.Plugin.as_view(), name='plugin'), url(r'^(?P<path>.+/|)_plugin/(?P<slug>\w+)/$', article.Plugin.as_view(), name='plugin'),
url('^(?P<path>.+/|)$', article.ArticleView.as_view(), name='get'), url(r'^(?P<path>.+/|)$', article.ArticleView.as_view(), name='get'),
) ]
def get_pattern(app_name="wiki", namespace="wiki"): def get_pattern(app_name="wiki", namespace="wiki"):
"""Every url resolution takes place as "wiki:view_name". """Every url resolution takes place as "wiki:view_name".
......
...@@ -43,11 +43,13 @@ class Create(FormView, ArticleMixin): ...@@ -43,11 +43,13 @@ class Create(FormView, ArticleMixin):
@method_decorator(get_article(can_write=True)) @method_decorator(get_article(can_write=True))
def dispatch(self, request, article, *args, **kwargs): def dispatch(self, request, article, *args, **kwargs):
return super(Create, self).dispatch(request, article, *args, **kwargs) return super(Create, self).dispatch(request, article, *args, **kwargs)
def get_form(self, form_class): def get_form(self, form_class=None):
""" """
Returns an instance of the form to be used in this view. Returns an instance of the form to be used in this view.
""" """
if form_class is None:
form_class = self.get_form_class()
kwargs = self.get_form_kwargs() kwargs = self.get_form_kwargs()
initial = kwargs.get('initial', {}) initial = kwargs.get('initial', {})
initial['slug'] = self.request.GET.get('slug', None) initial['slug'] = self.request.GET.get('slug', None)
...@@ -99,11 +101,16 @@ class Create(FormView, ArticleMixin): ...@@ -99,11 +101,16 @@ class Create(FormView, ArticleMixin):
return redirect('wiki:get', self.newpath.path) return redirect('wiki:get', self.newpath.path)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs['parent_urlpath'] = self.urlpath c = ArticleMixin.get_context_data(self, **kwargs)
kwargs['parent_article'] = self.article # Needed since Django 1.9 because get_context_data is no longer called
kwargs['create_form'] = kwargs.pop('form', None) # with the form instance
kwargs['editor'] = editors.getEditor() if 'form' not in c:
return super(Create, self).get_context_data(**kwargs) c['form'] = self.get_form()
c['parent_urlpath'] = self.urlpath
c['parent_article'] = self.article
c['create_form'] = c.pop('form', None)
c['editor'] = editors.getEditor()
return c
class Delete(FormView, ArticleMixin): class Delete(FormView, ArticleMixin):
...@@ -140,9 +147,9 @@ class Delete(FormView, ArticleMixin): ...@@ -140,9 +147,9 @@ class Delete(FormView, ArticleMixin):
def get_initial(self): def get_initial(self):
return {'revision': self.article.current_revision} return {'revision': self.article.current_revision}
def get_form(self, form_class): def get_form(self, form_class=None):
form = super(Delete, self).get_form(form_class) form = super(Delete, self).get_form(form_class=form_class)
if self.article.can_moderate(self.request.user): if self.article.can_moderate(self.request.user):
form.fields['purge'].widget = forms.forms.CheckboxInput() form.fields['purge'].widget = forms.forms.CheckboxInput()
return form return form
...@@ -193,7 +200,11 @@ class Delete(FormView, ArticleMixin): ...@@ -193,7 +200,11 @@ class Delete(FormView, ArticleMixin):
cannot_delete_children = False cannot_delete_children = False
if self.children_slice and not self.article.can_moderate(self.request.user): if self.children_slice and not self.article.can_moderate(self.request.user):
cannot_delete_children = True cannot_delete_children = True
# Needed since Django 1.9 because get_context_data is no longer called
# with the form instance
if 'form' not in kwargs:
kwargs['form'] = self.get_form()
kwargs['delete_form'] = kwargs.pop('form', None) kwargs['delete_form'] = kwargs.pop('form', None)
kwargs['cannot_delete_root'] = self.cannot_delete_root kwargs['cannot_delete_root'] = self.cannot_delete_root
kwargs['delete_children'] = self.children_slice[:20] kwargs['delete_children'] = self.children_slice[:20]
...@@ -202,7 +213,7 @@ class Delete(FormView, ArticleMixin): ...@@ -202,7 +213,7 @@ class Delete(FormView, ArticleMixin):
return super(Delete, self).get_context_data(**kwargs) return super(Delete, self).get_context_data(**kwargs)
class Edit(FormView, ArticleMixin): class Edit(ArticleMixin, FormView):
"""Edit an article and process sidebar plugins.""" """Edit an article and process sidebar plugins."""
form_class = forms.EditForm form_class = forms.EditForm
...@@ -213,12 +224,14 @@ class Edit(FormView, ArticleMixin): ...@@ -213,12 +224,14 @@ class Edit(FormView, ArticleMixin):
self.sidebar_plugins = plugin_registry.get_sidebar() self.sidebar_plugins = plugin_registry.get_sidebar()
self.sidebar = [] self.sidebar = []
return super(Edit, self).dispatch(request, article, *args, **kwargs) return super(Edit, self).dispatch(request, article, *args, **kwargs)
def get_form(self, form_class): def get_form(self, form_class=None):
""" """
Checks from querystring data that the edit form is actually being saved, Checks from querystring data that the edit form is actually being saved,
otherwise removes the 'data' and 'files' kwargs from form initialisation. otherwise removes the 'data' and 'files' kwargs from form initialisation.
""" """
if form_class is None:
form_class = self.get_form_class()
kwargs = self.get_form_kwargs() kwargs = self.get_form_kwargs()
if self.request.POST.get('save', '') != '1' and self.request.POST.get('preview') != '1': if self.request.POST.get('save', '') != '1' and self.request.POST.get('preview') != '1':
kwargs['data'] = None kwargs['data'] = None
...@@ -283,7 +296,7 @@ class Edit(FormView, ArticleMixin): ...@@ -283,7 +296,7 @@ class Edit(FormView, ArticleMixin):
revision.deleted = False revision.deleted = False
revision.set_from_request(self.request) revision.set_from_request(self.request)
self.article.add_revision(revision) self.article.add_revision(revision)
messages.success(self.request, _(u'A new revision of the article was succesfully added.')) messages.success(self.request, _(u'A new revision of the article was successfully added.'))
return self.get_success_url() return self.get_success_url()
def get_success_url(self): def get_success_url(self):
...@@ -293,7 +306,11 @@ class Edit(FormView, ArticleMixin): ...@@ -293,7 +306,11 @@ class Edit(FormView, ArticleMixin):
return redirect('wiki:get', article_id=self.article.id) return redirect('wiki:get', article_id=self.article.id)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs['edit_form'] = kwargs.pop('form', None) # Needed for Django 1.9 because get_context_data is no longer called
# with the form instance
if 'form' not in kwargs:
kwargs['form'] = self.get_form()
kwargs['edit_form'] = kwargs['form']
kwargs['editor'] = editors.getEditor() kwargs['editor'] = editors.getEditor()
kwargs['selected_tab'] = 'edit' kwargs['selected_tab'] = 'edit'
kwargs['sidebar'] = self.sidebar kwargs['sidebar'] = self.sidebar
...@@ -350,11 +367,11 @@ class Deleted(Delete): ...@@ -350,11 +367,11 @@ class Deleted(Delete):
return {'revision': self.article.current_revision, return {'revision': self.article.current_revision,
'purge': True} 'purge': True}
def get_form(self, form_class):
form = super(Delete, self).get_form(form_class)
return form
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
# Needed since Django 1.9 because get_context_data is no longer called
# with the form instance
if 'form' not in kwargs:
kwargs['form'] = self.get_form()
kwargs['purge_form'] = kwargs.pop('form', None) kwargs['purge_form'] = kwargs.pop('form', None)
return super(Delete, self).get_context_data(**kwargs) return super(Delete, self).get_context_data(**kwargs)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment