Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Questionnaire choice labels #739

Merged
merged 3 commits into from
Sep 29, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions cadasta/questionnaires/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,10 @@ def create_children(children, errors=[], project=None, kwargs={}):

def create_options(options, question, errors=[]):
if options:
for o in options:
for o, idx in zip(options, itertools.count()):
QuestionOption = apps.get_model('questionnaires', 'QuestionOption')
QuestionOption.objects.create(question=question, **o)

QuestionOption.objects.create(question=question, index=idx+1, **o)
else:
errors.append(_("Please provide at least one option for field"
" '{field_name}'".format(field_name=question.name)))
Expand Down Expand Up @@ -110,21 +111,24 @@ def create_attrs_schema(project=None, dict=None, content_type=None, errors=[]):
if c.get('choices'):
field['choices'] = [choice.get('name')
for choice in c.get('choices')]
field['choice_labels'] = [choice.get('label')
for choice in c.get('choices')]
fields.append(field)

for field, index in zip(fields, itertools.count(1)):
long_name = field.get('long_name', field['name'])
attr_type = AttributeType.objects.get(name=field['attr_type'])
choices = field.get('choices', [])
choice_labels = field.get('choice_labels', None)
default = field.get('default', '')
required = field.get('required', False)
omit = True if field.get('omit', '') == 'yes' else False
Attribute.objects.create(
schema=schema_obj,
name=field['name'], long_name=long_name,
attr_type=attr_type, index=index,
choices=choices, default=default,
required=required, omit=omit
choices=choices, choice_labels=choice_labels,
default=default, required=required, omit=omit
)


Expand Down
75 changes: 75 additions & 0 deletions cadasta/questionnaires/migrations/0006_add_choice_labels.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.6 on 2016-09-26 13:07
from __future__ import unicode_literals

from django.conf import settings
from django.db import migrations
from django.contrib.contenttypes.models import ContentType

from organization.models import Project
from jsonattrs.models import Schema, AttributeType


def add_schemas(ss, ct, sels):
for take in range(len(sels) + 1):
for s in Schema.objects.filter(content_type=ct,
selectors=sels[0:take]):
ss.add(s)


def add_attribute_choice_labels(apps, schema_editor):
# Empty database? Probably during testing...
if not AttributeType.objects.exists():
return

Questionnaire = apps.get_model('questionnaires', 'Questionnaire')

select_types = [AttributeType.objects.get(name=n)
for n in ['select_one', 'select_multiple']]
processed_schemas = set()
for prj in Project.objects.all():
org = prj.organization

if (prj.current_questionnaire is not None and
prj.current_questionnaire != ''):
quest = Questionnaire.objects.get(pk=prj.current_questionnaire)
selectors = (org.pk, prj.pk, prj.current_questionnaire)
for ct, sels in settings.JSONATTRS_SCHEMA_SELECTORS.items():
app_label, model = ct.split('.')
content_type = ContentType.objects.get(
app_label=app_label, model=model
)
schemas_to_process = set()
if len(sels) > 3:
cls = content_type.model_class()
selfield = cls._meta.get_field(sels[3])
for choice in selfield.choices:
add_schemas(schemas_to_process, content_type,
selectors + (choice[0],))
else:
add_schemas(schemas_to_process, content_type, selectors)
for schema in schemas_to_process:
if schema not in processed_schemas:
processed_schemas.add(schema)
for a in schema.attributes.filter(
attr_type__in=select_types
):
q = quest.questions.get(name=a.name)
opts = {o.name: o.label for o in q.options.all()}
a.choice_labels = [opts[c] for c in a.choices]
a.save()


class Migration(migrations.Migration):

dependencies = [
('questionnaires', '0005_auto_20160912_0720'),
('jsonattrs', '0002_attribute_choice_labels')
]

operations = [
migrations.RunPython(
add_attribute_choice_labels,
reverse_code=migrations.RunPython.noop
)
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.6 on 2016-09-27 13:39
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('questionnaires', '0006_add_choice_labels'),
]

