May 14, 2021 Django
Form processing typically has three paths:
Implementing this yourself often results in a lot of duplicate template code (see Using forms in views). To avoid this, Django provides a common set of class-based views for form processing.
Give the contact form:
the 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
You can use the construction view FormView:
the views.py
from myapp.forms import ContactForm
from django.views.generic.edit import FormView
class ContactView(FormView):
template_name = 'contact.html'
form_class = ContactForm
success_url = '/thanks/'
def form_valid(self, form):
# This method is called when valid form data has been POSTed.
# It should return an HttpResponse.
form.send_email()
return super().form_valid(form)
Notes:
Universal view is really great when you're using models. These generic views will automatically create a ModelForm, as long as they are able to determine which model class to use:
The model form view provides an implementation form_valid () automatically save the model. I f you have special requirements, you can override this setting. See the example below.
You don't even success_urlfor provide a CreateView or UpdateView-get_absolute_url if available, they will be used on model objects.
If you want to use a custom ModelForm, such as adding additional validation, form_class set up on the view.
Note: When you specify a custom form class, you must form_class model ModelForm, even if it is possible.
First, we need to get_absolute_url () to the Author class:
models.py in the middle
from django.db import models
from django.urls import reverse
class Author(models.Model):
name = models.CharField(max_length=200)
def get_absolute_url(self):
return reverse('author-detail', kwargs={'pk': self.pk})
Then we can work with friends on CreativeView. N ote how we configure a common class-based view here. We don't have to write any logic ourselves:
the views.py
from django.urls import reverse_lazy
from django.views.generic.edit import CreateView, DeleteView, UpdateView
from myapp.models import Author
class AuthorCreate(CreateView):
model = Author
fields = ['name']
class AuthorUpdate(UpdateView):
model = Author
fields = ['name']
class AuthorDelete(DeleteView):
model = Author
success_url = reverse_lazy('author-list')
Note: We must use reverse_lazy () instead of reverse(), because the url is not loaded when the file is imported.
The Fields property works in the same way as the internal Meta class property on Fields. Unless you otherwise define the form class, this property is required, and the view throws an ImperlyConfigured exception.
If both fields and form_class are specified, TheflyConfigured throws an exception.
Finally, we connect these new views to URLconf:
the urls.py
from django.urls import path
from myapp.views import AuthorCreate, AuthorDelete, AuthorUpdate
urlpatterns = [
# ...
path('author/add/', AuthorCreate.as_view(), name='author-add'),
path('author/<int:pk>/', AuthorUpdate.as_view(), name='author-update'),
path('author/<int:pk>/delete/', AuthorDelete.as_view(), name='author-delete'),
]
Note: Some ideas inherit singleObjectTemplateResponseMixin It uses template_name_suffix to build template_name model-based.
In this example:
If you want to provide CreativeView and Provide a separate template, UpdateView, you can set up a template_name or template_name_suffix.
To track users who create objects, CreateView can do this using the custom method ModelForm. First, add the foreign key relationship to the model:
models.py in the middle
from django.contrib.auth.models import User
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=200)
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
# ...
In the view, make sure that you created_by list of fields that you want to edit, and override form_valid() to add users:
the views.py
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.edit import CreateView
from myapp.models import Author
class AuthorCreate(LoginRequiredMixin, CreateView):
model = Author
fields = ['name']
def form_valid(self, form):
form.instance.created_by = self.request.user
return super().form_valid(form)
LoginRequiredMixin prevents users who are not logged in from accessing the form. If you ignore this, you need to deal with the unauthorized user form_valid ().
This is an example of how to implement a form that applies to AJAX requests and "normal" form POST:
from django.http import JsonResponse
from django.views.generic.edit import CreateView
from myapp.models import Author
class AjaxableResponseMixin:
"""
Mixin to add AJAX support to a form.
Must be used with an object-based FormView (e.g. CreateView)
"""
def form_invalid(self, form):
response = super().form_invalid(form)
if self.request.is_ajax():
return JsonResponse(form.errors, status=400)
else:
return response
def form_valid(self, form):
# We make sure to call the parent's form_valid() method because
# it might do some processing (in the case of CreateView, it will
# call form.save() for example).
response = super().form_valid(form)
if self.request.is_ajax():
data = {
'pk': self.object.pk,
}
return JsonResponse(data)
else:
return response
class AuthorCreate(AjaxableResponseMixin, CreateView):
model = Author
fields = ['name']
For more information:
https://docs.djangoproject.com/en/3.0/