Reputation: 135
When I used function views, It was able to handle cleaned_data with overriding form.clean() method. I thought when I call form.is_valid method, form.clean() is called too.
Form validation happens when the data is cleaned. If you want to customize this process, there are various places to make changes, each one serving a different purpose. Three types of cleaning methods are run during form processing. These are normally executed when you call the is_valid() method on a form.
Now I'm trying to do same things with class-based-view, but it does not work as I thought.
Here's my forms.py:
class PublishForm(forms.ModelForm):
class Meta:
model = models.Article
exclude = [
'author',
]
def __init__(self, user, *args, **kwargs) -> None:
self.user = user
return super(PublishForm, self).__init__(*args, **kwargs)
def is_valid(self):
print('IS_VALID METHOD CALLED')
return super(PublishForm, self).is_valid()
def clean(self):
print('CLEAN METHOD CALLED')
cleaned = super(PublishForm, self).clean()
cleaned['author'] = self.user
return cleaned
views.py:
class PublishView(generic.CreateView):
form_class = forms.PublishForm
success_url = '/'
template_name = 'ex00/publish.html'
def form_valid(self, form):
print(form.cleaned_data)
return super(PublishView, self).form_valid(form)
def form_invalid(self, form):
print(form.errors)
return super(PublishView, self).form_invalid(form)
and urls.py:
app_name = 'ex00'
urlpatterns = [
path('', views.HomeView.as_view(), name='home'),
path('articles/', views.ShowArticlesView.as_view(), name='show-articles'),
path('detail/<slug:slug>/', views.ArticleDetailView.as_view(), name='article-detail'),
path('favourites/', views.FavouriteArticlesView.as_view(), name='favourite-articles'),
path('login/', views.LogInView.as_view(), name='login'),
path('logout/', views.LogOutView.as_view(), name='logout'),
path('like/', views.LikeView.as_view(), name='like'),
path('register/', views.RegisterView.as_view(), name='register'),
path('publish/', views.PublishView.as_view(), name='publish'),
]
It seems form_valid() does not call neither form.is_valid() or form.clean(). But It was able to get form.cleaned_data().
How does form_valid() work?
What should I do to manipulate cleaned_data like I did it with form.is_valid()?
I can see the message POST CALLED
. But cannot see when added print
at ProcessFormView
that inherited by PublishView
.
my template:
{% extends 'share/base.html' %}
{% load django_bootstrap5 %}
{% block title %}Publishing Article{% endblock %}
{% block style %}
<style>
</style>
{% endblock %}
{% block content %}
<form method="POST">{% csrf_token %}
{{form}}
<input type="submit" value="Post">
</form>
{% endblock %}
Upvotes: 2
Views: 1341
Reputation: 477338
Short answer: It calls it in the post
method. The call to the .clean()
method of the form, is part of the validation with form.is_valid()
.
Indeed, if we take a look at the source code ProcessFormView
[GitHub], the view that is inherited by a CreateView
, FormView
and UpdateView
, we see:
class ProcessFormView(View): def post(self, request, *args, **kwargs): form = self.get_form() if form.is_valid(): return self.form_valid(form) else: return self.form_invalid(form)
The post
method will thus first create a form, and then check if it is valid, and depending on that, it will call the form_valid
method, or the form_invalid
method.
The clean()
method is not called by the view, but it is part of the form.is_valid()
method to clean all individual fields, and then call clean()
to validate items not related to a specific field.
Upvotes: 2