I get an error in my class AuthorCreateForm when I submit my form. NameError self is not defined
How do I use a CreateForm?
I have created a class in my Author.py file
from django.views.generic import TemplateView, ListView, CreateView
from books.models import Author, Publisher, Book
from books.forms import AuthorForm
class AuthorCreateView(CreateView):
objAuthorForm = AuthorForm(self.request.POST)
if(objAuthorForm.save()):
success = "Form saved!"
else:
error = "There was an error!"
and I have a html template which submits to /Author/Create
and I have the following line in my urls.py
('^authors/create/$', Author.AuthorCreateView.as_view()),
I render the form at this URL
('^authors/new/$', TemplateView.as_view(template_name="author_new.html")),
I find the class based views confusing, does anyone have a good tutorial on how to use it for CRUD operations?
Thanks
CreateView should be used when you need a form on the page and need to do a db insertion on submission of a valid form.
CreateView. A view that displays a form for creating an object, redisplaying the form with validation errors (if there are any) and saving the object. This view inherits methods and attributes from the following views: django.
A view is a callable which takes a request and returns a response. This can be more than just a function, and Django provides an example of some classes which can be used as views. These allow you to structure your views and reuse code by harnessing inheritance and mixins.
What you have is a python error -- self
is not defined. self
is generally what refers to the class instance itself on class methods.
Anyways, I agree, it's brand spanking new and not as documented. I think looking at the source is absolutely key at this point.
To get comfortable with class based views, I'd start by subclassing django.views.generic.base.View
, which implements only a few methods, namely attempting to call a function on the class based on the request method (post, get, head, - look at source).
For example, here's the first step to replace view functions with the new view classes:
class MyClassBasedView(View):
def get(self, request):
# behave exactly like old style views
# except this is called only on get request
return http.HttpResponse("Get")
def post(self, request):
return http.HttpResponse("Post")
(r'^foobar/$', MyClassBasedView.as_view())
Back to your specific question:
All TemplateView.as_view()
does is render the template - CreateView
is a combination of several other classes that handle ModelForms
and template rendering (TemplateView
).
So, for a very basic example, look to the docs for what class mixins
are used by CreateView
.
We see it implements TemplateResponseMixin
, ModelFormMixin
, and ProcessFormView
, each containing a list of methods for those classes.
At the most basic level, provide CreateView
's ModelFormMixin
with the model or custom ModelForm class as documented here.
Your CreateView
class would look something like the following
class AuthorCreateView(CreateView):
form_class = AuthorForm
template_name = 'author_new.html'
success_url = 'success'
With those 3 core attributes set, call it in your URLs.
('^authors/create/$', Author.AuthorCreateView.as_view()),
Render the page and you'll see your ModelForm passed to the template as form
, handling the form validation step (passing in request.POST
/ re-render if invalid), as well as calling form.save()
and redirecting to the success_url
.
To customize behavior, start overriding the methods documented for the mixins
.
Remember that you simply need to return an HttpResponse
from one of these methods just like any regular view function.
Example overriding form_invalid
documented in ModelFormMixin
:
class AuthorCreateView(CreateView):
form_class = AuthorForm
template_name = 'author_new.html'
success_url = 'success'
def form_invalid(self, form):
return http.HttpResponse("form is invalid.. this is just an HttpResponse object")
This per-method overriding starts becoming extremely useful as your forms grow more advanced and ultimately lets you build huge forms with a handful of lines of code, overriding only what is necessary.
Say you want to pass your form custom parameters such as the request
object (very common if you need access to the user in the form): you merely need to override get_form_kwargs
.
class MyFormView(FormView):
def get_form_kwargs(self):
# pass "user" keyword argument with the current user to your form
kwargs = super(MyFormView, self).get_form_kwargs()
kwargs['user'] = self.request.user
return kwargs
Class based views are a shining example of smart class usage. It gave me a great intro towards building my own mixins for views and python classes in general. It is saving countless hours.
Wow this got long. To think it started as a mere URL to the docs comment :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With