Skip to content

Commit

Permalink
Add support for django 1.9
Browse files Browse the repository at this point in the history
  • Loading branch information
steve authored and Steve Lamb committed Jan 22, 2016
1 parent 70af693 commit 0e2ba06
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 15 deletions.
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@ env:
- DJANGO=1.6
- DJANGO=1.7
- DJANGO=1.8
- DJANGO=1.9
matrix:
exclude:
- python: "2.6"
env: DJANGO=1.7
- python: "2.6"
env: DJANGO=1.8
- python: "2.6"
env: DJANGO=1.9
install:
- pip install -q Django==$DJANGO
- pip install -r dev_requirements.txt
Expand Down
43 changes: 28 additions & 15 deletions djqscsv/djqscsv.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,6 @@
from django.utils.text import slugify
from django.http import HttpResponse

from django.conf import settings
if not settings.configured:
# required to import ValuesQuerySet
settings.configure() # pragma: no cover

from django.db.models.query import ValuesQuerySet

from django.utils import six

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

# the CSV must always be built from a values queryset
# in order to introspect the necessary fields.
if isinstance(queryset, ValuesQuerySet):
# However, repeated calls to values can expose fields that were not
# present in the original qs. If using `values` as a way to
# scope field permissions, this is unacceptable. The solution
# is to make sure values is called *once*.

# perform an string check to avoid a non-existent class in certain
# versions
if type(queryset).__name__ == 'ValuesQuerySet':
values_qs = queryset
else:
values_qs = queryset.values()
# could be a non-values qs, or could be django 1.9+
iterable_class = getattr(queryset, '_iterable_class', object)
if iterable_class.__name__ == 'ValuesIterable':
values_qs = queryset
else:
values_qs = queryset.values()

try:
field_names = values_qs.field_names

field_names = values_qs.query.values_select
except AttributeError:
# in django1.5, empty querysets trigger
# this exception, but not django 1.6
raise CSVException("Empty queryset provided to exporter.")
try:
field_names = values_qs.field_names
except AttributeError:
# in django1.5, empty querysets trigger
# this exception, but not django 1.6
raise CSVException("Empty queryset provided to exporter.")

extra_columns = list(values_qs.query.extra_select)
if extra_columns:
field_names += extra_columns

aggregate_columns = list(values_qs.query.aggregate_select)
try:
aggregate_columns = list(values_qs.query.annotation_select)
except AttributeError:
# this gets a deprecation warning in django 1.9 but is
# required in django<=1.7
aggregate_columns = list(values_qs.query.aggregate_select)

if aggregate_columns:
field_names += aggregate_columns

Expand Down
36 changes: 36 additions & 0 deletions test_app/djqscsv_tests/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2016-01-13 15:38
from __future__ import unicode_literals

import datetime
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

initial = True

dependencies = [
]

operations = [
migrations.CreateModel(
name='Activity',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=50, verbose_name=b'Name of Activity')),
],
),
migrations.CreateModel(
name='Person',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=50, verbose_name="Person's name")),
('address', models.CharField(max_length=255)),
('info', models.TextField(verbose_name=b'Info on Person')),
('born', models.DateTimeField(default=datetime.datetime(2001, 1, 1, 1, 1))),
('hobby', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='djqscsv_tests.Activity')),
],
),
]
Empty file.

0 comments on commit 0e2ba06

Please sign in to comment.