Skip to content

Commit

Permalink
Merge pull request #24 from edx/christina/1_11_upgrade
Browse files Browse the repository at this point in the history
Updates for Django 1.11.
  • Loading branch information
Christina Roberts authored Aug 1, 2017
2 parents 144a816 + f749c67 commit f3dce90
Show file tree
Hide file tree
Showing 59 changed files with 303 additions and 265 deletions.
40 changes: 0 additions & 40 deletions django_notify/__init__.py
Original file line number Diff line number Diff line change
@@ -1,40 +0,0 @@
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)

37 changes: 36 additions & 1 deletion django_notify/models.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
# -*- coding: utf-8 -*-
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.utils.translation import ugettext_lazy as _

from django.contrib.contenttypes.models import ContentType

from django_notify import settings

_disable_notifications = False

class NotificationType(models.Model):
"""
Notification types are added on-the-fly by the
Expand Down Expand Up @@ -105,3 +107,36 @@ class Meta:
db_table = settings.DB_TABLE_PREFIX + '_notification'
verbose_name = _(u'notification')
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)
17 changes: 9 additions & 8 deletions django_notify/urls.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
# -*- coding: utf-8 -*-
from django.conf.urls import patterns, url
from django.conf.urls import url
from django_notify import views

urlpatterns = patterns('',
url('^json/get/$', 'django_notify.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/(\d+)/$', 'django_notify.views.mark_read', name='json_mark_read', kwargs={}),
url('^goto/(?P<notification_id>\d+)/$', 'django_notify.views.goto', name='goto', kwargs={}),
url('^goto/$', 'django_notify.views.goto', name='goto_base', kwargs={}),
)
urlpatterns = [
url('^json/get/$', views.get_notifications, name='json_get', kwargs={}),
url('^json/mark-read/$', views.mark_read, name='json_mark_read_base', kwargs={}),
url('^json/mark-read/(\d+)/$', views.mark_read, name='json_mark_read', kwargs={}),
url('^goto/(?P<notification_id>\d+)/$', views.goto, name='goto', kwargs={}),
url('^goto/$', views.goto, name='goto_base', kwargs={}),
]

def get_pattern(app_name="notify", namespace="notify"):
"""Every url resolution takes place as "notify:view_name".
Expand Down
12 changes: 6 additions & 6 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
django<1.9
South==1.0.1
Markdown<2.3.0
django-sekizai<0.7
django-mptt<0.8
sorl-thumbnail<13
django>=1.8,<2.0
Markdown>=2.6,<2.7
django-sekizai>=0.10
django-mptt>=0.8.6,<0.9
sorl-thumbnail>=12,<13
six>=1.10.0,<2.0.0
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def build_media_pattern(base_folder, file_extension):

setup(
name = "django-wiki",
version = "0.0.10",
version="0.0.11",
author = "Benjamin Bach",
author_email = "[email protected]",
description = ("A wiki system written for the Django framework."),
Expand All @@ -39,7 +39,7 @@ def build_media_pattern(base_folder, file_extension):
long_description=read('README.md'),
zip_safe = False,
install_requires=[
'Django>=1.4',
'Django>=1.8',
'markdown',
'django-sekizai',
'django-mptt',
Expand Down
Binary file modified testproject/testproject/db/prepopulated.db
Binary file not shown.
58 changes: 28 additions & 30 deletions testproject/testproject/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
PROJECT_PATH = os_path.abspath(os_path.split(__file__)[0])

DEBUG = True
TEMPLATE_DEBUG = DEBUG

ADMINS = (
# ('Your Name', '[email protected]'),
Expand Down Expand Up @@ -47,22 +46,9 @@

STATIC_ROOT = os_path.join(PROJECT_PATH, '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!'

TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
# 'django.template.loaders.eggs.Loader',
)

MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
Expand All @@ -79,22 +65,31 @@
# Python dotted path to the WSGI application used by Django's runserver.
WSGI_APPLICATION = 'testproject.wsgi.application'

TEMPLATE_DIRS = (
'templates',
)

TEMPLATE_CONTEXT_PROCESSORS =(
'django.contrib.auth.context_processors.auth',
'django.core.context_processors.debug',
'django.core.context_processors.i18n',
'django.core.context_processors.media',
'django.core.context_processors.static',
'django.core.context_processors.tz',
'django.contrib.messages.context_processors.messages',
'sekizai.context_processors.sekizai',
)
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os_path.join(PROJECT_PATH, 'templates'),
],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
"django.contrib.auth.context_processors.auth",
"django.template.context_processors.debug",
"django.template.context_processors.i18n",
"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.auth',
'django.contrib.contenttypes',
Expand All @@ -114,7 +109,7 @@
'wiki.plugins.attachments',
'wiki.plugins.notifications',
'mptt',
)
]

# A sample logging configuration. The only tangible logging
# performed by this configuration is to send an email to
Expand Down Expand Up @@ -146,3 +141,6 @@
}

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
27 changes: 13 additions & 14 deletions testproject/testproject/urls.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,26 @@
from django.conf.urls import patterns, include, url
from django.conf.urls import include, url
from django.conf import settings
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.views.static import serve as static_serve

