diff --git a/.travis.yml b/.travis.yml
index a11e47a..4fb4f0e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,21 +1,29 @@
language: python
python:
- "2.7"
- - "3.4"
+ - "3.5"
cache: pip
sudo: false
env:
matrix:
- - TOX_ENV=py27-dj17
- - TOX_ENV=py27-dj18
- - TOX_ENV=py34-dj17
- - TOX_ENV=py34-dj18
+ - TOX_ENV=dj17
+ - TOX_ENV=dj18
+ - TOX_ENV=dj19
+ - TOX_ENV=dj110
+ - TOX_ENV=djdev
+matrix:
+ exclude:
+ - python: "3.5"
+ env: TOX_ENV=dj17
+ allow_failures:
+ - env: TOX_ENV=djdev
+
install:
- pip install --upgrade pip
- pip install tox
- pip install coveralls
script:
- - tox -e $TOX_ENV coverage
+ - tox -e py${TRAVIS_PYTHON_VERSION/./}-$TOX_ENV coverage
after_success:
- coveralls
after_script:
diff --git a/betterforms/multiform.py b/betterforms/multiform.py
index 89894b6..6efe356 100644
--- a/betterforms/multiform.py
+++ b/betterforms/multiform.py
@@ -67,6 +67,24 @@ def __str__(self):
def __getitem__(self, key):
return self.forms[key]
+ @property
+ def errors(self):
+ errors = {}
+ for form_name in self.forms:
+ form = self.forms[form_name]
+ for field_name in form.errors:
+ errors[form.add_prefix(field_name)] = form.errors[field_name]
+ return errors
+
+ @property
+ def fields(self):
+ fields = []
+ for form_name in self.forms:
+ form = self.forms[form_name]
+ for field_name in form.fields:
+ fields += [form.add_prefix(field_name)]
+ return fields
+
def __iter__(self):
# TODO: Should the order of the fields be controllable from here?
return chain.from_iterable(self.forms.values())
diff --git a/betterforms/tests.py b/betterforms/tests.py
index a1f193d..42f07ab 100644
--- a/betterforms/tests.py
+++ b/betterforms/tests.py
@@ -353,7 +353,7 @@ class TestForm(BetterForm):
test = """
@@ -477,6 +485,8 @@ class TestForm(forms.Form):
"""
if django.VERSION < (1, 8):
test = test.replace('label class="required"', 'label')
+ if django.VERSION < (1, 10):
+ test = test.replace(' required ', ' ')
self.assertHTMLEqual(
render_to_string('betterforms/form_as_fieldsets.html', env),
test,
@@ -503,22 +513,24 @@ def test_form_as_p(self):
"""
if django.VERSION < (1, 8):
test = test.replace('label class="required"', 'label')
+ if django.VERSION < (1, 10):
+ test = test.replace(' required ', ' ')
self.assertHTMLEqual(
form.as_p(),
test,
@@ -530,22 +542,25 @@ def test_form_as_p(self):
-
+
-
+
"""
+ self.maxDiff=None
if django.VERSION < (1, 8):
test = test.replace('label class="required"', 'label')
+ if django.VERSION < (1, 10):
+ test = test.replace(' required ', ' ')
self.assertHTMLEqual(
form.as_p(),
test,
@@ -571,23 +586,25 @@ class Meta:
-
+
-
+
"""
if django.VERSION < (1, 8):
test = test.replace('label class="required"', 'label')
+ if django.VERSION < (1, 10):
+ test = test.replace(' required ', ' ')
self.assertHTMLEqual(
form.as_p(),
test,
@@ -603,11 +620,13 @@ class TestForm(BetterForm):
test = """
-
+
"""
if django.VERSION < (1, 8):
test = test.replace('label class="required"', 'label')
+ if django.VERSION < (1, 10):
+ test = test.replace(' required ', ' ')
self.assertHTMLEqual(
render_to_string('betterforms/form_as_fieldsets.html', env),
test,
diff --git a/tests/settings.py b/tests/settings.py
index ee324e0..6db29f2 100644
--- a/tests/settings.py
+++ b/tests/settings.py
@@ -12,6 +12,16 @@
'django.middleware.csrf.CsrfViewMiddleware',
)
+TEMPLATES = [
+ {
+ 'DIRS': [
+ os.path.join(PROJECT_PATH, 'templates/'),
+ ],
+ 'BACKEND': 'django.template.backends.django.DjangoTemplates',
+ 'APP_DIRS': True,
+ },
+]
+
INSTALLED_APPS = (
'django.contrib.sessions',
'django.contrib.contenttypes',
diff --git a/tests/tests.py b/tests/tests.py
index 9b079c7..78781cb 100644
--- a/tests/tests.py
+++ b/tests/tests.py
@@ -1,5 +1,6 @@
from collections import OrderedDict
+import django
from django.test import TestCase
from django.test.client import RequestFactory
from django.views.generic import CreateView
@@ -47,6 +48,14 @@ def test_as_table(self):
profile_table = form['profile'].as_table()
self.assertEqual(form.as_table(), user_table + profile_table)
+ def test_fields(self):
+ form = UserProfileMultiForm()
+ self.assertEqual(form.fields, ['user-name', 'profile-name', 'profile-display_name'])
+
+ def test_errors(self):
+ form = ErrorMultiForm()
+ self.assertEqual(form.errors, {})
+
def test_to_str_is_as_table(self):
form = UserProfileMultiForm()
self.assertEqual(force_text(form), form.as_table())
@@ -94,9 +103,12 @@ def test_is_multipart(self):
def test_media(self):
form = NeedsFileField()
+ static_prefix = ""
+ if django.VERSION < (1, 10):
+ static_prefix = "/static/"
self.assertEqual(form.media._js, [
- '/static/admin/js/calendar.js',
- '/static/admin/js/admin/DateTimeShortcuts.js',
+ static_prefix + 'admin/js/calendar.js',
+ static_prefix + 'admin/js/admin/DateTimeShortcuts.js',
'test.js',
])
diff --git a/tox.ini b/tox.ini
index 2b3e36d..f0d94c1 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,6 +1,6 @@
[tox]
envlist=
- {py27,py34}-{dj17,dj18}
+ {py27,py34,py35}-{dj17,dj18,dj19,dj110,djdev}
[testenv]
commands=
@@ -8,10 +8,14 @@ commands=
basepython=
py27: python2.7
py34: python3.4
+ py35: python3.5
deps=
dj17: Django>=1.7,<1.8
dj18: Django>=1.8,<1.9
- dj18: django-formtools
+ dj19: Django>=1.9,<1.10
+ dj110: Django>=1.10,<1.11
+ djdev: https://github.com/django/django/archive/master.tar.gz
+ django-formtools
pytest
pytest-django
pytest-cov