Updates for Django 1.10 and 1.11 (#73)

This commit is contained in:
Alexey Kotlyarov 2017-04-20 21:33:28 +10:00 committed by Cédric Carrard
parent 59283a1af4
commit a98318f5bf
9 changed files with 171 additions and 50 deletions

View file

@ -3,14 +3,30 @@ language: python
python: python:
- "2.7" - "2.7"
- "3.4" - "3.4"
- "3.6"
cache: pip cache: pip
env: env:
- DJANGO_VERSION=1.5.2 - DJANGO_VERSION=1.5.*
- DJANGO_VERSION=1.6.5 - DJANGO_VERSION=1.6.*
- DJANGO_VERSION=1.7.0 - DJANGO_VERSION=1.7.*
- DJANGO_VERSION=1.8.0 - DJANGO_VERSION=1.8.*
- DJANGO_VERSION=1.8.6 - DJANGO_VERSION=1.9.*
- DJANGO_VERSION=1.9.4 - DJANGO_VERSION=1.10.*
- DJANGO_VERSION=1.11.*
matrix:
exclude:
- python: '3.6'
env: DJANGO_VERSION=1.5.*
- python: '3.6'
env: DJANGO_VERSION=1.6.*
- python: '3.6'
env: DJANGO_VERSION=1.7.*
- python: '3.6'
env: DJANGO_VERSION=1.8.*
- python: '3.6'
env: DJANGO_VERSION=1.9.*
- python: '3.6'
env: DJANGO_VERSION=1.10.*
install: install:
- pip install -q Django==$DJANGO_VERSION - pip install -q Django==$DJANGO_VERSION
- pip install coveralls - pip install coveralls

View file

@ -37,14 +37,22 @@ Quick start
#. Add ``embed_video`` to ``INSTALLED_APPS`` in your Django settings. #. Add ``embed_video`` to ``INSTALLED_APPS`` in your Django settings.
#. If you want to detect HTTP/S in template tags, you have to set ``request`` #. If you want to detect HTTP/S in template tags, you have to set ``request``
context processor in ``settings.TEMPLATE_CONTEXT_PROCESSORS``: context processor in ``settings.TEMPLATES``:
:: ::
TEMPLATE_CONTEXT_PROCESSORS = ( TEMPLATES = [
... {
'django.core.context_processors.request', 'BACKEND': 'django.template.backends.django.DjangoTemplates',
) # ...
'OPTIONS': {
'context_processors': [
# ...
'django.template.context_processors.request',
],
},
},
]
#. Usage of template tags: #. Usage of template tags:

View file

@ -1,13 +1,29 @@
import os import os
from django.conf.global_settings import *
DEBUG = True DEBUG = True
SECRET_KEY = 'testing_key123' SECRET_KEY = 'testing_key123'
STATIC_ROOT = MEDIA_ROOT = os.path.join(os.path.dirname(__file__), 'static') STATIC_ROOT = MEDIA_ROOT = os.path.join(os.path.dirname(__file__), 'static')
STATIC_URL = MEDIA_URL = '/static/' STATIC_URL = MEDIA_URL = '/static/'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'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.tz',
'django.contrib.messages.context_processors.messages',
],
},
},
]
INSTALLED_APPS = ( INSTALLED_APPS = (
'django.contrib.contenttypes', 'django.contrib.contenttypes',
'django.contrib.auth', 'django.contrib.auth',

View file

@ -1,9 +1,15 @@
from unittest import TestCase, skip from unittest import TestCase, skip
from mock import Mock, patch from mock import Mock, patch
import sys
import re import re
if sys.version_info.major == 3:
import urllib.parse as urlparse
else:
import urlparse
from django.template import TemplateSyntaxError from django.template import TemplateSyntaxError
from django.http import HttpRequest from django.http import HttpRequest, QueryDict
from django.template.base import Template from django.template.base import Template
from django.template.context import RequestContext from django.template.context import RequestContext
from django.test.client import RequestFactory from django.test.client import RequestFactory
@ -15,10 +21,38 @@ URL_PATTERN = re.compile(r'src="?\'?([^"\'>]*)"')
class EmbedTestCase(TestCase): class EmbedTestCase(TestCase):
def assertRenderedTemplate(self, template_string, output, context=None): def render_template(self, template_string, context=None):
response = RequestContext(HttpRequest(), context) response = RequestContext(HttpRequest(), context)
rendered_output = Template(template_string).render(response) return Template(template_string).render(response).strip()
self.assertEqual(rendered_output.strip(), output.strip())
def assertRenderedTemplate(self, template_string, output, context=None):
rendered_output = self.render_template(template_string, context=context)
self.assertEqual(rendered_output, output.strip())
def url_dict(self, url):
"""
Parse the URL into a format suitable for comparison, ignoring the query
parameter order.
"""
parsed = urlparse.urlparse(url)
query = urlparse.parse_qs(parsed.query)
return {
'scheme': parsed.scheme,
'netloc': parsed.netloc,
'path': parsed.path,
'params': parsed.params,
'query': query,
'fragment': parsed.fragment,
}
def assertUrlEqual(self, actual, expected, msg=None):
"""Assert two URLs are equal, ignoring the query parameter order."""
actual_dict = self.url_dict(actual)
expected_dict = self.url_dict(expected)
self.assertEqual(actual_dict, expected_dict, msg=msg)
def test_embed(self): def test_embed(self):
template = """ template = """
@ -195,9 +229,11 @@ class EmbedTestCase(TestCase):
{{ ytb.url }} {{ ytb.url }}
{% endvideo %} {% endvideo %}
""" """
self.assertRenderedTemplate(
template, output = self.render_template(template)
'http://www.youtube.com/embed/jsrRJyHBvzw?wmode=transparent&rel=1' self.assertUrlEqual(
output,
'http://www.youtube.com/embed/jsrRJyHBvzw?rel=1&wmode=transparent'
) )
def test_direct_embed_with_query(self): def test_direct_embed_with_query(self):
@ -206,10 +242,25 @@ class EmbedTestCase(TestCase):
{% video 'http://www.youtube.com/watch?v=jsrRJyHBvzw' query="rel=1&wmode=transparent" %} {% video 'http://www.youtube.com/watch?v=jsrRJyHBvzw' query="rel=1&wmode=transparent" %}
""" """
self.assertRenderedTemplate( output = self.render_template(template)
template,
# The order of query parameters in the URL might change between Python
# versions. Compare the URL and the outer part separately.
url_pattern = re.compile(r'http[^"]+')
url = url_pattern.search(output).group(0)
self.assertUrlEqual(
url,
'http://www.youtube.com/embed/jsrRJyHBvzw?rel=1&wmode=transparent'
)
output_without_url = url_pattern.sub('URL', output)
self.assertEqual(
output_without_url,
'<iframe width="480" height="360" ' '<iframe width="480" height="360" '
'src="http://www.youtube.com/embed/jsrRJyHBvzw?wmode=transparent&rel=1" ' 'src="URL" '
'frameborder="0" allowfullscreen></iframe>' 'frameborder="0" allowfullscreen></iframe>'
) )

View file

@ -1,11 +1,13 @@
from unittest import TestCase from unittest import TestCase
from django.test import SimpleTestCase
from embed_video.admin import AdminVideoWidget, AdminVideoMixin from embed_video.admin import AdminVideoWidget, AdminVideoMixin
from embed_video.backends import VimeoBackend from embed_video.backends import VimeoBackend
from embed_video.fields import EmbedVideoField, EmbedVideoFormField from embed_video.fields import EmbedVideoField, EmbedVideoFormField
class AdminVideoWidgetTestCase(TestCase): class AdminVideoWidgetTestCase(SimpleTestCase):
def test_size(self): def test_size(self):
widget = AdminVideoWidget() widget = AdminVideoWidget()
self.assertTrue('size' in widget.attrs) self.assertTrue('size' in widget.attrs)
@ -21,15 +23,15 @@ class AdminVideoWidgetTestCase(TestCase):
def test_render_empty_value(self): def test_render_empty_value(self):
widget = AdminVideoWidget(attrs={'size': '0'}) widget = AdminVideoWidget(attrs={'size': '0'})
self.assertEqual(widget.render('foo'), self.assertHTMLEqual(widget.render('foo'),
'<input name="foo" size="0" type="text" />') '<input name="foo" size="0" type="text" />')
def test_render(self): def test_render(self):
backend = VimeoBackend('https://vimeo.com/1') backend = VimeoBackend('https://vimeo.com/1')
widget = AdminVideoWidget(attrs={'size': '0'}) widget = AdminVideoWidget(attrs={'size': '0'})
widget.output_format = '{video}{input}' widget.output_format = '{video}{input}'
self.assertEqual( self.assertHTMLEqual(
widget.render('foo', backend.url, size=(100, 100)), widget.render('foo', backend.url, size=(100, 100)),
backend.get_embed_code(100, 100) backend.get_embed_code(100, 100)
+ '<input name="foo" size="0" type="text" value="%s" />' + '<input name="foo" size="0" type="text" value="%s" />'
@ -38,14 +40,14 @@ class AdminVideoWidgetTestCase(TestCase):
def test_render_unknown_backend(self): def test_render_unknown_backend(self):
widget = AdminVideoWidget() widget = AdminVideoWidget()
self.assertEqual( self.assertHTMLEqual(
widget.render('foo', 'abcd'), widget.render('foo', 'abcd'),
'<input name="foo" size="40" type="text" value="abcd" />' '<input name="foo" size="40" type="text" value="abcd" />'
) )
def test_render_video_doesnt_exist(self): def test_render_video_doesnt_exist(self):
widget = AdminVideoWidget() widget = AdminVideoWidget()
self.assertEqual( self.assertHTMLEqual(
widget.render('foo', 'https://soundcloud.com/xyz/foo'), widget.render('foo', 'https://soundcloud.com/xyz/foo'),
'<input name="foo" size="40" type="text" value="https://soundcloud.com/xyz/foo" />' '<input name="foo" size="40" type="text" value="https://soundcloud.com/xyz/foo" />'
) )

View file

@ -7,6 +7,10 @@ Running example project
#. Create database:: #. Create database::
python manage.py migrate --run-syncdb --noinput
Or, for older versions of Django::
python manage.py syncdb --noinput python manage.py syncdb --noinput
#. Run testing server:: #. Run testing server::

View file

@ -1,7 +1,7 @@
# Django settings for example_project project. # Django settings for example_project project.
import django
DEBUG = True DEBUG = True
TEMPLATE_DEBUG = DEBUG
DATABASES = { DATABASES = {
'default': { 'default': {
@ -14,21 +14,45 @@ SITE_ID = 1
SECRET_KEY = 'u%38dln@$1!7w#cxi4np504^sa3_skv5aekad)jy_u0v2mc+nr' SECRET_KEY = 'u%38dln@$1!7w#cxi4np504^sa3_skv5aekad)jy_u0v2mc+nr'
TEMPLATE_CONTEXT_PROCESSORS = ( TEMPLATES = [
'django.contrib.auth.context_processors.auth', {
'django.core.context_processors.debug', 'BACKEND': 'django.template.backends.django.DjangoTemplates',
'django.core.context_processors.i18n', 'APP_DIRS': True,
'django.core.context_processors.media', 'OPTIONS': {
'django.core.context_processors.static', 'context_processors': [
'django.core.context_processors.tz', 'django.template.context_processors.debug',
'django.contrib.messages.context_processors.messages', 'django.template.context_processors.i18n',
'django.core.context_processors.request', 'django.template.context_processors.media',
) 'django.template.context_processors.static',
'django.template.context_processors.tz',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
TEMPLATE_LOADERS = ( if django.VERSION >= (1, 10):
'django.template.loaders.filesystem.Loader', MIDDLEWARE = [
'django.template.loaders.app_directories.Loader', 'django.middleware.security.SecurityMiddleware',
) 'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
else:
MIDDLEWARE_CLASSES = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
APPEND_SLASH = True APPEND_SLASH = True

View file

@ -1,11 +1,11 @@
from django.conf.urls import patterns, include, url from django.conf.urls import include, url
from django.contrib.staticfiles.urls import staticfiles_urlpatterns from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.contrib import admin from django.contrib import admin
admin.autodiscover() admin.autodiscover()
urlpatterns = staticfiles_urlpatterns() \ urlpatterns = staticfiles_urlpatterns() \
+ patterns('', + [
url(r'^admin/', include(admin.site.urls)), url(r'^admin/', include(admin.site.urls)),
url(r'^', include('posts.urls', namespace='posts')), url(r'^', include('posts.urls', namespace='posts')),
) ]

View file

@ -1,8 +1,8 @@
from django.conf.urls import patterns, url from django.conf.urls import url
from .views import PostListView, PostDetailView from .views import PostListView, PostDetailView
urlpatterns = patterns('', urlpatterns = [
url(r'(?P<pk>\d+)/$', PostDetailView.as_view(), name='detail'), url(r'(?P<pk>\d+)/$', PostDetailView.as_view(), name='detail'),
url(r'$', PostListView.as_view(), name='list'), url(r'$', PostListView.as_view(), name='list'),
) ]