from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^notify/', include('django_notify.urls', namespace='notify')),
)
]

if settings.DEBUG:
urlpatterns += staticfiles_urlpatterns()
urlpatterns += patterns('',
url(r'^media/(?P<path>.*)$', 'django.views.static.serve', {
'document_root': settings.MEDIA_ROOT,
}),
)
urlpatterns += [
url(r'^media/(?P<path>.*)$', static_serve, {'document_root': settings.MEDIA_ROOT}),
]


from wiki.urls import get_pattern as get_wiki_pattern
from django_notify.urls import get_pattern as get_notify_pattern
urlpatterns += patterns('',
(r'^notify/', get_notify_pattern()),
(r'', get_wiki_pattern())
)

urlpatterns += [
url(r'^notify/', get_notify_pattern()),
url(r'', get_wiki_pattern()),
]
1 change: 0 additions & 1 deletion wiki/conf/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
URL_CASE_SENSITIVE = getattr(django_settings, 'WIKI_URL_CASE_SENSITIVE', False)

# Non-configurable (at the moment)
APP_LABEL = 'wiki'
WIKI_LANGUAGE = 'markdown'

# The editor class to use -- maybe a 3rd party or your own...? You can always
Expand Down
14 changes: 14 additions & 0 deletions wiki/core/compat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# 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
11 changes: 6 additions & 5 deletions wiki/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ def response_forbidden(request, article, urlpath):
if request.user.is_anonymous():
return redirect(django_settings.LOGIN_URL)
else:
c = RequestContext(request, {'article': article,
'urlpath' : urlpath})
return HttpResponseForbidden(render_to_string("wiki/permission_denied.html", context_instance=c))
return HttpResponseForbidden(
render_to_string("wiki/permission_denied.html", context={'article': article, 'urlpath': urlpath},
request=request))

def get_article(func=None, can_read=True, can_write=False,
deleted_contents=False, not_locked=False,
Expand Down Expand Up @@ -75,8 +75,9 @@ def wrapper(request, *args, **kwargs):
parent = models.URLPath.get_by_path(path)
return redirect(reverse("wiki:create", kwargs={'path': parent.path,}) + "?slug=%s" % pathlist[-1])
except models.URLPath.DoesNotExist:
c = RequestContext(request, {'error_type' : 'ancestors_missing'})
return HttpResponseNotFound(render_to_string("wiki/error.html", context_instance=c))
return HttpResponseNotFound(
render_to_string("wiki/error.html", context={'error_type': 'ancestors_missing'},
request=request))
if urlpath.article:
# urlpath is already smart about prefetching items on article (like current_revision), so we don't have to
article = urlpath.article
Expand Down
11 changes: 7 additions & 4 deletions wiki/editors/markitup.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
from django.utils.html import conditional_escape
from django.utils.safestring import mark_safe

from wiki.core.compat import BuildAttrsCompat
from wiki.editors.base import BaseEditor

class MarkItUpAdminWidget(forms.Widget):

class MarkItUpAdminWidget(BuildAttrsCompat, forms.Widget):
"""A simplified more fail-safe widget for the backend"""
def __init__(self, attrs=None):
# The 'rows' and 'cols' attributes are required for HTML correctness.
Expand All @@ -18,11 +20,12 @@ def __init__(self, attrs=None):

def render(self, name, value, attrs=None):
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),
conditional_escape(force_unicode(value))))

class MarkItUpWidget(forms.Widget):

class MarkItUpWidget(BuildAttrsCompat, forms.Widget):
def __init__(self, attrs=None):
# The 'rows' and 'cols' attributes are required for HTML correctness.
default_attrs = {'class': 'markItUp',
Expand All @@ -33,7 +36,7 @@ def __init__(self, attrs=None):

def render(self, name, value, attrs=None):
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),
conditional_escape(force_unicode(value))))

Expand Down
5 changes: 3 additions & 2 deletions wiki/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from wiki.core.plugins.base import PluginSettingsFormMixin
from django.contrib.auth.models import User
from wiki.core import permissions
from wiki.core.compat import BuildAttrsCompat

class SpamProtectionMixin():

Expand Down Expand Up @@ -100,7 +101,7 @@ def clean(self):
return cd


class SelectWidgetBootstrap(forms.Select):
class SelectWidgetBootstrap(BuildAttrsCompat, forms.Select):
"""
http://twitter.github.com/bootstrap/components.html#buttonDropdowns
Needs bootstrap and jquery
Expand Down Expand Up @@ -143,7 +144,7 @@ def __setattr__(self, k, value):

def render(self, name, value, attrs=None, choices=()):
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>"""
""" <button class="btn btn-group-label" type="button">%(label)s</button>"""
""" <button class="btn dropdown-toggle" type="button" data-toggle="dropdown">"""
Expand Down
Loading

0 comments on commit f3dce90

Please sign in to comment.