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

Define interface for selecting Census regions #222

Merged
merged 5 commits into from
Oct 31, 2019
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
48 changes: 45 additions & 3 deletions surveys/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ def create_default_helper(self):
self.helper.label_class = 'col-lg-3'
self.helper.field_class = 'col-lg-9'
self.helper.form_method = 'post'
self.helper.add_input(Submit('submit', 'Submit', css_class='float-right'))
self.add_inputs(self.helper)

def add_inputs(self, helper):
helper.add_input(Submit('submit', 'Submit', css_class='float-right'))


class AgencyCreateForm(JustSpacesForm):
Expand Down Expand Up @@ -216,22 +219,61 @@ class Meta:
}


class CensusAreaRegionSelectForm(JustSpacesForm):
class Meta:
model = survey_models.CensusArea
fields = ['name', 'region']

def add_inputs(self, helper):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah nice!

# Override base method to remove Submit button from this form.
return None


class CensusAreaCreateForm(JustSpacesForm):
use_required_attribute = False
restrict_by_agency = forms.BooleanField(
label='Restrict to my agency',
initial=False,
help_text=(
'This will make this CensusArea viewable only by you and members '
'of your agency. If this box is unchecked, all users will be able '
'to find and use your CensusArea for their own analyses.'
),
required=False
)

class Meta:
model = survey_models.CensusArea
fields = ['name', 'agency', 'fips_codes']
fields = ['name', 'region', 'fips_codes', 'restrict_by_agency']
widgets = {
'fips_codes': widgets.MultiSelectGeometryWidget(),
}

def __init__(self, *args, **kwargs):
def __init__(self, user, *args, **kwargs):
super().__init__(*args, **kwargs)
self.user = user
self.fields['fips_codes'].widget.choices = [
(choice.fips_code, choice) for choice
in survey_models.CensusBlockGroup.objects.all()
]
if self.instance.agency:
self.fields['restrict_by_agency'].initial = True

def save(self, commit=True):
if self.cleaned_data['restrict_by_agency'] is True:
self.instance.agency = self.user.agency
else:
self.instance.agency = None
return super().save(commit=commit)


class CensusAreaEditForm(CensusAreaCreateForm):
class Meta:
model = survey_models.CensusArea
fields = ['name', 'fips_codes', 'restrict_by_agency']
widgets = {
'fips_codes': widgets.MultiSelectGeometryWidget(),
}


class SurveyChartForm(forms.ModelForm):
Expand Down
43 changes: 43 additions & 0 deletions surveys/migrations/0017_census_region.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import django.contrib.postgres.fields
from django.db import migrations, models
import django.db.models.deletion


def create_philadelphia(apps, schema_editor):
CensusRegion = apps.get_model('surveys', 'CensusRegion')
CensusRegion.objects.get_or_create(
name='Philadelphia',
slug='philadelphia',
fips_codes=['42101']
)


class Migration(migrations.Migration):

dependencies = [
('surveys', '0016_census_area_agency'),
]

operations = [
migrations.CreateModel(
name='CensusRegion',
fields=[
('fips_codes', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=12), size=None)),
('slug', models.SlugField(max_length=255, primary_key=True, serialize=False)),
('name', models.CharField(max_length=255, unique=True)),
],
),
migrations.RunPython(create_philadelphia, reverse_code=migrations.RunPython.noop),
migrations.AddField(
model_name='censusblockgroup',
name='region',
field=models.ForeignKey(default='philadelphia', on_delete=django.db.models.deletion.PROTECT, to='surveys.CensusRegion'),
preserve_default=False,
),
migrations.AddField(
model_name='censusarea',
name='region',
field=models.ForeignKey(default='philadelphia', on_delete=django.db.models.deletion.PROTECT, to='surveys.CensusRegion'),
preserve_default=False,
),
]
12 changes: 12 additions & 0 deletions surveys/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,18 @@ def __str__(self):
return self.name


class CensusRegion(models.Model):
# FIPS Codes that define this region, typically a set of Counties
fips_codes = pg_fields.ArrayField(models.CharField(max_length=12))
slug = models.SlugField(max_length=255, primary_key=True)
name = models.CharField(max_length=255, unique=True)

