I'm new to the technology, so I apologyze in advance if the question is too simple.
I'm using self.cleaned_data to get the selected data entered by the user. And it works when clean is called, but not on my save method.
Here is the code
Forms.py
def clean_account_type(self):
if self.cleaned_data["account_type"] == "select": # **here it works**
raise forms.ValidationError("Select account type.")
def save(self):
acc_type = self.cleaned_data["account_type"] # **here it doesn't, (NONE)**
if acc_type == "test1":
doSomeStuff()
Any ideas why that's not working when I call save?
Here is my views.py
def SignUp(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/')
Thanks in advance.
The clean_<field_name methods on the form must return the clean value or raise a ValidationError. From the docs https://docs.djangoproject.com/en/1.4/ref/forms/validation/
Just like the general field clean() method, above, this method should
return the cleaned data, regardless of whether it changed anything or
not.
The simple change would be
def clean_account_type(self):
account_type = self.cleaned_data["account_type"]
if account_type == "select":
raise forms.ValidationError("Select account type.")
return account_type
Related
In the below snippet, I'm validating a basic email form. This seems to work just fine (when I type in emails that aren't valid, the correct errors are raised), but I'm a little confused by what's going on behind the scenes.
Walking through the logic here: if the form is valid, then I know what happens.
However, what happens if the form isn't valid? I guess I'm confused, since there is no else statement, and so I'm wondering if is_valid generates a list of validation errors that are used later in the return render(request, 'index.html', {'form': form})? If not, how exactly are the validation errors generated? I've tried digging through the Django documentation, but I don't see much besides is_valid returns a boolean...
Is that what's going on? Could someone help verify, or if I'm off, help explain what happens when the form is not valid? Thanks!
views.py
def signup(request):
if request.method == 'POST':
form = SubscriberForm(request.POST)
if form.is_valid():
sub = Subscriber(email=request.POST['email'])
sub.save()
return render(request, 'index.html', {'email': sub.email, 'action': 'added'})
else:
form = SubscriberForm()
return render(request, 'index.html', {'form': form})
In case it's needed for context, an excerpt from my forms.py:
class SubscriberForm(forms.Form):
email = forms.EmailField(label='Enter your email:',
max_length=100,
widget=forms.EmailInput(attrs={'class': 'form-control'}))
def clean_email(self):
email = self.cleaned_data['email']
if Subscriber.objects.filter(email=email).exists():
raise ValidationError("Email already exists")
return email
A Form instance is either bound to a set of data, or unbound.
If it’s bound to a set of data, it’s capable of validating that data
If it’s unbound, it cannot do validation
class Form:
...
def is_valid(self):
"""Return True if the form has no errors, or False otherwise."""
return self.is_bound and not self.errors
With a bound Form instance, call the .is_valid() method to run validation and return a boolean designating whether the form is bound and the data is valid(has no errors)
self.is_bound check whether the data is passed to form
self.errors check the property error, which will trigger the full validation process(if _errors not populated yet)
class Form:
...
#property
def errors(self):
"""Return an ErrorDict for the data provided for the form."""
if self._errors is None:
self.full_clean()
return self._errors
After that, self.full_clean will trigger a series of validation, including cleaning individual field(self._clean_fields), whole form(self._clean_form), and post clean hooker(_self._post_clean).
In the process, any client side code that raises ValidationError (i.e raise ValidationError("Email already exists")) will be properly handled by Form itself by adding these errors to the form._errors attribute, which eventually, you could access through form.errors property
class BaseForm:
...
def full_clean(self):
"""
Clean all of self.data and populate self._errors and self.cleaned_data.
"""
self._errors = ErrorDict()
self.cleaned_data = {}
# these three methods will populate the _errors, cleaned_data attribute
self._clean_fields()
self._clean_form()
self._post_clean()
def _clean_fields(self):
# simplified for demonstration purpose
for name, field in self.fields.items():
try:
validate(field)
# your ValidationError("Email already exists") will be catched here
except ValidationError as e:
# add errors to `form._error` dict
self.add_error(name, e)
I am trying to post a ModelForm, but after the is_valid() function, I run another validation coming from another function.
What I want to do is, if the result of the other function is false, the form should raise an error, above the form as in the case "your password cannot be the same".
Since the function runs during the process, I cannot use a clean method in model.
Thanks in advance!
function
def somefunction():
.
.
print ("NOT WORKING")
return False
views.py
def index(request):
form = SomeForm(request.POST)
if request.method == "POST":
if form.is_valid():
if somefunction() == True:
form.save()
return HttpResponseRedirect("/contact/")
else:
form
else:
form
return render(request, "home.html", {'form': form})
You can use add_error method to add error to form manually like this.
form.add_error('<FIELD_NAME>)', 'your password cannot be the same')
But I suggest you to override clean method of form instead.
I have wrote a Django app for the user to upload files and see a list of uploaded files. I want to restrict the uploads to only using gif format and wrote a simple validator. Then I pass that validator in the Model, however it never triggers and the file is saved regardless of the format. Here's what I got so far.
views.py
def list(request):
# Handle file upload
if request.method == 'POST':
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
newdoc = Document(docfile=request.FILES['docfile'])
newdoc.save()
messages.add_message(request, messages.INFO, "Saved")
# Redirect to the document list after POST
return HttpResponseRedirect(reverse('list'))
else:
form = DocumentForm() # A empty, unbound form
# Load documents for the list page
documents = Document.objects.all()
# Render list page with the documents and the form
return render(
request,
'list.html',
{'documents': documents, 'form': form}
)
checkformat.py
def validate_file_type(upload):
if not (upload.name[-4:] == '.gif'):
raise ValidationError('File type not supported.')
models.py
from .checkformat import validate_file_type
def content_file_name(instance, filename):
return '/'.join(['documents', str(filename), filename])
class Document(models.Model):
docfile = models.FileField(upload_to=content_file_name, validators=[validate_file_type], null=False, verbose_name="File")
forms.py
class DocumentForm(forms.Form):
docfile = forms.FileField(
label='Select a file', widget=forms.FileInput(attrs={'accept':'image/gif'})
)
Is there something I'm missing? I've just started learning Django. Also, I know this is not a sercure way to check for a file type, but I just want to see it work to continue. Thank you for your time.
if form.is_valid():
newdoc = Document(docfile=request.FILES['docfile'])
if not '.gif' in newdoc.name:
raise ValidationError('File type not supported.')
else:
newdoc.save()
messages.add_message(request, messages.INFO, "Saved")
try this simple solution, hope it works as you need
Looks right so far. Maybe it's simply a lower/upper case issue?
A more accurate solution might be:
import os
def validate_file_type(upload):
if os.path.splitext(upload.name)[1].lower() != '.gif':
raise ValidationError('File type not supported.')
If it's still not working try to add a break point within the validation method and check the value of upload.name.
I think the problem is the form is derived from a simple Model class, but in your case you must use ModelForm instead.
This way the form knows about the Document model, and you can do some fancy operations, like calling the save mehond in the Form object so save the model instance. Also the is_valid method calls all the validations defined in the model, in addition to the validations defined in the Form itself.
def signup(request):
if request.method == 'POST':
if request.POST['password1'] == request.POST['password2']:
try:
user = User.objects.get(username=request.POST['username'])
return render(request, 'accounts/signup.html', {'error':'Username has already been taken'})
except User.DoesNotExist:
user = User.objects.create_user(request.POST['username'], password=request.POST['password1'])
login(request, user)
return render(request, 'accounts/signup.html')
else:
return render(request, 'accounts/signup.html', {'error':'Passwords didn\'t match'})
else:
return render(request, 'accounts/signup.html')
In the following program, the line
user = User.objects.get(username=request.POST['username'])
is confusing me in some point. I know that if I have the dictionary d = {word1 : definition1, word2 : definition2}, then d.get[word1] will output definition1 (the id of word1). So User.objects is a dictionary, because of the structure dict.get(). I have a little problem with this part of the line.
Could anyone be able to explain to me what is the meaning of objects?
Thanks in advance!
objects is a reference to the model's Manager, whos sole purpose is to handle the database queries to retrieve the required data from a database.
Although it has a method get that shares the same name as the get method of a dictionary, they do not do the same thing internally in respect to where the data is retrieved from.
Sorry if my english is bad, but if you need question, i'm here :)
I saw many answers about this subject of HttpResponse object in Django, but i can't resolve it.
Normally the user insert his email address in order to recieve an email for his new password.
def forgottenPwdEmail(request):
if request.method == 'POST':
form = PasswordResetRequestForm(request.POST)
user = User.objects.get(username=request.user.username)
user.confirmed = True
user.save()
sendResetPasswordMail(user, request.META['HTTP_HOST'])
else:
form = PasswordResetRequestForm()
return render(request, 'front/reset_password_form.html', {'form': form})
After these error is displayed : "View" didn't return an HttpResponse object. It returned None instead. I can recieve the mail anyway, so the problem is in this function but i can't resolve it.
If you have some ideas, i am open :)
You are missing a return in your if statement.
def forgottenPwdEmail(request):
if request.method == 'POST':
form = PasswordResetRequestForm(request.POST)
user = User.objects.get(username=request.user.username)
user.confirmed = True
user.save()
return sendResetPasswordMail(user, request.META['HTTP_HOST'])
else:
form = PasswordResetRequestForm()
return render(request, 'front/reset_password_form.html', {'form': form})
I am assuming that the sendResetPasswordMail is also returning a HttpResponse
Hope this helps
It is happening because your view doesn't return a response for a POST request.
You should add something like redirect page when the email is successfully sent, something like this:
def forgottenPwdEmail(request):
if request.method == 'POST':
form = PasswordResetRequestForm(request.POST)
user = User.objects.get(username=request.user.username)
user.confirmed = True
user.save()
sendResetPasswordMail(user, request.META['HTTP_HOST'])
return redirect('/password-reset-email-sent/')
......