Skip to content

Commit

Permalink
Merge pull request #197 from sanoma/195-media-assets
Browse files Browse the repository at this point in the history
Added support for media assets in Views and default templates
  • Loading branch information
MaartenPI committed Apr 25, 2017
2 parents ef4ed44 + 073c887 commit a7b8678
Show file tree
Hide file tree
Showing 12 changed files with 31,591 additions and 64 deletions.
8 changes: 4 additions & 4 deletions CHANGELOG.md
Expand Up @@ -7,18 +7,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

Always reference the ticket number at the end of the issue description.

##Pending

###Added

- Added support for read-only fields in update view - [#72][72]
##0.9.6 (2017-04-25)

###Changed

- Added support for read-only fields in update view - [#72][72]
- Added support for media assets in Views and default templates - [#195][195]
- Bumped django-filters to 1.0.1 and fixed breaking changes - [#171][171]

[72]: //github.com/sanoma/django-arctic/issues/72
[171]: //github.com/sanoma/django-arctic/issues/171
[195]: //github.com/sanoma/django-arctic/issues/195


##0.9.5 (2017-03-16)
Expand Down
34 changes: 34 additions & 0 deletions arctic/generics.py
Expand Up @@ -7,6 +7,8 @@
from django.core.exceptions import (FieldDoesNotExist)
from django.core.urlresolvers import (NoReverseMatch, reverse)
from django.db.models.deletion import (Collector, ProtectedError)
from django.forms import (Form, ModelForm)
from django.forms.widgets import Media
from django.shortcuts import (redirect, render, resolve_url)
from django.utils.formats import get_format
from django.utils.http import is_safe_url, quote
Expand Down Expand Up @@ -67,6 +69,7 @@ def get_context_data(self, **kwargs):
context['DATETIME_FORMATS'] = self.get_datetime_formats()
context['LOGIN_URL'] = self.get_login_url()
context['LOGOUT_URL'] = self.get_logout_url()
context['media'] = self.media
return context

def get_urls(self):
Expand Down Expand Up @@ -171,6 +174,37 @@ def get_login_url(self):
def get_logout_url(self):
return reverse(getattr(settings, 'LOGOUT_URL', 'logout'))

@classmethod
def _forms(cls):
forms = []
for f in dir(cls):
try:
if (issubclass(getattr(cls, f), Form) or
issubclass(getattr(cls, f), ModelForm)):
forms.append(f)
except TypeError:
pass
return forms

@property
def media(self):
"""
Return all media required to render this view, including forms.
"""
media = Media()
try:
media.add_css(self.Media.css)
except AttributeError:
pass
try:
media.add_js(self.Media.js)
except AttributeError:
pass
forms = self._forms()
for form in forms:
media = media + getattr(self, form)().media
return media


class TemplateView(View, base.TemplateView):
pass
Expand Down
7 changes: 4 additions & 3 deletions arctic/static/arctic/dist/assets/css/app.css

Large diffs are not rendered by default.

26 changes: 25 additions & 1 deletion arctic/static/arctic/dist/assets/img/arctic_logo.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31,438 changes: 31,422 additions & 16 deletions arctic/static/arctic/dist/assets/js/app.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions arctic/templates/arctic/base.html
Expand Up @@ -142,6 +142,7 @@ <h3 class="columns">
var TIME_FORMAT = '{{ DATETIME_FORMATS.TIME }}'
</script>
<script src="{% static "arctic/dist/assets/js/app.js" %}"></script>
{{ media.js }}
{% endblock %}
</body>
</html>
1 change: 1 addition & 0 deletions arctic/templates/arctic/partials/head.html
Expand Up @@ -13,6 +13,7 @@
</title>

<link href="{% static "arctic/dist/assets/css/app.css" %}" rel="stylesheet">
{{ media.css }}

<style>
{% if TOPBAR_BACKGROUND_COLOR %}
Expand Down
28 changes: 0 additions & 28 deletions arctic/tests/test_models.py

This file was deleted.

26 changes: 22 additions & 4 deletions docs/reference.md
Expand Up @@ -113,6 +113,23 @@ one of the tuples should point to the current view.
indicates if this view can only be accessed by authenticated users.
Can be `True` or `False`, default is `True`.

### `Media`

optional inner class indicating extra media assets to be included, if the View
has a form, all the form assets will be also included.

Example:

from arctic.generics import View

class MyView(View):
class Media:
css = {
'all': ('extra.css',)
}
js = ('extra.js', 'another.js')

For more information on the Media class usage check the [Django Form Assets documentation](https://docs.djangoproject.com/en/dev/topics/forms/media/)

**Methods**

Expand Down Expand Up @@ -184,11 +201,12 @@ accompanying method written like "get_{}_field". That method receives a
row_instance, so you can manipulate row data there.

Example:
class MyListView(arctic.ListView):
fields = (model_field1, model_field2, not_a_model_field)

def get_not_a_model_field_field(row_instance):
return '<b>' + row_instance.model_field3 + '</b>'
class MyListView(arctic.ListView):
fields = (model_field1, model_field2, not_a_model_field)

def get_not_a_model_field_field(row_instance):
return '<b>' + row_instance.model_field3 + '</b>'

### `search_fields`

Expand Down
3 changes: 1 addition & 2 deletions requirements/dev.txt
@@ -1,5 +1,4 @@
--process-dependency-links
-e .
-r test.txt

pypandoc==1.4
django>=1.8.12,<1.11
16 changes: 10 additions & 6 deletions setup.py
@@ -1,12 +1,16 @@
from setuptools import (find_packages, setup)


__VERSION__ = '0.9.5'
__VERSION__ = '0.9.6'


def read_md(f):
try:
from pypandoc import convert
return convert(f, 'rst')
except ImportError:
return open(f, 'r').read()

try:
README = open('README.md').read()
except:
README = None

try:
REQUIREMENTS = open('requirements/base.txt').read()
Expand All @@ -33,7 +37,7 @@
],

version=__VERSION__,
long_description=README,
long_description=read_md('README.md'),
install_requires=REQUIREMENTS,
packages=find_packages(),
include_package_data=True,
Expand Down
67 changes: 67 additions & 0 deletions tests/test_generics/test_media_assets.py
@@ -0,0 +1,67 @@
import pytest

from django.forms import Form

from arctic.generics import View


class FormWithAssets(Form):
class Media:
css = {
'all': ('form-common.css', 'view-common.css')
}
js = ('form1-1.js', 'form-common.js')


class AnotherFormWithAssets(Form):
class Media:
css = {
'all': ('form-common.css', 'form2.css')
}
js = ('form2-1.js', 'form-common.js')


class ViewWithAssets(View):
class Media:
css = {
'all': ('view.css', 'view-common.css')
}
js = ('view.js',)


class ViewWithAssetsAndForms(ViewWithAssets):
form1 = FormWithAssets
form2 = AnotherFormWithAssets


@pytest.mark.django_db
class TestViewAssets(object):
"""
Test media assets in views, including eventual form assets.
"""

def test_view_with_assets(self):
view = ViewWithAssets()
response = """<link href="/static/view.css" type="text/css" media="all" rel="stylesheet" />
<link href="/static/view-common.css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="/static/view.js"></script>""" # noqa

assert str(view.media) == response

def test_view_with_assets_and_forms(self):
view = ViewWithAssetsAndForms()
response = """<link href="/static/view.css" type="text/css" media="all" rel="stylesheet" />
<link href="/static/view-common.css" type="text/css" media="all" rel="stylesheet" />
<link href="/static/form-common.css" type="text/css" media="all" rel="stylesheet" />
<link href="/static/form2.css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="/static/view.js"></script>
<script type="text/javascript" src="/static/form1-1.js"></script>
<script type="text/javascript" src="/static/form-common.js"></script>
<script type="text/javascript" src="/static/form2-1.js"></script>""" # noqa

assert str(view.media) == response

def test_view_without_assets(self):
view = View()

assert str(view.media) == ''

0 comments on commit a7b8678

Please sign in to comment.