def __str__(self):
return self.name


class CensusBlockGroup(models.Model):
region = models.ForeignKey('CensusRegion', on_delete=models.PROTECT)
fips_code = models.CharField(max_length=12, primary_key=True)
geom = geo_models.MultiPolygonField(srid=4269)

Expand Down Expand Up @@ -90,6 +101,7 @@ class CensusArea(models.Model):
'all agencies.'
)
)
region = models.ForeignKey('CensusRegion', on_delete=models.PROTECT)
is_active = models.BooleanField(default=True)
is_preset = models.BooleanField(default=False)

Expand Down
2 changes: 2 additions & 0 deletions surveys/static/js/spin.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 33 additions & 3 deletions surveys/templates/census_area_create.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,41 @@
{% endblock %}

{% block card_content %}
<form class="form-horizontal" name="census-area-form" method="post">
{% crispy form %}
</form>
<form class="form-horizontal" name="census-area-form" method="post">
{% crispy form %}
</form>
<div class="modal" id="modal" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-body">
<div id="spinner" style="height:100px; margin-left:50%; margin-top:100px"></div>
</div>
</div>
</div>
</div>
{% endblock %}

{% block footer_js %}
<script src="{% static 'js/spin.min.js' %}"></script>
<script type="text/javascript">
$(document).ready(function() {
$('select[name="region"]').select2().change(function(e) {
// Start the "Loading" spinner
var spinner = Spinner().spin();
$('#spinner').append(spinner.el);
$('#modal').modal('show');

// Redirect to an updated view with a new Region on the map
var params = {
region: e.target.value,
};
var name = $('input[name="name"]').val();
if (name) {
params.name = name;
}
var queryString = $.param(params);
window.location.href = '{% url "census-areas-create" %}' + '?' + queryString;
});
});
</script>
{% endblock %}
2 changes: 1 addition & 1 deletion surveys/templates/census_area_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
{% block head %}Census Areas{% endblock %}

{% block top_button %}
<a class="btn btn-primary ml-sm-auto ml-2 mr-sm-3" href="{% url 'census-areas-create' %}">Create new census area</a>
<a class="btn btn-primary ml-sm-auto ml-2 mr-sm-3" href="{% url 'census-areas-region-select' %}">Create new census area</a>
{% endblock %}

{% block subhead %}
Expand Down
2 changes: 1 addition & 1 deletion surveys/templates/partials/chart_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
{{form.census_areas | attr:"class:form-control basic-multiple"}}
<small class="form-text text-muted">
Select one or multiple Census geographies to compare to the data collected for this question.
Don't see the census area you need? <a href="{% url 'census-areas-create' %}" target="_blank">Create a new one here.</a>
Don't see the census area you need? <a href="{% url 'census-areas-region-select' %}" target="_blank">Create a new one here.</a>
</small>
</div>
</div>
Expand Down
4 changes: 4 additions & 0 deletions surveys/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,10 @@
# API endpoint for retreiving CensusObservation data
path('acs/', view=survey_views.census_area_to_observation, name="acs"),

url(r'census-areas/region/$',
staff_required_custom_login(survey_views.CensusAreaRegionSelect.as_view()),
name='census-areas-region-select'),

url(r'census-areas/create/$',
staff_required_custom_login(survey_views.CensusAreaCreate.as_view()),
name='census-areas-create'),
Expand Down
55 changes: 44 additions & 11 deletions surveys/views.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import json
import uuid

from django.views.generic import TemplateView, ListView, UpdateView, DetailView
from django.views.generic import TemplateView, ListView, UpdateView, DetailView, FormView
from django.views.generic.edit import CreateView

from django.db.models import Q
Expand Down Expand Up @@ -83,7 +83,7 @@ class AgencyRestrictQuerysetMixin(object):
Provide common methods allowing views to restrict their querysets based on
the user's Agency.
"""
def get_queryset_for_agency(self, agency_filter='agency'):
def get_queryset_for_agency(self, queryset, agency_filter='agency'):
"""
Filter the queryset based on the user's agency. The 'agency_filter' string
will be used as the filter kwarg for the Agency lookup; e.g. if the Agency
Expand All @@ -94,9 +94,9 @@ def get_queryset_for_agency(self, agency_filter='agency'):
agency_null_kwargs = {agency_filter + '__isnull': True}

