class MRFilterForm(forms.Form): """A generic class to filter a list of items""" user = forms.ModelChoiceField( required=False, queryset=User.objects.all(), widget=autocomplete_light.ChoiceWidget( 'UserAutocomplete', attrs={'placeholder': 'All Users'})) agency = forms.ModelChoiceField( required=False, queryset=Agency.objects.all(), widget=autocomplete_light.ChoiceWidget( 'AgencyAutocomplete', attrs={'placeholder': 'All Agencies'})) jurisdiction = forms.ModelChoiceField( required=False, queryset=Jurisdiction.objects.all(), widget=autocomplete_light.ChoiceWidget( 'JurisdictionAutocomplete', attrs={'placeholder': 'All Jurisdictions'})) tags = TaggitField(widget=TaggitWidget( 'TagAutocomplete', attrs={ 'placeholder': 'All Tags (comma separated)', 'data-autocomplete-minimum-characters': 1}))
class ProjectUpdateForm(forms.ModelForm): """Form for updating a project instance""" tags = TaggitField(widget=TaggitWidget( 'TagAutocomplete', attrs={'placeholder': 'Search tags'}), help_text='Separate tags with commas.', required=False) class Meta: model = Project fields = [ 'title', 'summary', 'image', 'tags', 'description', 'contributors', 'requests', 'articles', ] widgets = { 'description': forms.Textarea(attrs={'class': 'prose-editor'}), 'contributors': autocomplete_light.MultipleChoiceWidget('UserAutocomplete'), 'requests': autocomplete_light.MultipleChoiceWidget('FOIARequestAutocomplete'), 'articles': autocomplete_light.MultipleChoiceWidget('ArticleAutocomplete'), } help_texts = { 'title': 'Changing the title will change the URL of your project.', }
class TagManagerForm(forms.Form): """A form with an autocomplete input for tags""" tags = TaggitField(widget=TaggitWidget( 'TagAutocomplete', attrs={ 'placeholder': 'Tags', 'data-autocomplete-minimum-characters': 1}))
class ResourceBaseAdminForm(ModelForm): # We need to specify autocomplete='TagAutocomplete' or admin views like # /admin/maps/map/2/ raise exceptions during form rendering. # But if we specify it up front, TaggitField.__init__ throws an exception # which prevents app startup. Therefore, we defer setting the widget until # after that's done. keywords = TaggitField(required=False)
class NetworkTagForm(forms.Form): tags = TaggitField(widget=TaggitWidget("TagAutocomplete")) def __init__(self, *args, **kwargs): super(NetworkTagForm, self).__init__(*args, **kwargs) self.helper = FormHelper() self.helper.form_tag = False
class TagManagerForm(forms.Form): """A form with an autocomplete input for tags""" tags = TaggitField( widget=TaggitWidget('TagAutocomplete', attrs={ 'placeholder': 'Tags', 'data-autocomplete-minimum-characters': 1 })) def __init__(self, *args, **kwargs): required = kwargs.pop('required', True) super(TagManagerForm, self).__init__(*args, **kwargs) self.fields['tags'].required = required
class ProjectCreateForm(forms.ModelForm): """Form for the basic fields of a project.""" tags = TaggitField(widget=TaggitWidget( 'TagAutocomplete', attrs={ 'placeholder': 'Search tags', 'data-autocomplete-minimum-characters': 1 }), help_text='Separate tags with commas.', required=False) class Meta: model = Project fields = ['title', 'summary', 'image', 'tags'] help_texts = { 'summary': 'A short description of the project and its goals.', 'image': 'Image should be large and high-resolution.' }
class TrainingForm(ModelForm): """ Form to add/update a training """ _date_widget_options = { "icon_attrs": {"class": "fa fa-calendar"}, "attrs": {"class": "form-control input-sm"}, "format": "%Y-%m-%d %H:%M", # Options for the datetimepickers are not set here on purpose. # They are set in the metadata_form_js.html template because # bootstrap-datetimepicker uses jquery for its initialization # and we need to ensure it is available before trying to # instantiate a new datetimepicker. This could probably be improved. "options": False, } publication_date = forms.DateTimeField( localize=True, widget=DateTimePicker(**_date_widget_options) ) keywords = TaggitField( required=False, help_text=_("A space or comma-separated list of keywords"), widget=TaggitWidget('TagAutocomplete')) def __init__(self, *args, **kwargs): super(TrainingForm, self).__init__(*args, **kwargs) for field in self.fields: help_text = self.fields[field].help_text self.fields[field].help_text = None if help_text != '': self.fields[field].widget.attrs.update( { 'class': 'has-popover', 'data-content': help_text, 'data-placement': 'right', 'data-container': 'body', 'data-html': 'true'}) class Meta: model = Training
class ResourceBaseForm(TranslationModelForm): """Base form for metadata, should be inherited by childres classes of ResourceBase""" owner = forms.ModelChoiceField( empty_label="Owner", label=_("Owner"), required=False, queryset=Profile.objects.exclude(username='******'), widget=ChoiceWidget('ProfileAutocomplete')) date = forms.DateTimeField(label=_("Date"), localize=True, input_formats=['%Y-%m-%d %H:%M %p'], widget=ResourceBaseDateTimePicker( options={"format": "YYYY-MM-DD HH:mm a"})) temporal_extent_start = forms.DateTimeField( label=_("temporal extent start"), required=False, localize=True, input_formats=['%Y-%m-%d %H:%M %p'], widget=ResourceBaseDateTimePicker( options={"format": "YYYY-MM-DD HH:mm a"})) temporal_extent_end = forms.DateTimeField( label=_("temporal extent end"), required=False, localize=True, input_formats=['%Y-%m-%d %H:%M %p'], widget=ResourceBaseDateTimePicker( options={"format": "YYYY-MM-DD HH:mm a"})) poc = forms.ModelChoiceField( empty_label=_("Person outside GeoNode (fill form)"), label=_("Point of Contact"), required=False, queryset=Profile.objects.exclude(username='******'), widget=ChoiceWidget('ProfileAutocomplete')) metadata_author = forms.ModelChoiceField( empty_label=_("Person outside GeoNode (fill form)"), label=_("Metadata Author"), required=False, queryset=Profile.objects.exclude(username='******'), widget=ChoiceWidget('ProfileAutocomplete')) keywords = TaggitField( label=_("Free-text Keywords"), required=False, help_text= _("A space or comma-separated list of keywords. Use the widget to select from Hierarchical tree." ), widget=TreeWidget(autocomplete='HierarchicalKeywordAutocomplete')) """ regions = TreeNodeMultipleChoiceField( label=_("Regions"), required=False, queryset=Region.objects.all(), level_indicator=u'___') """ regions = RegionsMultipleChoiceField(label=_("Regions"), required=False, choices=get_tree_data(), widget=RegionsSelect) regions.widget.attrs = {"size": 20} def __init__(self, *args, **kwargs): super(ResourceBaseForm, self).__init__(*args, **kwargs) for field in self.fields: help_text = self.fields[field].help_text self.fields[field].help_text = None if help_text != '': self.fields[field].widget.attrs.update({ 'class': 'has-popover', 'data-content': help_text, 'data-placement': 'right', 'data-container': 'body', 'data-html': 'true' }) def clean_keywords(self): import urllib import HTMLParser def unicode_escape(unistr): """ Tidys up unicode entities into HTML friendly entities Takes a unicode string as an argument Returns a unicode string """ import htmlentitydefs escaped = "" for char in unistr: if ord(char) in htmlentitydefs.codepoint2name: name = htmlentitydefs.codepoint2name.get(ord(char)) escaped += '&%s;' % name if 'nbsp' not in name else ' ' else: escaped += char return escaped keywords = self.cleaned_data['keywords'] _unsescaped_kwds = [] for k in keywords: _k = urllib.unquote(('%s' % k)).split(",") if not isinstance(_k, basestring): for _kk in [x.strip() for x in _k]: _kk = HTMLParser.HTMLParser().unescape(unicode_escape(_kk)) # Simulate JS Unescape _kk = _kk.replace( '%u', r'\u').decode('unicode-escape') if '%u' in _kk else _kk _hk = HierarchicalKeyword.objects.filter( name__contains='%s' % _kk.strip()) if _hk and len(_hk) > 0: _unsescaped_kwds.append(_hk[0]) else: _unsescaped_kwds.append(_kk) else: _hk = HierarchicalKeyword.objects.filter(name__iexact=_k) if _hk and len(_hk) > 0: _unsescaped_kwds.append(_hk[0]) else: _unsescaped_kwds.append(_k) return _unsescaped_kwds class Meta: exclude = ( 'contacts', 'name', 'uuid', 'bbox_x0', 'bbox_x1', 'bbox_y0', 'bbox_y1', 'srid', 'category', 'csw_typename', 'csw_schema', 'csw_mdsource', 'csw_type', 'csw_wkt_geometry', 'metadata_uploaded', 'metadata_xml', 'csw_anytext', 'popular_count', 'share_count', 'thumbnail', 'charset', 'rating', 'detail_url', 'tkeywords', )
class ResourceBaseForm(TranslationModelForm): """Base form for metadata, should be inherited by childres classes of ResourceBase""" owner = forms.ModelChoiceField( empty_label="Owner", label="Owner", required=False, queryset=Profile.objects.exclude(username='******'), widget=autocomplete_light.ChoiceWidget('ProfileAutocomplete')) _date_widget_options = { "icon_attrs": { "class": "fa fa-calendar" }, "attrs": { "class": "form-control input-sm" }, "format": "%Y-%m-%d %I:%M %p", # Options for the datetimepickers are not set here on purpose. # They are set in the metadata_form_js.html template because # bootstrap-datetimepicker uses jquery for its initialization # and we need to ensure it is available before trying to # instantiate a new datetimepicker. This could probably be improved. "options": False, } date = forms.DateTimeField(localize=True, input_formats=['%Y-%m-%d %I:%M %p'], widget=DateTimePicker(**_date_widget_options)) temporal_extent_start = forms.DateTimeField( required=False, localize=True, input_formats=['%Y-%m-%d %I:%M %p'], widget=DateTimePicker(**_date_widget_options)) temporal_extent_end = forms.DateTimeField( required=False, localize=True, input_formats=['%Y-%m-%d %I:%M %p'], widget=DateTimePicker(**_date_widget_options)) poc = forms.ModelChoiceField( empty_label="Person outside GeoNode (fill form)", label="Point Of Contact", required=False, queryset=Profile.objects.exclude(username='******'), widget=autocomplete_light.ChoiceWidget('ProfileAutocomplete')) metadata_author = forms.ModelChoiceField( empty_label="Person outside GeoNode (fill form)", label="Metadata Author", required=False, queryset=Profile.objects.exclude(username='******'), widget=autocomplete_light.ChoiceWidget('ProfileAutocomplete')) keywords = TaggitField( required=False, help_text=_("A space or comma-separated list of keywords"), widget=TaggitWidget('TagAutocomplete')) regions = TreeNodeMultipleChoiceField(required=False, queryset=Region.objects.all(), level_indicator=u'___') regions.widget.attrs = {"size": 20} def __init__(self, *args, **kwargs): super(ResourceBaseForm, self).__init__(*args, **kwargs) for field in self.fields: help_text = self.fields[field].help_text self.fields[field].help_text = None if help_text != '': self.fields[field].widget.attrs.update({ 'class': 'has-popover', 'data-content': help_text, 'data-placement': 'right', 'data-container': 'body', 'data-html': 'true' }) class Meta: exclude = ('contacts', 'name', 'uuid', 'bbox_x0', 'bbox_x1', 'bbox_y0', 'bbox_y1', 'srid', 'category', 'csw_typename', 'csw_schema', 'csw_mdsource', 'csw_type', 'csw_wkt_geometry', 'metadata_uploaded', 'metadata_xml', 'csw_anytext', 'popular_count', 'share_count', 'thumbnail', 'charset', 'rating', 'detail_url')
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 = ComposerAgencyField( queryset=Agency.objects.get_approved(), widget=autocomplete_light.MultipleChoiceWidget( 'AgencyComposerAutocomplete'), 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 = TaggitField( widget=TaggitWidget('TagAutocomplete', attrs={ 'placeholder': 'Search tags', 'data-autocomplete-minimum-characters': 1 }), 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(), ) 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 agencies""" return [a for a in self.cleaned_data['agencies'] if not a.exempt] 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 ResourceBaseAdminForm(autocomplete_light.ModelForm): keywords = TaggitField(widget=TaggitWidget('TagAutocomplete'), required=False)
class ResourceBaseForm(TranslationModelForm): """Base form for metadata, should be inherited by childres classes of ResourceBase""" owner = forms.ModelChoiceField( empty_label="Owner", label=_("Owner"), required=False, queryset=Profile.objects.exclude(username='******'), widget=ChoiceWidget('ProfileAutocomplete')) date = forms.DateTimeField(label=_("Date"), localize=True, input_formats=['%Y-%m-%d %H:%M %p'], widget=ResourceBaseDateTimePicker( options={"format": "YYYY-MM-DD HH:mm a"})) temporal_extent_start = forms.DateTimeField( label=_("temporal extent start"), required=False, localize=True, input_formats=['%Y-%m-%d %H:%M %p'], widget=ResourceBaseDateTimePicker( options={"format": "YYYY-MM-DD HH:mm a"})) temporal_extent_end = forms.DateTimeField( label=_("temporal extent end"), required=False, localize=True, input_formats=['%Y-%m-%d %H:%M %p'], widget=ResourceBaseDateTimePicker( options={"format": "YYYY-MM-DD HH:mm a"})) poc = forms.ModelChoiceField( empty_label=_("Person outside GeoNode (fill form)"), label=_("Point of Contact"), required=False, queryset=Profile.objects.exclude(username='******'), widget=ChoiceWidget('ProfileAutocomplete')) metadata_author = forms.ModelChoiceField( empty_label=_("Person outside GeoNode (fill form)"), label=_("Metadata Author"), required=False, queryset=Profile.objects.exclude(username='******'), widget=ChoiceWidget('ProfileAutocomplete')) keywords = TaggitField( label=_("Free-text Keywords"), required=False, help_text= _("A space or comma-separated list of keywords. Use the widget to select from Hierarchical tree." ), widget=TreeWidget(autocomplete='HierarchicalKeywordAutocomplete')) """ regions = TreeNodeMultipleChoiceField( label=_("Regions"), required=False, queryset=Region.objects.all(), level_indicator=u'___') """ regions = RegionsMultipleChoiceField(label=_("Regions"), required=False, choices=get_tree_data(), widget=RegionsSelect) regions.widget.attrs = {"size": 20} def __init__(self, *args, **kwargs): super(ResourceBaseForm, self).__init__(*args, **kwargs) for field in self.fields: help_text = self.fields[field].help_text self.fields[field].help_text = None if help_text != '': self.fields[field].widget.attrs.update({ 'class': 'has-popover', 'data-content': help_text, 'data-placement': 'right', 'data-container': 'body', 'data-html': 'true' }) def clean_keywords(self): import urllib keywords = self.cleaned_data['keywords'] _unsescaped_kwds = [] for k in keywords: _k = urllib.unquote(k.decode('utf-8')).decode('utf-8').split(",") if not isinstance(_k, basestring): for _kk in [x.strip() for x in _k]: _unsescaped_kwds.append(_kk) else: _unsescaped_kwds.append(_k) return _unsescaped_kwds class Meta: exclude = ('contacts', 'name', 'uuid', 'bbox_x0', 'bbox_x1', 'bbox_y0', 'bbox_y1', 'srid', 'category', 'csw_typename', 'csw_schema', 'csw_mdsource', 'csw_type', 'csw_wkt_geometry', 'metadata_uploaded', 'metadata_xml', 'csw_anytext', 'popular_count', 'share_count', 'thumbnail', 'charset', 'rating', 'detail_url')
class GroupForm(SanitizeHTMLMixin, ModelForm): """Form for groups.models.Group.""" category = forms.ModelChoiceField(label='Category', queryset=Category.objects.all()) tags = TaggitField(widget=TaggitWidget( 'TagAutocomplete', attrs={'placeholder': "type tags here"}), required=False) display_location = forms.CharField( label="Display Location", help_text=("Optionally enter the location you'd like displayed on the " "group description page."), required=False, widget=forms.TextInput( attrs={'placeholder': "i.e. West Loop, Chicago, IL"})) whitelist_users = forms.ModelMultipleChoiceField( widget=MultipleChoiceWidget('UserAutocomplete'), help_text=u'These users will always be allowed to send to this group.', required=False, queryset=get_user_model().objects.all()) class Meta(object): """Meta options.""" model = Group fields = [ 'category', 'description', 'tags', 'state', 'owners', 'whitelist_users', 'featured', 'private', 'published', 'moderated', 'member_list_published', 'display_location', 'latitude', 'longitude', 'radius' ] widgets = { 'latitude': forms.HiddenInput(), 'longitude': forms.HiddenInput(), 'radius': forms.HiddenInput(), 'owners': MultipleChoiceWidget('UserAutocomplete'), } def clean_description(self): """Cleans the description field""" return self.sanitize_html(self.cleaned_data['description']) def clean_tags(self): """Clean the tags added into the form""" tags = self.cleaned_data['tags'] invalid_tags = [] valid_tags = Tag.objects.values_list('name', flat=True) for tag in tags: if tag not in valid_tags: invalid_tags.append(tag) if invalid_tags: self._errors['tags'] = self.error_class( ['These tags are invalid: %s.' % ', '.join(invalid_tags)]) return tags def save(self, *args, **kwargs): """Save the form""" self.instance.tos_accepted_at = now() result = super(GroupForm, self).save(*args, **kwargs) # For each group owner, added them to the group if self.instance.pk: for owner in self.cleaned_data['owners']: add_user_to_group.delay(owner.pk, self.instance.pk) return result
class WFPDocumentForm(TranslationModelForm): """ For to upload Static Maps. """ permissions = forms.CharField(widget=HiddenInput(attrs={ 'name': 'permissions', 'id': 'permissions' }), required=True) _date_widget_options = { "icon_attrs": { "class": "fa fa-calendar" }, "attrs": { "class": "form-control input-sm" }, "format": "%Y-%m-%d %H:%M", # Options for the datetimepickers are not set here on purpose. # They are set in the metadata_form_js.html template because # bootstrap-datetimepicker uses jquery for its initialization # and we need to ensure it is available before trying to # instantiate a new datetimepicker. This could probably be improved. "options": False, } date = forms.DateTimeField(localize=True, widget=DateTimePicker(**_date_widget_options)) keywords = TaggitField( required=False, help_text=_("A space or comma-separated list of keywords"), widget=TaggitWidget('TagAutocomplete')) def __init__(self, *args, **kwargs): super(WFPDocumentForm, self).__init__(*args, **kwargs) # we need to override help_text for title (comes from ResourceBase) title_help_text = _( 'Please use the following convention: Country Name, Theme, Date - ' 'ex: Afghanistan, Snow Forecast, 17 - 23 February 2015') title_field = self.fields['title'] title_field.help_text = title_help_text for field in self.fields: help_text = self.fields[field].help_text self.fields[field].help_text = None if help_text != '': self.fields[field].widget.attrs.update({ 'class': 'has-popover', 'data-content': help_text, 'data-placement': 'right', 'data-container': 'body', 'data-html': 'true' }) class Meta: model = WFPDocument fields = ( 'title', 'doc_file', 'source', 'orientation', 'page_format', 'categories', 'keywords', 'regions', 'last_version', 'layers', 'date', ) def clean_doc_file(self): """ Ensures the doc_file is valid. """ doc_file = self.cleaned_data.get('doc_file') if doc_file and not os.path.splitext(doc_file.name)[1].lower()[1:] in ( 'gif', 'jpg', 'jpeg', 'pdf', 'png'): raise forms.ValidationError(_("This file type is not allowed")) return doc_file def clean_permissions(self): """ Ensures the JSON field is JSON. """ permissions = self.cleaned_data['permissions'] try: return json.loads(permissions) except ValueError: raise forms.ValidationError(_("Permissions must be valid JSON."))