class ProcessingFOIARequestFilterSet(JurisdictionFilterSet): """Allows filtering a request by user, agency, jurisdiction, or tags.""" user = django_filters.ModelMultipleChoiceFilter( field_name="composer__user", label="User", queryset=User.objects.all(), widget=autocomplete.ModelSelect2Multiple( url="user-autocomplete", attrs={ "data-placeholder": "Search users", "data-minimum-input-length": 2 }, ), ) agency = django_filters.ModelMultipleChoiceFilter( queryset=Agency.objects.get_approved(), widget=autocomplete.ModelSelect2Multiple( url="agency-autocomplete", attrs={"data-placeholder": "Search agencies"}), ) 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"}), ) class Meta: model = FOIARequest fields = ["user", "agency", "jurisdiction"]
class PortalTaskFilterSet(TaskFilterSet): """Allows portal tasks to be filtered by category""" # pylint: disable=invalid-name category = django_filters.ChoiceFilter(choices=PORTAL_CATEGORIES) agency = django_filters.ModelMultipleChoiceFilter( field_name="communication__foia__agency", label="Agency", queryset=Agency.objects.all(), widget=autocomplete.ModelSelect2Multiple( url="agency-autocomplete", attrs={"data-placeholder": "Search agencies"}), ) communication__foia__portal__type = django_filters.ChoiceFilter( choices=PORTAL_TYPES, label="Portal Type") resolved = django_filters.BooleanFilter(label="Show Resolved", widget=forms.CheckboxInput()) resolved_by = django_filters.ModelMultipleChoiceFilter( queryset=User.objects.all(), widget=autocomplete.ModelSelect2Multiple( url="user-autocomplete", attrs={"data-placeholder": "Search users"}, forward=(forward.Const(True, "tasks"), ), ), ) class Meta: model = PortalTask fields = [ "category", "agency", "communication__foia__portal__type", "resolved", "resolved_by", ]
class AgencyFOIARequestFilterSet(django_filters.FilterSet): """Filters for agency users""" user = django_filters.ModelMultipleChoiceFilter( field_name="composer__user", label="User", queryset=User.objects.all(), widget=autocomplete.ModelSelect2Multiple( url="user-autocomplete", attrs={ "data-placeholder": "Search users", "data-minimum-input-length": 2 }, ), ) 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"}), ) date_range = django_filters.DateFromToRangeFilter( field_name="communications__datetime", label="Date Range", lookup_expr="contains", widget=RangeWidget(attrs={ "class": "datepicker", "placeholder": "MM/DD/YYYY" }), ) class Meta: model = FOIARequest fields = ["user"]
class MyFOIARequestFilterSet(JurisdictionFilterSet): """Allows filtering a request by status, agency, jurisdiction, or tags.""" status = django_filters.ChoiceFilter(choices=BLANK_STATUS) agency = django_filters.ModelMultipleChoiceFilter( queryset=Agency.objects.get_approved(), widget=autocomplete.ModelSelect2Multiple( url="agency-autocomplete", attrs={"data-placeholder": "Search agencies"}), ) 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"}), ) has_embargo = django_filters.BooleanFilter( field_name="embargo", widget=forms.Select(choices=NULL_BOOLEAN_CHOICES)) has_crowdfund = django_filters.BooleanFilter( field_name="crowdfund", lookup_expr="isnull", exclude=True, widget=forms.Select(choices=NULL_BOOLEAN_CHOICES), ) minimum_pages = django_filters.NumberFilter( field_name="communications__files__pages", lookup_expr="gte", label="Min. Pages", distinct=True, widget=forms.NumberInput(), ) date_range = django_filters.DateFromToRangeFilter( field_name="communications__datetime", label="Date Range", lookup_expr="contains", widget=RangeWidget(attrs={ "class": "datepicker", "placeholder": "MM/DD/YYYY" }), ) file_types = django_filters.CharFilter(label="File Types", method="filter_file_types") def filter_file_types(self, queryset, name, value): """Filter requests with certain types of files""" # pylint: disable=unused-argument file_types = value.split(",") query = Q() for file_type in file_types: query |= Q( communications__files__ffile__endswith=file_type.strip()) return queryset.filter(query) class Meta: model = FOIARequest fields = ["status", "agency", "jurisdiction"]
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 TaskFilterSet(django_filters.FilterSet): """Allows tasks to be filtered by whether they're resolved, and by who resolved them.""" resolved = django_filters.BooleanFilter(label="Show Resolved", widget=forms.CheckboxInput()) resolved_by = django_filters.ModelMultipleChoiceFilter( queryset=User.objects.all(), widget=autocomplete.ModelSelect2Multiple( url="user-autocomplete", attrs={"data-placeholder": "Search users"}, forward=(forward.Const(True, "tasks"), ), ), ) assigned = django_filters.ModelMultipleChoiceFilter( queryset=User.objects.all(), widget=autocomplete.ModelSelect2Multiple( url="user-autocomplete", attrs={"data-placeholder": "Search users"}, forward=(forward.Const(True, "tasks"), ), ), ) deferred = django_filters.BooleanFilter(label="Deferred", method="filter_deferred", widget=forms.CheckboxInput()) date_created = django_filters.DateFromToRangeFilter( label="Date Range", lookup_expr="contains", widget=RangeWidget(attrs={ "class": "datepicker", "placeholder": "MM/DD/YYYY" }), ) class Meta: model = Task fields = ["resolved", "resolved_by"] def filter_deferred(self, queryset, name, value): """Check if the foia has a tracking number.""" # pylint: disable=unused-argument if value: queryset = queryset.get_deferred() else: queryset = queryset.get_undeferred() return queryset
class ProjectAdminForm(forms.ModelForm): """Form to include autocomplete fields""" requests = forms.ModelMultipleChoiceField( queryset=FOIARequest.objects.all(), required=False, widget=autocomplete.ModelSelect2Multiple( url="foia-request-autocomplete", attrs={ "data-placeholder": "FOIA?", "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 }, ), ) articles = forms.ModelMultipleChoiceField( queryset=Article.objects.all(), required=False, widget=autocomplete.ModelSelect2Multiple( url="article-autocomplete", attrs={ "data-placeholder": "Article?", "data-width": None }, ), ) class Meta: model = Project fields = "__all__"
class ArticleDateRangeFilterSet(django_filters.FilterSet): """Allows a list of news items to be filtered by a date range, an author, or many tags.""" projects = django_filters.ModelMultipleChoiceFilter( field_name="projects", queryset=lambda request: Project.objects.get_visible(request.user), widget=autocomplete.ModelSelect2Multiple( url="project-autocomplete", attrs={"data-placeholder": "Search projects"}), ) authors = django_filters.ModelMultipleChoiceFilter( queryset=(User.objects.annotate( article_count=Count("authored_articles")).filter( article_count__gt=0)), widget=autocomplete.ModelSelect2Multiple( url="user-autocomplete", attrs={"data-placeholder": "Search authors"}, forward=(forward.Const(True, "authors"), ), ), ) pub_date = django_filters.DateFromToRangeFilter( label="Date Range", lookup_expr="contains", widget=RangeWidget(attrs={ "class": "datepicker", "placeholder": "MM/DD/YYYY" }), ) 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"}), ) class Meta: model = Article fields = ["projects", "authors", "pub_date"]
class ArticleAdminForm(forms.ModelForm): """Form with autocompletes""" authors = forms.ModelMultipleChoiceField( queryset=User.objects.all(), widget=autocomplete.ModelSelect2Multiple( url="user-autocomplete", attrs={ "data-placeholder": "User?", "data-width": None }, ), ) editors = forms.ModelMultipleChoiceField( queryset=User.objects.all(), required=False, widget=autocomplete.ModelSelect2Multiple( url="user-autocomplete", attrs={ "data-placeholder": "User?", "data-width": None }, ), ) foias = forms.ModelMultipleChoiceField( queryset=FOIARequest.objects.all(), required=False, widget=autocomplete.ModelSelect2Multiple( url="foia-request-autocomplete", attrs={ "data-placeholder": "FOIA?", "data-width": None }, ), ) class Meta: model = Article fields = "__all__"
class Meta: model = Project fields = [ "title", "summary", "image", "tags", "description", "contributors", "requests", "articles", ] widgets = { "description": forms.Textarea(attrs={"class": "prose-editor"}), "contributors": autocomplete.ModelSelect2Multiple( url="user-autocomplete", attrs={ "data-placeholder": "Search for users", "data-minimum-input-length": 2, }, ), "requests": autocomplete.ModelSelect2Multiple( url="foia-request-autocomplete", attrs={"data-placeholder": "Search for requests"}, ), "articles": autocomplete.ModelSelect2Multiple( url="article-autocomplete", attrs={"data-placeholder": "Search for articles"}, ), } help_texts = { "title": "Changing the title will change the URL of your project." }
class ProjectFilterSet(django_filters.FilterSet): """Allows a project to be filtered by whether it's featured or by its user.""" contributors = django_filters.ModelMultipleChoiceFilter( queryset=User.objects.all(), widget=autocomplete.ModelSelect2Multiple( url="user-autocomplete", attrs={ "data-placeholder": "Search users", "data-minimum-input-length": 2 }, ), ) 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"}), ) class Meta: model = Project fields = ["contributors"]
class FOIAAccessForm(forms.Form): """Form to add editors or viewers to a request.""" users = forms.ModelMultipleChoiceField( queryset=User.objects.all(), widget=autocomplete.ModelSelect2Multiple( url="user-autocomplete", attrs={"data-placeholder": "User?"}), ) access_choices = [("edit", "Can Edit"), ("view", "Can View")] access = forms.ChoiceField(choices=access_choices) def __init__(self, *args, **kwargs): required = kwargs.pop("required", True) super(FOIAAccessForm, self).__init__(*args, **kwargs) self.fields["users"].required = required self.fields["access"].required = required
class ProxyFilterSet(django_filters.FilterSet): """Allows proxies to be filtered by location.""" location = django_filters.ModelMultipleChoiceFilter( label="State", queryset=Jurisdiction.objects.filter(level="s", hidden=False), widget=autocomplete.ModelSelect2Multiple( url="jurisdiction-autocomplete", attrs={"data-placeholder": "Search for state"}, forward=(forward.Const(["s"], "levels"), ), ), ) class Meta: model = Profile fields = ["location"]
class ProjectManagerForm(forms.Form): """Form for managing a list of projects""" projects = forms.ModelMultipleChoiceField( required=False, queryset=Project.objects.none(), widget=autocomplete.ModelSelect2Multiple( url="project-autocomplete", attrs={"placeholder": "Search for a project"}, forward=(forward.Const(True, "manager"), ), ), ) def __init__(self, *args, **kwargs): user = kwargs.pop("user") super(ProjectManagerForm, self).__init__(*args, **kwargs) self.fields["projects"].queryset = Project.objects.get_manager(user)
class FlaggedTaskFilterSet(TaskFilterSet): """Allows a flagged task to be filtered by a user.""" user = django_filters.ModelMultipleChoiceFilter( queryset=User.objects.all(), widget=autocomplete.ModelSelect2Multiple( url="user-autocomplete", attrs={ "data-placeholder": "Search users", "data-minimum-input-length": 2 }, ), ) category = django_filters.ChoiceFilter(choices=FLAG_CATEGORIES) class Meta: model = FlaggedTask fields = ["user", "category", "resolved", "resolved_by"]
class ReviewAgencyTaskFilterSet(JurisdictionFilterSet, TaskFilterSet): """Allows a review agency task to be filtered by jurisdiction.""" COMPLICATED_LIMIT = 10 jurisdiction_field = "agency__jurisdiction" agency = django_filters.ModelMultipleChoiceFilter( field_name="agency", queryset=Agency.objects.exclude(reviewagencytask=None), widget=autocomplete.ModelSelect2Multiple( url="agency-autocomplete", attrs={"data-placeholder": "Search agencies"}), ) federal = django_filters.ChoiceFilter(method="filter_federal", label="Federal Agencies", choices=BOOLEAN_CHOICES) complicated = django_filters.ChoiceFilter(method="filter_complicated", label="Complicated Tasks", choices=BOOLEAN_CHOICES) class Meta: model = ReviewAgencyTask fields = ["jurisdiction", "agency", "resolved", "resolved_by"] def filter_federal(self, queryset, name, value): """Check if the task is for a federal agency""" # pylint: disable=unused-argument if value == "True": return queryset.filter(agency__jurisdiction__level="f") else: return queryset.exclude(agency__jurisdiction__level="f") def filter_complicated(self, queryset, name, value): """Check if the task is for a federal agency""" # pylint: disable=unused-argument queryset = queryset.annotate(c=CountWhen( agency__foiarequest__status__in=["ack", "processed", "appealing"])) if value == "True": return queryset.filter(c__gte=self.COMPLICATED_LIMIT) else: return queryset.exclude(c__gte=self.COMPLICATED_LIMIT)
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 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 SnailMailTaskFilterSet(TaskFilterSet): """Allows snail mail tasks to be filtered by category, as well as the presence of a tracking number or an agency note.""" category = django_filters.ChoiceFilter(choices=[("", "All")] + SNAIL_MAIL_CATEGORIES) has_address = django_filters.ChoiceFilter(method="filter_has_address", label="Has address", choices=BOOLEAN_CHOICES) has_attachments = django_filters.ChoiceFilter( method="filter_has_attachments", label="Has attachments", choices=BOOLEAN_CHOICES, ) has_tracking_number = django_filters.ChoiceFilter( method="filter_has_tracking_number", label="Has tracking number", choices=BOOLEAN_CHOICES, ) has_agency_notes = django_filters.ChoiceFilter( method="filter_has_agency_notes", label="Has agency notes", choices=BOOLEAN_CHOICES, ) resolved = django_filters.BooleanFilter(label="Show Resolved", widget=forms.CheckboxInput()) resolved_by = django_filters.ModelMultipleChoiceFilter( queryset=User.objects.all(), widget=autocomplete.ModelSelect2Multiple( url="user-autocomplete", attrs={"data-placeholder": "Search users"}, forward=(forward.Const(True, "tasks"), ), ), ) def blank_choice(self, queryset, name, value): """Check if the value is blank""" if value == "True": return queryset.exclude(**{name: ""}) elif value == "False": return queryset.filter(**{name: ""}) return queryset def filter_has_address(self, queryset, name, value): """Check if the foia has an address.""" # pylint: disable=unused-argument if value == "True": return queryset.exclude(communication__foia__address=None) else: return queryset.filter(communication__foia__address=None) def filter_has_attachments(self, queryset, name, value): """Check if the communication has attachments.""" # pylint: disable=unused-argument if value == "True": return queryset.exclude(communication__files=None) else: return queryset.filter(communication__files=None) def filter_has_tracking_number(self, queryset, name, value): """Check if the foia has a tracking number.""" # pylint: disable=unused-argument if value == "True": return queryset.exclude(communication__foia__tracking_ids=None) else: return queryset.filter(communication__foia__tracking_ids=None) def filter_has_agency_notes(self, queryset, name, value): """Check if the agency has notes.""" # pylint: disable=unused-argument return self.blank_choice(queryset, "communication__foia__agency__notes", value) class Meta: model = SnailMailTask fields = [ "category", "has_address", "has_attachments", "has_tracking_number", "has_agency_notes", "resolved", "resolved_by", ]
class BaseComposerForm(forms.ModelForm): """This form creates and updates FOIA composers""" title = forms.CharField( widget=forms.TextInput(attrs={ "placeholder": "Add a title", "class": "submit-required" }), max_length=255, required=False, help_text='i.e., "John Doe Arrest Report" or "2017 Agency Leadership ' 'Calendars". Agencies may see this on emailed requests.', ) requested_docs = forms.CharField( widget=forms.Textarea( attrs={ "placeholder": "Write a short description of the documents you are " "looking for. The more specific you can be, the better.", "class": "submit-required", }), required=False, ) agencies = forms.ModelMultipleChoiceField( queryset=Agency.objects.get_approved(), widget=autocomplete.ModelSelect2Multiple( url="agency-composer-autocomplete", attrs={ "data-placeholder": "Agency's name, followed by location", "data-minimum-input-length": 2, "data-allow-clear": False, }, forward=(forward.Self(), ), ), required=False, help_text="i.e., Police Department, Austin, TX or Office of the " "Governor, Arkansas", ) edited_boilerplate = forms.BooleanField(required=False, label="Edit Template Language") embargo = forms.BooleanField( required=False, help_text="Embargoing a request keeps it completely private from " "other users until the embargo date you set. " "You may change this whenever you want.", ) permanent_embargo = forms.BooleanField(required=False) tags = TagField( widget=TaggitSelect2( url="tag-autocomplete", attrs={ "data-placeholder": "Search tags", "data-width": "100%" }, ), help_text="Separate tags with commas.", required=False, ) parent = forms.ModelChoiceField(queryset=FOIAComposer.objects.none(), required=False, widget=forms.HiddenInput()) action = forms.ChoiceField( choices=[("save", "Save"), ("submit", "Submit"), ("delete", "Delete")], widget=forms.HiddenInput(), ) no_proxy = forms.BooleanField( initial=False, required=False, label="Do not use a proxy to file this request", help_text= "You will be repsonsible for proving any citizenship requirements " "to the agency on your own", ) register_full_name = forms.CharField(label="Full Name or Handle (Public)", required=False) register_email = forms.EmailField(label="Email", required=False) register_newsletter = forms.BooleanField( initial=True, required=False, label="Get MuckRock's weekly newsletter with " "FOIA news, tips, and more", ) login_username = forms.CharField(label="Username", required=False) login_password = forms.CharField(label="Password", widget=forms.PasswordInput(), required=False) class Meta: model = FOIAComposer fields = [ "title", "agencies", "requested_docs", "edited_boilerplate", "embargo", "permanent_embargo", "tags", "parent", "register_full_name", "register_email", "register_newsletter", ] def __init__(self, *args, **kwargs): if not hasattr(self, "_user"): self._user = kwargs.pop("user") self.request = kwargs.pop("request") super(BaseComposerForm, self).__init__(*args, **kwargs) if self._user.is_authenticated: del self.fields["register_full_name"] del self.fields["register_email"] del self.fields["register_newsletter"] del self.fields["login_username"] del self.fields["login_password"] if not self._user.has_perm("foia.embargo_foiarequest"): del self.fields["embargo"] if not self._user.has_perm("foia.embargo_perm_foiarequest"): del self.fields["permanent_embargo"] self.fields["parent"].queryset = FOIAComposer.objects.get_viewable( self._user).distinct() self.fields["agencies"].user = self._user self.fields[ "agencies"].queryset = Agency.objects.get_approved_and_pending( self._user) def save(self, commit=True, update_owners=True): """Update the composer's user and organization""" # pylint: disable=arguments-differ if update_owners: self.instance.user = self.request.user self.instance.organization = self.request.user.profile.organization return super(BaseComposerForm, self).save(commit) def clean_register_email(self): """Do a case insensitive uniqueness check""" email = self.cleaned_data["register_email"] if email and User.objects.filter(email__iexact=email).exists(): raise forms.ValidationError( "User with this email already exists. Please login first.") return email def clean_title(self): """Make sure we have a non-blank(ish) title""" title = self.cleaned_data["title"].strip() if title: return title else: return "Untitled" def clean_agencies(self): """Remove exempt and uncooperative agencies""" return [ a for a in self.cleaned_data["agencies"] if not (a.exempt or a.uncooperative) ] def clean(self): """Check cross field dependencies""" cleaned_data = super(BaseComposerForm, self).clean() if cleaned_data.get("action") == "submit": for field in ["title", "requested_docs", "agencies"]: if not self.cleaned_data.get(field): self.add_error(field, "This field is required when submitting") if cleaned_data.get("permanent_embargo"): cleaned_data["embargo"] = True if not self._user.is_authenticated: register = cleaned_data.get( "register_full_name") and cleaned_data.get("register_email") login = cleaned_data.get("login_username") and cleaned_data.get( "login_password") if not register and not login: raise forms.ValidationError( "You must supply either registration information or " "login information") if login: try: self._user = mini_login( self.request, cleaned_data.get("login_username"), cleaned_data.get("login_password"), ) except HTTPError: raise forms.ValidationError( "Please enter a correct username and password") return cleaned_data
class FOIARequestAdminForm(forms.ModelForm): """Form to include custom choice fields""" agency = forms.ModelChoiceField( queryset=Agency.objects.all(), widget=autocomplete.ModelSelect2( url="agency-autocomplete", attrs={ "data-placeholder": "Agency?", "data-width": None }, ), ) read_collaborators = forms.ModelMultipleChoiceField( queryset=User.objects.all(), required=False, widget=autocomplete.ModelSelect2Multiple( url="user-autocomplete", attrs={ "data-placeholder": "User?", "data-width": None }, ), ) edit_collaborators = forms.ModelMultipleChoiceField( queryset=User.objects.all(), required=False, widget=autocomplete.ModelSelect2Multiple( url="user-autocomplete", attrs={ "data-placeholder": "User?", "data-width": None }, ), ) email = forms.ModelChoiceField( queryset=EmailAddress.objects.all(), required=False, widget=autocomplete.ModelSelect2( url="email-autocomplete", attrs={ "data-placeholder": "Email?", "data-width": None, "data-html": False, }, ), ) fax = forms.ModelChoiceField( queryset=PhoneNumber.objects.filter(type="fax"), required=False, widget=autocomplete.ModelSelect2( url="fax-autocomplete", attrs={ "data-placeholder": "Fax Number?", "data-width": None, "data-html": False, }, ), ) cc_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, }, ), ) proxy = forms.ModelChoiceField( queryset=User.objects.all(), required=False, widget=autocomplete.ModelSelect2( url="user-autocomplete", attrs={ "data-placeholder": "User?", "data-width": None }, ), ) class Meta: model = FOIARequest fields = "__all__"