if self.request.user.agency is not None:
return self.queryset.filter(Q(**agency_kwargs) | Q(**agency_null_kwargs))
return queryset.filter(Q(**agency_kwargs) | Q(**agency_null_kwargs))
else:
return self.queryset
return queryset


class AgencyInitialMixin(object):
Expand Down Expand Up @@ -184,7 +184,7 @@ class LocationList(AgencyRestrictQuerysetMixin, ListView):
queryset = pldp_models.Location.objects.all().exclude(is_active=False)

def get_queryset(self):
return self.get_queryset_for_agency()
return self.get_queryset_for_agency(super().get_queryset())


class LocationDetail(DetailView):
Expand Down Expand Up @@ -277,7 +277,7 @@ class StudyList(AgencyRestrictQuerysetMixin, ListView):
queryset = pldp_models.Study.objects.all().exclude(is_active=False)

def get_queryset(self):
return self.get_queryset_for_agency()
return self.get_queryset_for_agency(super().get_queryset())


class StudyDeactivate(TemplateView):
Expand Down Expand Up @@ -453,7 +453,7 @@ class SurveyListEdit(AgencyRestrictQuerysetMixin, ListView):
queryset = survey_models.SurveyFormEntry.objects.filter(active=True, is_cloneable=False, published=False)

def get_queryset(self):
return self.get_queryset_for_agency('study__agency')
return self.get_queryset_for_agency(super().get_queryset(), 'study__agency')

def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
Expand All @@ -470,7 +470,7 @@ class SurveyListRun(AgencyRestrictQuerysetMixin, ListView):
queryset = survey_models.SurveyFormEntry.objects.filter(active=True, is_cloneable=False, published=True)

def get_queryset(self):
return self.get_queryset_for_agency('study__agency')
return self.get_queryset_for_agency(super().get_queryset(), 'study__agency')

def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
Expand All @@ -497,7 +497,7 @@ class SurveySubmittedList(AgencyRestrictQuerysetMixin, ListView):
queryset = pldp_models.Survey.objects.all()

def get_queryset(self):
return self.get_queryset_for_agency('study__agency')
return self.get_queryset_for_agency(super().get_queryset(), 'study__agency')

def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
Expand All @@ -518,12 +518,40 @@ def get_context_data(self, **kwargs):
return context


class CensusAreaRegionSelect(AgencyInitialMixin, FormView):
form_class = survey_forms.CensusAreaRegionSelectForm
template_name = 'census_area_create.html'

def get_initial(self):
initial = {}

if self.request.user.agency:
initial['agency'] = self.request.user.agency


class CensusAreaCreate(AgencyInitialMixin, CreateView):
form_class = survey_forms.CensusAreaCreateForm
model = survey_models.CensusArea
template_name = "census_area_create.html"
success_url = reverse_lazy('census-areas-list')

def get_initial(self):
initial = {}

for var in ['region', 'name']:
if self.request.GET.get(var):
initial[var] = self.request.GET[var]

if 'region' not in initial.keys():
initial['region'] = 'philadelphia'

return initial

def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['user'] = self.request.user
return kwargs


class CensusAreaList(AgencyRestrictQuerysetMixin, ListView):
model = survey_models.CensusArea
Expand All @@ -532,16 +560,21 @@ class CensusAreaList(AgencyRestrictQuerysetMixin, ListView):
queryset = survey_models.CensusArea.objects.all().exclude(is_active=False)

def get_queryset(self):
return self.get_queryset_for_agency()
return self.get_queryset_for_agency(super().get_queryset())


class CensusAreaEdit(UpdateView):
model = survey_models.CensusArea
template_name = "census_area_edit.html"
form_class = survey_forms.CensusAreaCreateForm
form_class = survey_forms.CensusAreaEditForm
context_object_name = 'form_object'
success_url = reverse_lazy('census-areas-list')

def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['user'] = self.request.user
return kwargs


class CensusAreaDeactivate(TemplateView):
template_name = "census_area_deactivate.html"
Expand Down
Loading