class FOIACommunicationAdminForm(forms.ModelForm): """Form for comm inline""" from_user = forms.ModelChoiceField( queryset=User.objects.all(), required=False, widget=autocomplete.ModelSelect2( url="user-autocomplete", attrs={ "data-placeholder": "User?", "data-width": None }, ), ) to_user = forms.ModelChoiceField( queryset=User.objects.all(), required=False, widget=autocomplete.ModelSelect2( url="user-autocomplete", attrs={ "data-placeholder": "User?", "data-width": None }, ), ) class Meta: model = FOIACommunication fields = "__all__"
class QuestionForm(forms.ModelForm): """Form with autocomplete for user and foia""" user = forms.ModelChoiceField( queryset=User.objects.all(), widget=autocomplete.ModelSelect2( url="user-autocomplete", attrs={ "data-placeholder": "User?", "data-width": None }, ), ) foia = forms.ModelChoiceField( queryset=FOIARequest.objects.all(), required=False, widget=autocomplete.ModelSelect2( url="foia-request-autocomplete", attrs={ "data-placeholder": "FOIA?", "data-width": None }, ), ) class Meta: model = Question fields = "__all__"
class OutboundRequestAttachmentAdminForm(forms.ModelForm): """Form for outbound attachment admin""" foia = forms.ModelChoiceField( queryset=FOIARequest.objects.all(), widget=autocomplete.ModelSelect2( url="foia-request-autocomplete", attrs={ "data-placeholder": "FOIA?", "data-width": None }, ), ) user = forms.ModelChoiceField( queryset=User.objects.all(), widget=autocomplete.ModelSelect2( url="user-autocomplete", attrs={ "data-placeholder": "User?", "data-width": None }, ), ) class Meta: model = OutboundRequestAttachment fields = "__all__"
class FOIAComposerAdminForm(forms.ModelForm): """Form for the FOIA composer admin""" user = forms.ModelChoiceField( queryset=User.objects.all(), widget=autocomplete.ModelSelect2( url="user-autocomplete", attrs={ "data-placeholder": "User?", "data-width": None }, ), ) agencies = forms.ModelMultipleChoiceField( queryset=Agency.objects.all(), required=False, widget=autocomplete.ModelSelect2Multiple( url="agency-autocomplete", attrs={ "data-placeholder": "Agency?", "data-width": None }, ), ) class Meta: model = FOIAComposer fields = "__all__"
class Meta: model = FoiaMachineRequest fields = [ "title", "status", "request_language", "jurisdiction", "agency" ] widgets = { "agency": autocomplete.ModelSelect2( url="agency-autocomplete", attrs={"data-placeholder": "Search agencies"}, forward=("jurisdiction", ), ), "jurisdiction": autocomplete.ModelSelect2( url="jurisdiction-autocomplete", attrs={"data-placeholder": "Search jurisdictions"}, ), } labels = {"request_language": "Request"}
class ReplaceNewAgencyForm(forms.Form): """Form for rejecting and replacing a new agency""" replace_jurisdiction = forms.ModelChoiceField( queryset=Jurisdiction.objects.filter(hidden=False), widget=autocomplete.ModelSelect2( url="jurisdiction-autocomplete", attrs={"data-placeholder": "Search for jurisdiction"}, ), ) replace_agency = forms.ModelChoiceField( label="Move this agency's requests to:", queryset=Agency.objects.filter(status="approved"), widget=autocomplete.ModelSelect2( url="agency-autocomplete", forward=(forward.Field("replace_jurisdiction", "jurisdiction"), ), attrs={"data-placeholder": "Search agencies"}, ), )
class FoiaMachineRequestFilter(django_filters.FilterSet): """Allows FOIA Machine Requests to be filtered by their status, jurisdiction, or agency.""" jurisdiction = django_filters.ModelChoiceFilter( queryset=Jurisdiction.objects.filter(hidden=False), widget=autocomplete.ModelSelect2( url="jurisdiction-autocomplete", attrs={"data-placeholder": "Search jurisdictions"}, ), ) agency = django_filters.ModelChoiceFilter( queryset=Agency.objects.get_approved(), widget=autocomplete.ModelSelect2( url="agency-autocomplete", attrs={"data-placeholder": "Search agencies"} ), ) class Meta: model = FoiaMachineRequest fields = ["status", "jurisdiction", "agency"]
class CrowdsourceAdminForm(forms.ModelForm): """Form for Crowdsource admin""" user = forms.ModelChoiceField( queryset=User.objects.all(), widget=autocomplete.ModelSelect2( url="user-autocomplete", attrs={ "data-placeholder": "User?", "data-width": None }, ), ) project = forms.ModelChoiceField( queryset=Project.objects.all(), required=False, widget=autocomplete.ModelSelect2( url="project-autocomplete", attrs={ "data-placeholder": "Project?", "data-width": None }, ), ) submission_emails = forms.ModelMultipleChoiceField( queryset=EmailAddress.objects.all(), required=False, widget=autocomplete.ModelSelect2Multiple( url="email-autocomplete", attrs={ "data-placeholder": "Emails?", "data-width": None, "data-html": False, }, ), ) class Meta: model = Crowdsource fields = "__all__"
class AgencyAdminForm(forms.ModelForm): """Agency admin form to order users""" user = forms.ModelChoiceField( queryset=User.objects.all(), required=False, widget=autocomplete.ModelSelect2( url="user-autocomplete", attrs={"data-placeholder": "User?", "data-width": None}, ), ) jurisdiction = forms.ModelChoiceField( queryset=Jurisdiction.objects.filter(hidden=False), widget=autocomplete.ModelSelect2( url="jurisdiction-autocomplete", attrs={"data-placeholder": "Jurisdiction?", "data-width": None}, ), ) appeal_agency = forms.ModelChoiceField( queryset=Agency.objects.all(), required=False, widget=autocomplete.ModelSelect2( url="agency-autocomplete", forward=("jurisdiction", forward.Const(True, "appeal")), attrs={"data-placeholder": "Agency?", "data-width": None}, ), ) parent = forms.ModelChoiceField( queryset=Agency.objects.all(), required=False, widget=autocomplete.ModelSelect2( url="agency-autocomplete", forward=("jurisdiction",), attrs={"data-placeholder": "Agency?", "data-width": None}, ), ) class Meta: model = Agency fields = "__all__"
class TagForm(forms.Form): """This form allows the selection of a tag""" tag_select = forms.ModelChoiceField( queryset=Tag.objects.all(), label=" ", required=False, widget=autocomplete.ModelSelect2( url="tag-autocomplete", attrs={"data-placeholder": "Search tags"}, forward=(forward.Const(True, "slug"), ), ), )
class FoiaMachineRequestAdminForm(forms.ModelForm): """Form to include custom choice fields""" jurisdiction = forms.ModelChoiceField( queryset=Jurisdiction.objects.filter(hidden=False), widget=autocomplete.ModelSelect2( url="jurisdiction-autocomplete", attrs={ "data-placeholder": "Jurisdiction?", "data-width": None }, ), ) agency = forms.ModelChoiceField( queryset=Agency.objects.filter(status="approved"), widget=autocomplete.ModelSelect2( url="agency-autocomplete", forward=("jurisdiction", ), attrs={ "data-placeholder": "Agency?", "data-width": None }, ), ) user = forms.ModelChoiceField( queryset=User.objects.all(), widget=autocomplete.ModelSelect2( url="user-autocomplete", attrs={ "data-placeholder": "User?", "data-width": None }, ), ) class Meta: model = models.FoiaMachineRequest fields = "__all__"
class InvokedExemptionAdminForm(forms.ModelForm): """Adds an autocomplete to the invoked exemption request field.""" request = forms.ModelChoiceField( queryset=FOIARequest.objects.all(), widget=autocomplete.ModelSelect2( url="foia-request-autocomplete", attrs={"data-placeholder": "FOIA?", "data-width": None}, ), ) class Meta: model = InvokedExemption fields = "__all__"
class AgencyFilterSet(django_filters.FilterSet): """Allows agencies to be filtered by jurisdiction.""" jurisdiction = django_filters.ModelChoiceFilter( queryset=Jurisdiction.objects.filter(hidden=False), widget=autocomplete.ModelSelect2( url="jurisdiction-autocomplete", attrs={"data-placeholder": "Search for jurisdiction"}, ), ) class Meta: model = Agency fields = ["jurisdiction"]
class ProfileAdminForm(forms.ModelForm): """Form to include custom choice fields""" location = forms.ModelChoiceField( queryset=Jurisdiction.objects.filter(hidden=False), required=False, widget=autocomplete.ModelSelect2( url="jurisdiction-autocomplete", attrs={"data-placeholder": "Jurisdiction?", "data-width": None}, ), ) agency = forms.ModelChoiceField( queryset=Agency.objects.filter(status="approved"), required=False, widget=autocomplete.ModelSelect2( url="agency-autocomplete", attrs={"data-placeholder": "Agency?", "data-width": None}, ), ) class Meta: model = Profile fields = "__all__"
class BulkNewAgencyTaskForm(forms.Form): """Form for creating blank new agencies""" name = forms.CharField(max_length=255) jurisdiction = forms.ModelChoiceField( queryset=Jurisdiction.objects.filter(hidden=False), widget=autocomplete.ModelSelect2( url="jurisdiction-autocomplete", attrs={ "data-placeholder": "Search for jurisdiction", "data-width": "30%" }, ), )
class RecurringDonationAdminForm(forms.ModelForm): """Form to include custom choice fields""" user = forms.ModelChoiceField( queryset=User.objects.all(), required=False, widget=autocomplete.ModelSelect2( url="user-autocomplete", attrs={"data-placeholder": "User?", "data-width": None}, ), ) class Meta: model = RecurringDonation fields = "__all__"
class AgencyMergeForm(forms.Form): """A form to merge two agencies""" good_agency = forms.ModelChoiceField( queryset=Agency.objects.get_approved(), widget=autocomplete.ModelSelect2( url="agency-composer-autocomplete", attrs={"data-placeholder": "Search for agency"}, ), ) bad_agency = forms.ModelChoiceField( queryset=Agency.objects.get_approved(), widget=autocomplete.ModelSelect2( url="agency-composer-autocomplete", attrs={"data-placeholder": "Search for agency"}, ), ) confirmed = forms.BooleanField(initial=False, widget=forms.HiddenInput(), required=False) def __init__(self, *args, **kwargs): confirmed = kwargs.pop("confirmed", False) super(AgencyMergeForm, self).__init__(*args, **kwargs) if confirmed: self.fields["confirmed"].initial = True self.fields["good_agency"].widget = forms.HiddenInput() self.fields["bad_agency"].widget = forms.HiddenInput() def clean(self): cleaned_data = super(AgencyMergeForm, self).clean() good_agency = cleaned_data.get("good_agency") bad_agency = cleaned_data.get("bad_agency") if good_agency and good_agency == bad_agency: raise forms.ValidationError("Cannot merge an agency into itself") return cleaned_data
class ExemptionFilterSet(django_filters.FilterSet): """Allows exemptions to be filtered by jurisdiction""" jurisdiction = django_filters.ModelChoiceFilter( label="Jurisdiction", queryset=Jurisdiction.objects.filter(level__in=("s", "f"), hidden=False), widget=autocomplete.ModelSelect2( url="jurisdiction-autocomplete", attrs={"data-placeholder": "Search for jurisdiction"}, forward=(forward.Const(["s", "f"], "levels"),), ), ) class Meta: model = Exemption fields = ["jurisdiction"]
class AnswerForm(forms.ModelForm): """Form with autocomplete for users""" user = forms.ModelChoiceField( queryset=User.objects.all(), widget=autocomplete.ModelSelect2( url="user-autocomplete", attrs={ "data-placeholder": "User?", "data-width": None }, ), ) class Meta: model = Answer fields = "__all__"
class JurisdictionFilterSet(django_filters.FilterSet): """Allows jurisdiction to be filtered by level of government and state.""" level = django_filters.ChoiceFilter(choices=LEVELS) parent = django_filters.ModelChoiceFilter( label="State", queryset=Jurisdiction.objects.filter(level="s", hidden=False), widget=autocomplete.ModelSelect2( url="jurisdiction-autocomplete", attrs={"data-placeholder": "Search for state"}, forward=(forward.Const(["s"], "levels"),), ), ) class Meta: model = Jurisdiction fields = ["level", "parent"]
class CrowdsourceChoiceForm(forms.Form): """Form to choose a crowdsource""" crowdsource = forms.ModelChoiceField( queryset=Crowdsource.objects.none(), required=False, widget=autocomplete.ModelSelect2( url="crowdsource-autocomplete", attrs={"data-placeholder": "Choose an unstarted crowdsource"}, ), ) def __init__(self, *args, **kwargs): user = kwargs.pop("user") super(CrowdsourceChoiceForm, self).__init__(*args, **kwargs) self.fields["crowdsource"].queryset = Crowdsource.objects.filter( status="draft", user=user)
class CrowdsourceResponseAdminForm(forms.ModelForm): """Form for Crowdsource response admin""" user = forms.ModelChoiceField( queryset=User.objects.all(), widget=autocomplete.ModelSelect2( url="user-autocomplete", attrs={ "data-placeholder": "User?", "data-width": None }, ), ) class Meta: model = CrowdsourceResponse fields = "__all__"
class AgencyEmailAdminForm(forms.ModelForm): """AgencyEmail Inline admin form""" email = forms.ModelChoiceField( queryset=EmailAddress.objects.all(), widget=autocomplete.ModelSelect2( url="email-autocomplete", attrs={ "data-placeholder": "Email?", "data-width": None, "data-html": False, }, ), ) class Meta: model = AgencyEmail fields = "__all__"
class FOIANoteAdminForm(forms.ModelForm): """Form for note inline""" author = forms.ModelChoiceField( label="Author", queryset=User.objects.all(), widget=autocomplete.ModelSelect2( url="user-autocomplete", attrs={ "data-placeholder": "User?", "data-width": None }, ), ) class Meta: model = FOIANote fields = "__all__"
class AgencyPhoneAdminForm(forms.ModelForm): """AgencyPhone Inline admin form""" phone = forms.ModelChoiceField( queryset=PhoneNumber.objects.all(), widget=autocomplete.ModelSelect2( url="phone-autocomplete", attrs={ "data-placeholder": "Phone Number?", "data-width": None, "data-html": False, }, ), ) class Meta: model = AgencyPhone fields = "__all__"
class CrowdfundPaymentAdminForm(forms.ModelForm): """Form for crowdfund payment inline""" user = forms.ModelChoiceField( label="User", queryset=User.objects.all(), required=False, widget=autocomplete.ModelSelect2( url="user-autocomplete", attrs={ "data-placeholder": "User?", "data-width": None }, ), ) class Meta: model = models.CrowdfundPayment fields = "__all__"
class CrowdsourceFilterSet(django_filters.FilterSet): """Filtering for crowdsources for admins""" status = django_filters.ChoiceFilter(choices=(("draft", "Draft"), ("open", "Open"), ("close", "Closed"))) is_staff = django_filters.BooleanFilter( field_name="user__is_staff", label="Staff Owned", widget=forms.Select(choices=NULL_BOOLEAN_CHOICES), ) user = django_filters.ModelChoiceFilter( queryset=User.objects.all(), widget=autocomplete.ModelSelect2( url="user-autocomplete", attrs={"data-placeholder": "Search users"}), ) class Meta: model = Crowdsource fields = ["status", "user"]
class ExemptionAdminForm(forms.ModelForm): """Form to include a jurisdiction and contributor autocomplete""" jurisdiction = forms.ModelChoiceField( queryset=Jurisdiction.objects.filter(hidden=False), widget=autocomplete.ModelSelect2( url="jurisdiction-autocomplete", attrs={"data-placeholder": "Jurisdiction?", "data-width": None}, ), ) contributors = forms.ModelMultipleChoiceField( queryset=User.objects.all(), required=False, widget=autocomplete.ModelSelect2Multiple( url="user-autocomplete", attrs={"data-placeholder": "User?", "data-width": None}, ), ) class Meta: model = Exemption fields = "__all__"
class QuestionFilterSet(django_filters.FilterSet): """Allows question to be filtered by user, date, or if it's unanswered.""" user = django_filters.ModelChoiceFilter( queryset=User.objects.all(), widget=autocomplete.ModelSelect2( url="user-autocomplete", attrs={"data-placeholder": "Search users", "data-minimum-input-length": 2}, ), ) date = django_filters.DateFromToRangeFilter( label="Date Range", lookup_expr="contains", widget=RangeWidget(attrs={"class": "datepicker", "placeholder": "MM/DD/YYYY"}), ) unanswered = django_filters.BooleanFilter( method="unanswered_filter", widget=forms.CheckboxInput() ) tags = django_filters.ModelMultipleChoiceFilter( field_name="tags__name", queryset=Tag.objects.all(), label="Tags", widget=autocomplete.ModelSelect2Multiple( url="tag-autocomplete", attrs={"data-placeholder": "Search tags"} ), ) def unanswered_filter(self, queryset, name, value): """Filter to show either only unanswered questions or all questions""" # pylint: disable=unused-argument if value: return queryset.filter(answers__isnull=True) else: return queryset class Meta: model = Question fields = ["user", "date"]
class CrowdsourceForm(forms.ModelForm, CrowdsourceDataCsvForm): """Form for creating a crowdsource""" prefix = "crowdsource" project = forms.ModelChoiceField( queryset=Project.objects.none(), required=False, widget=autocomplete.ModelSelect2( url="project-autocomplete", attrs={"data-placeholder": "Search projects"}, forward=(forward.Const(True, "manager"), ), ), ) form_json = forms.CharField(widget=forms.HiddenInput(), initial="[]") submission_emails = forms.CharField( help_text="Comma seperated list of emails to send to on submission", required=False, ) class Meta: model = Crowdsource fields = ( "title", "project", "description", "data_limit", "user_limit", "registration", "form_json", "data_csv", "multiple_per_page", "project_only", "project_admin", "submission_emails", "ask_public", ) def __init__(self, *args, **kwargs): user = kwargs.pop("user") super(CrowdsourceForm, self).__init__(*args, **kwargs) self.fields["data_csv"].required = False if not user.profile.is_advanced: del self.fields["registration"] self.fields["project"].queryset = Project.objects.get_manager(user) def clean_form_json(self): """Ensure the form JSON is in the correct format""" # pylint: disable=too-many-branches form_json = self.cleaned_data["form_json"] try: form_data = json.loads(form_json) except ValueError: raise forms.ValidationError("Invalid form data: Invalid JSON") if not isinstance(form_data, list): raise forms.ValidationError("Invalid form data: Not a list") if form_data == []: raise forms.ValidationError( "Having at least one field on the form is required") for data in form_data: label = data.get("label") if not label: raise forms.ValidationError("Invalid form data: Missing label") required = data.get("required", False) if required not in [True, False]: raise forms.ValidationError( "Invalid form data: Invalid required") type_ = data.get("type") if not type_: raise forms.ValidationError( "Invalid form data: Missing type for {}".format(label)) if type_ not in FIELD_DICT: raise forms.ValidationError( "Invalid form data: Bad type {}".format(type_)) field = FIELD_DICT[type_] if field.accepts_choices and "values" not in data: raise forms.ValidationError( "Invalid form data: {} requires choices".format(type_)) if field.accepts_choices and "values" in data: for value in data["values"]: choice_label = value.get("label") if not choice_label: raise forms.ValidationError( "Invalid form data: Missing label for " "choice of {}".format(label)) choice_value = value.get("value") if not choice_value: raise forms.ValidationError( "Invalid form data: Missing value for " "choice {} of {}".format(choice_label, label)) return form_json def clean_submission_emails(self): """Validate the submission emails field""" return EmailAddress.objects.fetch_many( self.cleaned_data["submission_emails"], ignore_errors=False)