operations = [
migrations.AddField(
model_name='historicalquestionoption',
name='index',
field=models.IntegerField(default=1, null=True),
),
migrations.AddField(
model_name='questionoption',
name='index',
field=models.IntegerField(default=1, null=True),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.6 on 2016-09-27 13:42
from __future__ import unicode_literals
import itertools

from django.db import migrations

from questionnaires.models import Question


def populate_index_fields(apps, schema_editor):
for question in Question.objects.filter(type__in=['S1', 'SM']):
for opt, idx in zip(question.options.order_by('index'),
itertools.count()):
opt.index = idx + 1
opt.save()


class Migration(migrations.Migration):

dependencies = [
('questionnaires', '0007_add_question_option_index_field'),
]

operations = [
migrations.RunPython(
populate_index_fields,
reverse_code=migrations.RunPython.noop
)
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.6 on 2016-09-27 14:31
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('questionnaires', '0008_populate_question_option_index_field'),
]

operations = [
migrations.AlterModelOptions(
name='questionoption',
options={'ordering': ('index',)},
),
migrations.AlterField(
model_name='historicalquestionoption',
name='index',
field=models.IntegerField(),
),
migrations.AlterField(
model_name='questionoption',
name='index',
field=models.IntegerField(),
),
]
4 changes: 4 additions & 0 deletions cadasta/questionnaires/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,12 @@ def has_options(self):


class QuestionOption(RandomIDModel):
class Meta:
ordering = ('index',)

name = models.CharField(max_length=100)
label = models.CharField(max_length=200)
index = models.IntegerField(null=False)
question = models.ForeignKey(Question, related_name='options')

history = HistoricalRecords()
1 change: 1 addition & 0 deletions cadasta/questionnaires/tests/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,5 @@ class Meta:

name = factory.Sequence(lambda n: "question_option_%s" % n)
label = factory.Sequence(lambda n: "Question Option #%s" % n)
index = factory.Sequence(lambda n: n)
question = factory.SubFactory(QuestionFactory)
6 changes: 5 additions & 1 deletion cadasta/spatial/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,11 @@ def create_model_fields(self, model, field_prefix, selectors,
# args['max_length'] = 32
if (atype.form_field == 'ChoiceField' or
atype.form_field == 'MultipleChoiceField'):
args['choices'] = list(map(lambda c: (c, c), attr.choices))
if attr.choice_labels is not None and attr.choice_labels != []:
chs = list(zip(attr.choices, attr.choice_labels))
else:
chs = list(map(lambda c: (c, c), attr.choices))
args['choices'] = chs
if atype.form_field == 'BooleanField':
args['required'] = False
if len(attr.default) > 0:
Expand Down
12 changes: 9 additions & 3 deletions cadasta/spatial/tests/test_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,14 +126,19 @@ def test_init(self):
index=0, required=True, default='John'
)
Attribute.objects.create(
schema=schema, name='p_choice', long_name='Party field',
schema=schema, name='p_choice1', long_name='Party field',
attr_type=AttributeType.objects.get(name='select_one'),
index=1, choices=['1', '2']
)
Attribute.objects.create(
schema=schema, name='p_choice2', long_name='Party field',
attr_type=AttributeType.objects.get(name='select_one'),
index=2, choices=['1', '2'], choice_labels=['Choice 1', 'Choice 2']
)
Attribute.objects.create(
schema=schema, name='p_bool', long_name='Party field',
attr_type=AttributeType.objects.get(name='boolean'),
index=2, default='False'
index=3, default='False'
)

form = forms.TenureRelationshipForm(
Expand All @@ -155,7 +160,8 @@ def test_init(self):
assert isinstance(form.fields['party::p_name'], CharField)
assert form.fields['party::p_name'].initial == 'John'
assert form.fields['party::p_name'].required is True
assert isinstance(form.fields['party::p_choice'], ChoiceField)
assert isinstance(form.fields['party::p_choice1'], ChoiceField)
assert isinstance(form.fields['party::p_choice2'], ChoiceField)
assert isinstance(form.fields['party::p_bool'], BooleanField)
assert form.fields['party::p_bool'].initial is False
assert isinstance(form.fields['relationship::r_name'], CharField)
Expand Down
2 changes: 1 addition & 1 deletion requirements/common.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ django-buckets==0.1.16
pyxform-cadasta==0.9.22
python-magic==0.4.11
Pillow==3.2.0
django-jsonattrs==0.1.10
django-jsonattrs==0.1.13
openpyxl==2.3.5
pytz==2016.4
shapely==1.5.16
Expand Down