I have a basic registration form that includes a BooleanField for people to accept Terms and Privacy Policy. What I want to do is change the language of the ValidationError that is raised if users do not check it.
class RegisterForm(forms.Form):
username = forms.CharField(label="Username")
email = forms.EmailField(label="Email")
location = forms.CharField(label="Location",required=False)
headline = forms.CharField(label="Headline",required=False)
password = forms.CharField(widget=forms.PasswordInput,label="Password")
confirm_password = forms.CharField(widget=forms.PasswordInput,label="Confirm Password")
terms = TermsField(label=mark_safe("I have read and understand the <a href='/terms'>Terms of Service</a> and <a href='/privacy'>Privacy Policy</a>."),required=True)
TermsField is subclassed from BooleanField:
class TermsField(forms.BooleanField):
"Check that user agreed, return custom message."
def validate(self,value):
if not value:
raise forms.ValidationError('You must agree to the Terms of Service and Privacy Policy to use this site.')
else:
super(TermsField, self).validate(value)
It validates correctly in that if a user does not check them TermsField the form does not validate, but it returns the generic "This field is required" error. This seems like a pretty simple task, and I'm sure I'm doing something basic wrong. Any ideas?
It's because Django sees the field is required and no value was provided, so it doesn't even bother calling your validate method (which comes after the built-in validation).
The way to accomplish what you're trying to accomplish is:
class RegisterForm(forms.Form):
# ...other fields
terms = forms.BooleanField(
required=True,
label=mark_safe('I have read and understand the <a href=\'/terms\'>Terms of Service</a> and <a href=\'/privacy\'>Privacy Policy</a>.')
error_messages={'required': 'You must agree to the Terms of Service and Privacy Policy to use Prospr.me.'}
)
That will override the default "required" message defined in Field.default_error_messages.
Related
When creating a form using Flask-WTF and implementing a method, say, to check whether a username is available, I'm curious to how/why such methods work.
What I mean is, not once do you reference any of methods defined in the form class throughout the rest of your code; they seem to work on their own without any interference - can somebody explains how and why it works this way?
For example:
class RegistrationForm(FlaskForm):
username = StringField('Username', validators=[DataRequired()])
email = StringField('Email', validators=[DataRequired(), Email()])
...
def validate_username(self, username):
user = User.query.filter_by(username=username.data).first()
if user is not None:
raise ValidationError('Please use a different username.')
The above code seems to run validate_username on submission of the form without myself having to call it.
This is by convention - when your form is being validated, it will check whether you have defined any custom inline validators in the form of validate_your_field and run these.
You can find more details in the Custom Validators section of documentation.
In my Contact model I use an EmailField to assure I'm saving a valid email address.
In my form however, I only want the user to be able to change the part before the #, the domain part is not user defined. (e.g. every email needs to end with #gmail.com)
I have looked at a lot of questions about modifying Django form field values before and after validation and display phase, but a lot of the answers are kind of 'hacky' or seem to much of a workaround for my case.
Is there some support of kind of a display filter, which manages a fixed prefix/suffix of a Django form field, without having to edit POST values or needing to suppress certain validations?
Use the clean method in your form to validate the email. It'll be something like this
def clean(self):
"""Check if valid email for institution."""
super().clean()
cleaned_data = self.cleaned_data
if not '#gmail.com' in cleaned_data['email']
msg = forms.ValidationError("Your email must be #gmail")
self.add_error('email', msg)
I'm trying to write a generic DetailView for my model (which is related to User), but I don't know how to limit access for specific model (view) for only that User (owner). I've looked into docs but haven't found any guide how to do that the proper way. So far I've managed to overwrite test_func() method of the class using UserPassesTestMixin where i check if object.user == self.request.user but I'm not sure if that's the proper way to do that.
What I've just said may not be clear, so e.g.
Model A of id 4 is related (owned by) User A.
Now, if User B tries to request Model A DetailView (/models/4) he should be rejected with 403 Error Code, or even better, custom error page.
Have you tried a query like this?
MyTable.objects.filter(user=self.request.user)
This only returns the objects related to the current user.
There are few ways you can try
verify user permissions in your own views using the has_perm method provided in the user model.
if user.has_perm('foo.add_bar'):
return HttpResponse("You are authorized to add content!")
else:
return HttpResponse("Permission to add denied")
verify in your templates using the perms variable that is automatically added to the template context.
{% if perms.app_label.can_do_something %}
This content will be shown users with can_do_something permission.
{% endif %}
This content will be shown to all users.
You can also create your own permissions to the models
class SomeModel(models.Model):
owner = models.ForeignKey(User)
content = models.TextField()
class Meta:
permissions = (
('view_content', 'View content'),
)
have a look at this link it will give you an idea.
Is there a way to pre-populate a Django form password field so that it display something in the resulting <input type="password"> html element?
The default behavior seems to be not to display anything when the MyForm(initial = {'passfield':'something'}) is set.
I need this in order to implement an user edit form. I want to display a random string which if the user doesn't modify I will know that he does not want to change the password. So I don't think there is ANY security issue in what I'm trying to do.
It seems that using the render_value argument works not just for the case listed in the Django docs and can be used:
class MyForm(forms.Form):
password_field = forms.CharField(widget = forms.PasswordInput(render_value = True))
According to the docs, Django PasswordField does not support initial value. So even when you pass it, it would not render.
You can either subclass the field and make your own password widget which will allow you to do so or you can use HTML5 placeholder. HTML5 is much more secure bevause you can display something to the user, but not the password itself.
For HTML5 support, you can use https://github.com/adamcupial/django-html5-forms. Then you can do something like (not exact syntax but something along the lines of):
class FooForm(forms.Form):
...
password = forms.PasswordField(..., placeholder="Your password here")
I came across similar situation and I did the following:
class UserForm(forms.ModelForm):
password1 = PasswordField(label="Password")
In the PasswordField there is PasswordInput field you will need to set render_value = True as mentioned above which is by default False, then during initialization of UserForm I passed initial value for password.
UserForm(instance=user, initial={'password1': settings.dummy_password})
Now this initial value was predefined in settings file which I compare if the password is changed then update the password else leave the original as is.
Need help accessing Hidden inputs in a Form clean_data or clean function. Unable to find solution here and Django docs after about 1 hr of searching.
class AccountForm(forms.ModelForm):
class Meta:
model = Account
#action = forms.CharField(widget=forms.HiddenInput()) <--- also tried this
exclude = [
"a_account_number"
]
# Validate that there isn't already an account that exists with a similar company name during account creation
def clean_a_company_name(self):
logging.debug("Value of action %s") % self.data.__getitem__('action')
if Account.objects.filter( a_company_name = self.cleaned_data['a_company_name']).exists() and % self.data.__getitem__('action')== 'create':
logging.debug("In account views - form validation - clean_a_company - company already exists raising exception *****************")
raise forms.ValidationError(u"An organization with this name and owner already exists. Change the Organization name or edit Organization Account information instead of creating a new Organization Account")
return self.cleaned_data["a_company_name"]
Above gives a unicode error. I also tried:
%self.fields['action']
So you are trying to access action field in method for cleaning a_company_name?
You don't have access to other field in field's clean method. You should use form's clean method.
From django docs:
The Form subclass’s clean() method.
This method can perform any validation
that requires access to multiple
fields from the form at once. This is
where you might put in things to check
that if field A is supplied, field B
must contain a valid email address and
the like.
https://docs.djangoproject.com/en/dev/ref/forms/validation/#cleaning-and-validating-fields-that-depend-on-each-other