class BaseZendeskForm(forms.Form): """Base Form class for all Zendesk forms.""" def __init__(self, user, *args, **kwargs): super(BaseZendeskForm, self).__init__(*args, **kwargs) self.user = user # Add email field for users not logged in. if not user.is_authenticated(): email = forms.EmailField( label=_lazy(u'Email:'), widget=forms.TextInput(attrs={ 'placeholder': EMAIL_PLACEHOLDER })) self.fields['email'] = email subject = StrippedCharField( label=_lazy(u'Subject:'), min_length=4, max_length=255, widget=forms.TextInput(attrs={'placeholder': SUBJECT_PLACEHOLDER}), error_messages={'required': SUBJECT_CONTENT_REQUIRED, 'min_length': SUBJECT_CONTENT_SHORT, 'max_length': SUBJECT_CONTENT_LONG}) body = StrippedCharField( label=_lazy(u'Body:'), min_length=5, max_length=10000, widget=forms.Textarea(attrs={'placeholder': BODY_PLACEHOLDER}), error_messages={'required': BODY_CONTENT_REQUIRED, 'min_length': BODY_CONTENT_SHORT, 'max_length': BODY_CONTENT_LONG}) def ticket_body(self, email): """Body of the ticket to submit to Zendesk.""" return 'Email: {email}\n{body}'.format( email=email, body=self.cleaned_data['body']) def submit_ticket(self): """Submit the ticket to Zendesk.""" if self.user.is_authenticated(): email = self.user.email else: email = self.cleaned_data['email'] submit_ticket( email, self.cleaned_data['category'], self.cleaned_data['subject'], self.ticket_body(email), [])
class ExampleForm(forms.Form): """Example form to test a bunch of Django fields.""" char = forms.CharField(max_length=10) char_optional = forms.CharField(required=False, widget=forms.TextInput()) file = forms.FileField(max_length=10) choice = forms.ChoiceField(choices=((1, 1), (2, 2))) stripped_char = StrippedCharField(max_length=10) bool = forms.BooleanField() textarea = StrippedCharField(widget=forms.Textarea()) email = forms.EmailField() url = forms.URLField(required=False, verify_exists=False) date = forms.DateField() time = forms.TimeField()
class ReviewForm(forms.Form): comment = StrippedCharField(max_length=2000, widget=forms.Textarea(), required=False, label=_lazy(u'Comment:'), error_messages={'max_length': COMMENT_LONG}) _widget = forms.RadioSelect(renderer=RadioFieldRendererWithHelpText) significance = forms.TypedChoiceField( label=_lazy(u'Significance:'), choices=SIGNIFICANCES, initial=SIGNIFICANCES[1][0], required=False, widget=_widget, coerce=int, empty_value=SIGNIFICANCES[1][0]) is_ready_for_localization = forms.BooleanField( initial=False, label=_lazy(u'Ready for localization'), required=False) needs_change = forms.BooleanField( label=_lazy(u'Needs change'), initial=False, required=False) needs_change_comment = forms.CharField( label=_lazy(u'Comment:'), widget=forms.Textarea(), required=False)
class NewThreadForm(forms.Form): """Form to start a new thread.""" title = StrippedCharField(min_length=5, max_length=255, label=_lazy(u'Title:'), widget=forms.TextInput(attrs={'size': 80}), error_messages={'required': MSG_TITLE_REQUIRED, 'min_length': MSG_TITLE_SHORT, 'max_length': MSG_TITLE_LONG}) content = StrippedCharField( label=_lazy(u'Content:'), min_length=5, max_length=10000, widget=forms.Textarea(attrs={'rows': 30, 'cols': 76}), error_messages={'required': MSG_CONTENT_REQUIRED, 'min_length': MSG_CONTENT_SHORT, 'max_length': MSG_CONTENT_LONG})
class EditThreadForm(forms.ModelForm): """Form to start a new thread.""" title = StrippedCharField(min_length=5, max_length=255, label=_lazy(u'Title:'), widget=forms.TextInput(attrs={'size': 80}), error_messages={'required': MSG_TITLE_REQUIRED, 'min_length': MSG_TITLE_SHORT, 'max_length': MSG_TITLE_LONG}) class Meta: model = Thread fields = ('title',)
class EditPostForm(forms.Form): """Form to edit an existing post.""" content = StrippedCharField( label=_lazy(u'Content:'), min_length=5, max_length=10000, widget=forms.Textarea(attrs={'rows': 30, 'cols': 76}), error_messages={'required': MSG_CONTENT_REQUIRED, 'min_length': MSG_CONTENT_SHORT, 'max_length': MSG_CONTENT_LONG}) class Meta: model = Post exclude = ('thread', 'author', 'updated', 'created', 'updated_by')
class ReplyForm(forms.ModelForm): """Reply form for forum threads.""" content = StrippedCharField( label=_lazy(u'Content:'), min_length=5, max_length=10000, widget=forms.Textarea(attrs={'rows': 10, 'cols': 80}), error_messages={'required': MSG_CONTENT_REQUIRED, 'min_length': MSG_CONTENT_SHORT, 'max_length': MSG_CONTENT_LONG}) class Meta: model = Post fields = ('content', )
class AnswerForm(forms.Form): """Form for replying to a question.""" content = StrippedCharField( label=_lazy('Content:'), min_length=5, max_length=10000, widget=forms.Textarea(attrs={'placeholder': REPLY_PLACEHOLDER}), error_messages={'required': MSG_CONTENT_REQUIRED, 'min_length': MSG_CONTENT_SHORT, 'max_length': MSG_CONTENT_LONG}) class Meta: model = Answer fields = ('content',)
class MediaForm(forms.ModelForm): """Common abstractions for Image form.""" locale = forms.ChoiceField(required=False, label=_lazy(u'Locale'), choices=[(k, LOCALES[k].native) for k in settings.SUMO_LANGUAGES], initial=settings.WIKI_DEFAULT_LANGUAGE) title = StrippedCharField(required=False, label=_lazy(u'Title'), help_text=TITLE_HELP_TEXT % {'type': u'Image'}, min_length=5, max_length=255, error_messages={ 'required': MSG_TITLE_REQUIRED, 'min_length': MSG_TITLE_SHORT, 'max_length': MSG_TITLE_LONG }) description = StrippedCharField(required=False, label=_lazy(u'Description'), help_text=DESCRIPTION_HELP_TEXT, max_length=10000, widget=forms.Textarea(), error_messages={ 'required': MSG_DESCRIPTION_REQUIRED, 'max_length': MSG_DESCRIPTION_LONG }) def __init__(self, *args, **kwargs): self.is_ajax = kwargs.pop('is_ajax', True) super(MediaForm, self).__init__(*args, **kwargs) if not self.is_ajax: self.fields['locale'].required = True self.fields['title'].required = True self.fields['description'].required = True def save(self, update_user=None, is_draft=True, **kwargs): return save_form(self, update_user, is_draft=is_draft, **kwargs)
class MarketplaceRefundForm(BaseZendeskForm): transaction_id = StrippedCharField( label=_lazy(u'Transaction ID:'), widget=forms.TextInput( attrs={'placeholder': TRANSACTION_ID_PLACEHOLDER}), error_messages={'required': TRANSACTION_ID_REQUIRED}) category = forms.ChoiceField(label=_lazy(u'Category:'), choices=REFUND_CATEGORY_CHOICES) @property def ticket_body(self): """Body of the ticket to submit to Zendesk.""" return 'Transaction ID: {id}\nCategory: {category}\n{body}'.format( id=self.cleaned_data['transaction_id'], category=self.cleaned_data['category'], body=self.cleaned_data['body'])
class DocumentForm(forms.ModelForm): """Form to create/edit a document.""" def __init__(self, *args, **kwargs): # Quasi-kwargs: can_archive = kwargs.pop('can_archive', False) can_edit_needs_change = kwargs.pop('can_edit_needs_change', False) initial_title = kwargs.pop('initial_title', '') super(DocumentForm, self).__init__(*args, **kwargs) title_field = self.fields['title'] title_field.initial = initial_title slug_field = self.fields['slug'] slug_field.initial = slugify(initial_title) topics_field = self.fields['topics'] topics_field.choices = Topic.objects.values_list('id', 'title') products_field = self.fields['products'] products_field.choices = Product.objects.values_list('id', 'title') related_documents_field = self.fields['related_documents'] related_documents_field.choices = Document.objects.values_list('id', 'title') # If user hasn't permission to frob is_archived, remove the field. This # causes save() to skip it as well. if not can_archive: del self.fields['is_archived'] # If user hasn't permission to mess with needs_change*, remove the # fields. This causes save() to skip it as well. if not can_edit_needs_change: del self.fields['needs_change'] del self.fields['needs_change_comment'] title = StrippedCharField( min_length=5, max_length=255, widget=forms.TextInput(), label=_lazy(u'Title:'), help_text=_lazy(u'Title of article'), error_messages={'required': TITLE_REQUIRED, 'min_length': TITLE_SHORT, 'max_length': TITLE_LONG}) # We don't use forms.SlugField because it is too strict in # what it allows (English/Roman alpha-numeric characters and dashes). # Instead, we do custom validation in `clean_slug` below. slug = StrippedCharField( min_length=3, max_length=255, widget=forms.TextInput(), label=_lazy(u'Slug:'), help_text=_lazy(u'Article URL'), error_messages={'required': SLUG_REQUIRED, 'min_length': SLUG_SHORT, 'max_length': SLUG_LONG}) products = forms.MultipleChoiceField( label=_lazy(u'Relevant to:'), required=False, widget=forms.CheckboxSelectMultiple()) is_localizable = forms.BooleanField( initial=True, label=_lazy(u'Allow translations:'), required=False) is_archived = forms.BooleanField( label=_lazy(u'Obsolete:'), required=False) allow_discussion = forms.BooleanField( label=_lazy(u'Allow discussion on this article?'), initial=True, required=False) category = forms.ChoiceField( choices=CATEGORIES, # Required for non-translations, which is # enforced in Document.clean(). required=False, label=_lazy(u'Category:'), help_text=_lazy(u'Type of article')) topics = forms.MultipleChoiceField( label=_lazy(u'Topics:'), required=False, widget=ProductTopicsAndSubtopicsWidget()) related_documents = forms.MultipleChoiceField( label=_lazy(u'Related documents:'), required=False, widget=RelatedDocumentsWidget()) locale = forms.CharField(widget=forms.HiddenInput()) needs_change = forms.BooleanField( label=_lazy(u'Needs change:'), initial=False, required=False) needs_change_comment = forms.CharField( label=_lazy(u'Comment:'), widget=forms.Textarea(), required=False) def clean_slug(self): slug = self.cleaned_data['slug'] # Blacklist /, ?, % and +, if not re.compile(r'^[^/^\+^\?%]+$').match(slug): raise forms.ValidationError(SLUG_INVALID) return slug def clean(self): c = super(DocumentForm, self).clean() locale = c.get('locale') # Products are required for en-US products = c.get('products') if (locale == settings.WIKI_DEFAULT_LANGUAGE and (not products or len(products) < 1)): raise forms.ValidationError(PRODUCT_REQUIRED) # Topics are required for en-US topics = c.get('topics') if (locale == settings.WIKI_DEFAULT_LANGUAGE and (not topics or len(topics) < 1)): raise forms.ValidationError(TOPIC_REQUIRED) return c class Meta: model = Document fields = ('title', 'slug', 'category', 'is_localizable', 'products', 'topics', 'locale', 'is_archived', 'allow_discussion', 'needs_change', 'needs_change_comment', 'related_documents') def save(self, parent_doc, **kwargs): """Persist the Document form, and return the saved Document.""" doc = super(DocumentForm, self).save(commit=False, **kwargs) doc.parent = parent_doc # If document doesn't need change, clear out the comment. if not doc.needs_change: doc.needs_change_comment = '' # Create the share link if it doesn't exist and is in # a category it should show for. doc.save() if (doc.category in settings.IA_DEFAULT_CATEGORIES and not doc.share_link): # This operates under the constraints of passing in a list. add_short_links.delay([doc.pk]) self.save_m2m() if parent_doc: # Products are not set on translations. doc.products.remove(*[p for p in doc.products.all()]) return doc
class RevisionForm(forms.ModelForm): """Form to create new revisions.""" keywords = StrippedCharField(required=False, label=_lazy(u'Keywords:'), help_text=_lazy(u'Affects search results')) summary = StrippedCharField( min_length=5, max_length=1000, widget=forms.Textarea(), label=_lazy(u'Search result summary:'), help_text=_lazy(u'Only displayed on search results page'), error_messages={'required': SUMMARY_REQUIRED, 'min_length': SUMMARY_SHORT, 'max_length': SUMMARY_LONG}) content = StrippedCharField( min_length=5, max_length=100000, label=_lazy(u'Content:'), widget=forms.Textarea(), error_messages={'required': CONTENT_REQUIRED, 'min_length': CONTENT_SHORT, 'max_length': CONTENT_LONG}) expires = forms.DateField( label=_lazy(u'Expiry date:'), required=False) comment = StrippedCharField(required=False, label=_lazy(u'Comment:')) class Meta(object): model = Revision fields = ('keywords', 'summary', 'content', 'comment', 'based_on', 'expires') def __init__(self, *args, **kwargs): super(RevisionForm, self).__init__(*args, **kwargs) self.fields['based_on'].widget = forms.HiddenInput() self.fields['comment'].widget = forms.TextInput( attrs={'maxlength': MAX_REVISION_COMMENT_LENGTH}) def save(self, creator, document, based_on_id=None, base_rev=None, **kwargs): """Persist me, and return the saved Revision. Take several other necessary pieces of data that aren't from the form. """ # Throws a TypeError if somebody passes in a commit kwarg: new_rev = super(RevisionForm, self).save(commit=False, **kwargs) new_rev.document = document new_rev.creator = creator if based_on_id: new_rev.based_on_id = based_on_id # If the document doesn't allow the revision creator to edit the # keywords, keep the old value. if base_rev and not document.allows(creator, 'edit_keywords'): new_rev.keywords = base_rev.keywords new_rev.save() return new_rev
def __init__(self, product=None, category=None, *args, **kwargs): """Init the form. We are adding fields here and not declaratively because the form fields to include depend on the selected product/category. """ super(EditQuestionForm, self).__init__(*args, **kwargs) # Extra fields required by product/category selected extra_fields = [] if product: extra_fields += product.get('extra_fields', []) if category: extra_fields += category.get('extra_fields', []) # Add the fields to the form error_messages = { 'required': MSG_TITLE_REQUIRED, 'min_length': MSG_TITLE_SHORT, 'max_length': MSG_TITLE_LONG } field = StrippedCharField(label=TITLE_LABEL, min_length=5, max_length=160, widget=forms.TextInput(), error_messages=error_messages) self.fields['title'] = field error_messages = { 'required': MSG_CONTENT_REQUIRED, 'min_length': MSG_CONTENT_SHORT, 'max_length': MSG_CONTENT_LONG } field = StrippedCharField(label=CONTENT_LABEL, min_length=5, max_length=10000, widget=forms.Textarea(), error_messages=error_messages) self.fields['content'] = field if 'sites_affected' in extra_fields: field = StrippedCharField(label=SITE_AFFECTED_LABEL, initial='http://', required=False, max_length=255, widget=forms.TextInput()) self.fields['sites_affected'] = field if 'crash_id' in extra_fields: field = StrippedCharField(label=CRASH_ID_LABEL, help_text=CRASH_ID_HELP, required=False, max_length=255, widget=forms.TextInput()) self.fields['crash_id'] = field if 'frequency' in extra_fields: field = forms.ChoiceField(label=FREQUENCY_LABEL, choices=FREQUENCY_CHOICES, required=False) self.fields['frequency'] = field if 'started' in extra_fields: field = StrippedCharField(label=STARTED_LABEL, required=False, max_length=255, widget=forms.TextInput()) self.fields['started'] = field if 'addon' in extra_fields: field = StrippedCharField(label=ADDON_LABEL, required=False, max_length=255, widget=forms.TextInput()) self.fields['addon'] = field if 'troubleshooting' in extra_fields: widget = forms.Textarea(attrs={'class': 'troubleshooting'}) field = StrippedCharField(label=TROUBLESHOOTING_LABEL, help_text=TROUBLESHOOTING_HELP, required=False, max_length=655360, widget=widget) self.fields['troubleshooting'] = field if 'ff_version' in extra_fields: self.fields['ff_version'] = StrippedCharField( label=FF_VERSION_LABEL, required=False) if 'device' in extra_fields: self.fields['device'] = StrippedCharField(label=DEVICE_LABEL, required=False) if 'os' in extra_fields: self.fields['os'] = StrippedCharField(label=OS_LABEL, required=False) if 'plugins' in extra_fields: widget = forms.Textarea(attrs={'class': 'plugins'}) self.fields['plugins'] = StrippedCharField(label=PLUGINS_LABEL, required=False, widget=widget)