mirror of
https://github.com/Hopiu/django-embed-video.git
synced 2026-03-16 21:30:23 +00:00
Updates for Django 1.10 and 1.11 (#73)
This commit is contained in:
parent
59283a1af4
commit
a98318f5bf
9 changed files with 171 additions and 50 deletions
28
.travis.yml
28
.travis.yml
|
|
@ -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
|
||||||
|
|
|
||||||
18
README.rst
18
README.rst
|
|
@ -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:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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',
|
||||||
|
|
|
||||||
|
|
@ -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>'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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" />'
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -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::
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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')),
|
||||||
)
|
]
|
||||||
|
|
|
||||||
|
|
@ -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'),
|
||||||
)
|
]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue