Skip to content

Commit 0e2ba06

Browse files
steveSteve Lamb
authored andcommitted
Add support for django 1.9
1 parent 70af693 commit 0e2ba06

File tree

4 files changed

+67
-15
lines changed

4 files changed

+67
-15
lines changed

.travis.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,15 @@ env:
77
- DJANGO=1.6
88
- DJANGO=1.7
99
- DJANGO=1.8
10+
- DJANGO=1.9
1011
matrix:
1112
exclude:
1213
- python: "2.6"
1314
env: DJANGO=1.7
1415
- python: "2.6"
1516
env: DJANGO=1.8
17+
- python: "2.6"
18+
env: DJANGO=1.9
1619
install:
1720
- pip install -q Django==$DJANGO
1821
- pip install -r dev_requirements.txt

djqscsv/djqscsv.py

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,6 @@
55
from django.utils.text import slugify
66
from django.http import HttpResponse
77

8-
from django.conf import settings
9-
if not settings.configured:
10-
# required to import ValuesQuerySet
11-
settings.configure() # pragma: no cover
12-
13-
from django.db.models.query import ValuesQuerySet
14-
158
from django.utils import six
169

1710
""" A simple python package for turning django models into csvs """
@@ -74,24 +67,44 @@ def write_csv(queryset, file_obj, **kwargs):
7467

7568
# the CSV must always be built from a values queryset
7669
# in order to introspect the necessary fields.
77-
if isinstance(queryset, ValuesQuerySet):
70+
# However, repeated calls to values can expose fields that were not
71+
# present in the original qs. If using `values` as a way to
72+
# scope field permissions, this is unacceptable. The solution
73+
# is to make sure values is called *once*.
74+
75+
# perform an string check to avoid a non-existent class in certain
76+
# versions
77+
if type(queryset).__name__ == 'ValuesQuerySet':
7878
values_qs = queryset
7979
else:
80-
values_qs = queryset.values()
80+
# could be a non-values qs, or could be django 1.9+
81+
iterable_class = getattr(queryset, '_iterable_class', object)
82+
if iterable_class.__name__ == 'ValuesIterable':
83+
values_qs = queryset
84+
else:
85+
values_qs = queryset.values()
8186

8287
try:
83-
field_names = values_qs.field_names
84-
88+
field_names = values_qs.query.values_select
8589
except AttributeError:
86-
# in django1.5, empty querysets trigger
87-
# this exception, but not django 1.6
88-
raise CSVException("Empty queryset provided to exporter.")
90+
try:
91+
field_names = values_qs.field_names
92+
except AttributeError:
93+
# in django1.5, empty querysets trigger
94+
# this exception, but not django 1.6
95+
raise CSVException("Empty queryset provided to exporter.")
8996

9097
extra_columns = list(values_qs.query.extra_select)
9198
if extra_columns:
9299
field_names += extra_columns
93100

94-
aggregate_columns = list(values_qs.query.aggregate_select)
101+
try:
102+
aggregate_columns = list(values_qs.query.annotation_select)
103+
except AttributeError:
104+
# this gets a deprecation warning in django 1.9 but is
105+
# required in django<=1.7
106+
aggregate_columns = list(values_qs.query.aggregate_select)
107+
95108
if aggregate_columns:
96109
field_names += aggregate_columns
97110

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# -*- coding: utf-8 -*-
2+
# Generated by Django 1.9 on 2016-01-13 15:38
3+
from __future__ import unicode_literals
4+
5+
import datetime
6+
from django.db import migrations, models
7+
import django.db.models.deletion
8+
9+
10+
class Migration(migrations.Migration):
11+
12+
initial = True
13+
14+
dependencies = [
15+
]
16+
17+
operations = [
18+
migrations.CreateModel(
19+
name='Activity',
20+
fields=[
21+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
22+
('name', models.CharField(max_length=50, verbose_name=b'Name of Activity')),
23+
],
24+
),
25+
migrations.CreateModel(
26+
name='Person',
27+
fields=[
28+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
29+
('name', models.CharField(max_length=50, verbose_name="Person's name")),
30+
('address', models.CharField(max_length=255)),
31+
('info', models.TextField(verbose_name=b'Info on Person')),
32+
('born', models.DateTimeField(default=datetime.datetime(2001, 1, 1, 1, 1))),
33+
('hobby', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='djqscsv_tests.Activity')),
34+
],
35+
),
36+
]

test_app/djqscsv_tests/migrations/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)