Django validation best practice - django

I'm implementing a custom Django form which just contains an email address field.
As well as the usual email field type validation, I want to add some extra checks, such as whether this email address has already been used for this user etc.
What is the best practice way of doing this using class-based views (FormView, in this case, obviously) ?
Should I put the validation code:-
in the form_valid() method of the FormView or
in the clean_email() method of the form class
Option 2 seems the neatest to me, but if I go that way, I need to pass the user into the form (and pop it in the init method) so that the clean_email method can use to do database lookups which doesn't seem quite right either.

Use the latter approach since you know it would be neatest one.
Another benefit of going via this approach will be that you can identify which function your validation error occurred which might be helpful when you want to add more validations in future.
And then what other ways do you have to check if user is already present in the system.
You have to add the logic in view then.

Related

When to use form vs model validation?

Just curious. What is the best practice for when to use form vs model validation?
From what I understand currently, form validation should be used for:
AJAX / HTTP requests params
Forms that do not correlate to a model?
Another question is: I have a HTML form that roughly correlates to a model instance, do I use a ModelForm for it?
Definitely use ModelForm, if your form resembles model object even in a tiny bit.
If there are some minor differences (e.g. you don't use some of the fields or you want to use different error messages etc.) it's much easier to customize ModelForm then to use Form and implement all this functionality from scratch.
For more reference regarding ModelForm please checkout PyDanny's Core Concepts of Django ModelForms.
I am also trying to understand what is the difference/relation between form and model validation and I would like to share my notes that are formed after reading several docs.
I am currently interested in Creating Forms from Models
#mariodev shared the document Core Concepts of Django ModelForms and this provided a good start.
ModelForms select validators based off of Model field definitions
The main story behind the scenes seems to be the DRY principal. This article explains very well what exactly is the case here.
All right, all this is fair. The question is "Where in the Django Documentation is this explained"?
I bumped on a very brilliant article where it states that:
The form.full_clean() method is called by django at the start of the validation process (by form.is_valid(), usually immediately after the view receives the posted data).
Correct me if I am wrong but that line reads that everytime I enter data and hit 'enter' the validation process begins!
OK, this is simple now:
The validation on a ModelForm begins when we hit 'enter'.
Django first validates the form by checking one by one every applicable validation method on Fields, Field Subclasses (This is the documentation for a model's field subclass, not for a form field subclass), Form Subclasses and ModelForm (since it is a ModelForm).
Finally, it validates the Model Instance.
This is how all this works theoretically. The only thing that remains is to implement it.

django form methods are for validation only or not?

While I am studying the new django docs on class-based views, I notice this example code:
# forms.py
from django import forms
class ContactForm(forms.Form):
name = forms.CharField()
message = forms.CharField(widget=forms.Textarea)
def send_email(self):
# send email using the self.cleaned_data dictionary
pass
The fact of seeing send_email as a method of ContactForm really annoys me. I have always thought form methods should be for validation purpose and methods that consume forms (like send_email in this case) should be in the views layer. Am I missing anything here? Or should the example be corrected?
There is no correct answer for this one. It really depends on your coding style. Using a form for more than just validation is as valid as doing this method in the view.
The above example has some kind of advantage though. Lets say you have one model and you want to use different forms (with different logic) for it. Instead of putting the logic in the view and check which form is now used it probably better to put this logic on the form level.
The first time I got the same weird feeling was when I encountered the LoginForm from django.contrib.auth that also verifies that the user's browser is capable of working with cookies aside from managing the credentials passed in.
Personally, I agree with you. I'm more inclined to think that the view should be the responsible actor for performing the action of sending the email rather than the form and that send_email should be a method defined in the view.
But, then again, you can easily observe how a lot of us use Django differently or have a different approach to solving the same problems. Due to the fact that we have different concerns in mind when developing our applications, it's quite possible we have a different understanding of how certain framework components are meant to be used, which is a bit of a moot point. In the end, what's important to acknowledge is that it's possible to delegate some of the heavy-lifting from the view to the form in a manner that's well-defined.
There is nothing wrong with the example. For any but the simplest of cases, your form will contain only cleaning methods; most forms do extra validation and other actions. In the end, it is just a Python class and you can do whatever you would like in it; there is no "rule" except maybe DRY.
We have form methods that validate against external services, call other procedures and trigger workflows. For such complicated logic, it is best to embed it in to the form class as it increases reusability of the code. Developers working on the view simply use the form class as a library and don't have to worry about exotic validation requirements. In this case, it actually promotes DRY.
When we have to update the logic we only update the form class's "private" methods (those prefixed with _). This keeps the "public" interface (documented by django) intact and all view code using that form doesn't have to be updated.

Separating form input and model validation in Django?

Is it typical to separate input validation from model-level validation in Django projects? For example, validating that a username fits naming criteria would be input validation, and verifying that the user isn't already in the database would be model-level validation.
I've been looking at a co-worker's code, and they put both types of validation in a form class (in forms.py). Is this the typical setup, or is it more common for the model-level validation to appear in the model or view?
Or is there a better way to be approaching this-- such as using a ModelForm? I'm rather new to Django and trying to learn what is the recommended pattern for this situation.
This is a very interesting question (for me).
In my opinion, all validation code should be moved to model code. This is the way to not break business rules. When validation code is in the model it is not possible to forget some validation in a new form or to have inconsistent rules in several forms.
I link to you 'Django, Raise a validation error in a model's save method' question that is related to yours. Below question you can see how move code validations from forms to model. I hope that this brief introduction can helps to you.
From what framework you come? How validation rules are writen in your enviromnent?
I don't agree with the accepted answer. I prefer to use model-level validation to avoid inconsistencies in models, and form-level validation for any site-specific restrictions.
Suppose we have a model for events, with datetime fields for the start and end time. Model validation would force us to have an end time that comes after the start time. However, I would leave it in the form to validate that the newly created event is not in the past. Therefore, if I ever have to add an event that occured in the past, I could use an admin-specific form that allows dates in the past, or simply add it straight to the database.
Thus, model validation should only check for values that are patently wrong. but if you ever need to do something funky (Unicode characters in a username for a bot, for example), it should let you do it, even if it's only through the admin or the shell. I've read an answer on StackOverflow that suggested always using forms in backend code, filling fields with code like form["field"] = "value", to benefit from consistent validation.

Externally add form errors in Django

I have a Django form that will add an entry to a database with a unique constraint on one of the columns. If the submission happens to attempt creation of a duplicate, I get a django.db.utls.IntegrityError stating I violated the unique constraint (thankfully).
When processing Django forms, there are a number of ways to validate:
Override the form class' clean method
Override the form class' clean_<field> method
If the clear_<field> method raises a django.forms.ValidationError, the error message will be appended to a list in the _errors dictionary under the field's name. When using the clean method, errors should be manually inserted into the _errors dict.
Now, the clean and clean_<field> methods don't sound like a nice place to put code that has side effects, and I fear that checking at this moment whether the value is unique does not guarantee I won't get IntegrityErrors. I would prefer to actually try and create the row in the database and signal a form error when a constraint is violated.
My main problem is that forms expose a public property errors which is read-only. Therefore, I should, according to the docs, add a method in my form that does all the work, try to insert in the database and register an error when an IntegrityError is raised. Because the action that processes the form after validation requires lots of other data, I don't want to put the code inside the form class itself.
Is there any other (documented or not) way to go about adding an entry in the errors dict from outside the class, or should I simply access the _errors "private" variable and be happy with that? I know this sounds like an OOP breach, but creating an extra method just to access this "private" variable does not seem to me like it shields anybody from anything.
Edit:
Seems like someone else already raised a similar question, but it seems the answers pointed to manual insertion into _errors...
For now, a simple solution is the following:
try:
# Try to save model instance, which might throw `IntegrityError`.
# ...
except django.db.utils.IntegrityError:
# The form passed validation so it has no errors.
# Use the `setdefault` function just in case.
errors = django.forms.util.ErrorList()
errors = form._errors.setdefault(
django.forms.forms.NON_FIELD_ERRORS, errors)
errors.append('Sorry, this username is already in use.')
I think adding the method to the form is quite reasonable. The ModelForm class, which has a save() method which does the logic of saving the created instance to the database. If your form can inherit from ModelForm (or just add a save() method to your form), you'll still be well within "djangonian" standards.
http://docs.djangoproject.com/en/dev/topics/forms/modelforms/#the-save-method

#django what method is used to represent a model field in admin

I am trying to subclass CharField with a custom unicode method. Basically, I want to be able to call my custom crypto method on the value that is returned by the default model field. I tried the following, but it seems that admin is getting the values some other way. It seems to me that this would be the most pythonic way to implement this, but perhaps I'm wrong.
def PasswordCharField(models.CharField):
def __unicode__(self):
return crypt(super(PasswordCharField,self).__unicode__())
I'm still not really sure why you're trying to encrypt a field on output - that doesn't seem very secure, the usual approach (taken by Django's own password fields) is to hash the data on entry and store that hashed version on the database.
However, if you want to go down this route, there's still no reason to use __unicode__ on a custom field subclass. There's nothing in the documentation that implies that this is what any part of Django - whether the admin or anything else - uses to get the value of a field. In fact, the admin uses exactly the same method to get the value of a field as anything else.
Custom field subclasses are fully described in the documentation, linked from the contents page. Without really understanding what you're trying to do it's hard to tell, but it could be that the to_python method is what you need. Bear in mind though that this will affect the value of the field for all uses in Django.