When to use form vs model validation? - django

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.

Related

Django Rest Framework -A concrete example of when you would use a serializer class vs a model serializer class

I am learning django rest framework, while I understand what a serializer does and when you would use it, I cannot fully seat the need for a serializer and a model serialzer class. Can one of you please give me a concrete real world example use case of both please?
Yes I have gone through the tutorial on DRF website several times and I still am experiencing fuzziness
There is an excellent example on the DRF tutorial and it would take too much to cover in an answer, but I would like to make some points.
First, the DRF documentation explains:
Our SnippetSerializer class is replicating a lot of information that's also contained in the Snippet model. It would be nice if we could keep our code a bit more concise.
In the same way that Django provides both Form classes and ModelForm classes, REST framework includes both Serializer classes, and ModelSerializer classes.
The Snippet model is the name of the model used in that example. So as the documentation says, rather than typing again the same fields from the model over to a Serializer, we can use a ModelSerializer as a shortcut, in a similar way that we would use a ModelForm over a simple Form.
But this leaves the question essentially as "ok, then why is there a simple Serializer class at all?", as you pointed out in your comment.
In the vast majority of cases where you have models and you need to serialize/deserialize relevant data (usually JSON but not limited to), then ModelSerializer is the way to go. Even if additional fields, related serializers or arbitrary logic is required, a ModelSerializer can be easily tweaked. Personally it has never occured to me with any of my projects that ModelSerializer is not suitable for data related to a model.
But there may be cases where you need to handle data that do not abide to a model. Such data would be POSTed to a DRF view and a Serializer would handle them. Such cases could be for example to send a mail message, to setup a Celery task, to add data to session, and many others that do not involve a model at all.

Why does BaseModelForm update ALL fields, despite documentation saying it does not? Is this a bug?

I'm working on a django project with a legacy DB, using formset to edit a set of rows. There are fields in that DB that I don't want django to update, although I need them in my model. In other words, I want them to be treated as READ-ONLY fields.
Thus, I was happy to read the documentation on saving model formsets, which states:
"When fields are missing from the form (for example because they have
been excluded), these fields will not be set by the save() method. You
can find more information about this restriction, which also holds for
regular ModelForms, in Selecting the fields to use."
https://docs.djangoproject.com/en/1.8/topics/forms/modelforms/#saving-objects-in-the-formset
Indeed, when forms.model.BaseModelForm.save() is invoked, it calls forms.model.save_instance(), nicely passing in all the form fields. BUT than then calls instance.save() WITHOUT passing along the update_fields!! And so ALL the model fields are included in the update query :-(
As a test, I modified forms.model.save_instance() to pass the fields:
instance.save(update_fields=fields)
and voila - the model only saves fields listed by its form.
I'm hoping someone more involved in the django project can tell me if this a bug, or a documentation issue? Should I submit a bug report? Am I missing something - is there some other way I should be enforcing "read only" on those fields?
Using django1.8 and python3.4
I'm not sure why you think this behaviour contradicts that documentation, or why it would need to pass along the fields to update. The instance already has the unchanged data; Django will update the rest of the fields from the form, and save the whole thing.

Process of creating form in Django?

Django is really flexible. The simple html form can be used and processed in Django. But while going through the Django documentation I find that there are numerous ways to write a form in Django. The best I find is to create a forms.py and then create a template for it and process using views. Is this the right approach? I think it's way too easy to validate the form and use it in template using this approach. But I am confused where to apply the validation rules in this process. I want to use less Javascript as possible.
For validation you can specify them by
while defining field using validators attribute
by implementing clean_field() method in form
or clean() method in form for multiple field dependent validation.
The validation will be done when you call form.is_valid() method in the view where you are processing the form.
Here is more detailed documentation. Form and field validation

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.