mirror of https://github.com/django/django.git
Fixed #32271 -- Improved consistency of docs CBV examples.
Co-Authored-By: Carles Pina i Estany <carles@pina.cat>
This commit is contained in:
parent
73b1b225ce
commit
5fd4f22d19
|
@ -220,11 +220,11 @@ MRO is an acronym for Method Resolution Order.
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
from django.views.generic.base import RedirectView
|
from django.views.generic.base import RedirectView
|
||||||
|
|
||||||
from article.views import ArticleCounterRedirectView, ArticleDetail
|
from article.views import ArticleCounterRedirectView, ArticleDetailView
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('counter/<int:pk>/', ArticleCounterRedirectView.as_view(), name='article-counter'),
|
path('counter/<int:pk>/', ArticleCounterRedirectView.as_view(), name='article-counter'),
|
||||||
path('details/<int:pk>/', ArticleDetail.as_view(), name='article-detail'),
|
path('details/<int:pk>/', ArticleDetailView.as_view(), name='article-detail'),
|
||||||
path('go-to-django/', RedirectView.as_view(url='https://djangoproject.com'), name='go-to-django'),
|
path('go-to-django/', RedirectView.as_view(url='https://djangoproject.com'), name='go-to-django'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,7 @@ editing content:
|
||||||
from myapp.forms import ContactForm
|
from myapp.forms import ContactForm
|
||||||
from django.views.generic.edit import FormView
|
from django.views.generic.edit import FormView
|
||||||
|
|
||||||
class ContactView(FormView):
|
class ContactFormView(FormView):
|
||||||
template_name = 'contact.html'
|
template_name = 'contact.html'
|
||||||
form_class = ContactForm
|
form_class = ContactForm
|
||||||
success_url = '/thanks/'
|
success_url = '/thanks/'
|
||||||
|
@ -141,7 +141,7 @@ editing content:
|
||||||
from django.views.generic.edit import CreateView
|
from django.views.generic.edit import CreateView
|
||||||
from myapp.models import Author
|
from myapp.models import Author
|
||||||
|
|
||||||
class AuthorCreate(CreateView):
|
class AuthorCreateView(CreateView):
|
||||||
model = Author
|
model = Author
|
||||||
fields = ['name']
|
fields = ['name']
|
||||||
|
|
||||||
|
@ -220,7 +220,7 @@ editing content:
|
||||||
from django.views.generic.edit import UpdateView
|
from django.views.generic.edit import UpdateView
|
||||||
from myapp.models import Author
|
from myapp.models import Author
|
||||||
|
|
||||||
class AuthorUpdate(UpdateView):
|
class AuthorUpdateView(UpdateView):
|
||||||
model = Author
|
model = Author
|
||||||
fields = ['name']
|
fields = ['name']
|
||||||
template_name_suffix = '_update_form'
|
template_name_suffix = '_update_form'
|
||||||
|
@ -295,7 +295,7 @@ editing content:
|
||||||
from django.views.generic.edit import DeleteView
|
from django.views.generic.edit import DeleteView
|
||||||
from myapp.models import Author
|
from myapp.models import Author
|
||||||
|
|
||||||
class AuthorDelete(DeleteView):
|
class AuthorDeleteView(DeleteView):
|
||||||
model = Author
|
model = Author
|
||||||
success_url = reverse_lazy('author-list')
|
success_url = reverse_lazy('author-list')
|
||||||
|
|
||||||
|
|
|
@ -369,7 +369,7 @@ Adding messages in class-based views
|
||||||
from django.views.generic.edit import CreateView
|
from django.views.generic.edit import CreateView
|
||||||
from myapp.models import Author
|
from myapp.models import Author
|
||||||
|
|
||||||
class AuthorCreate(SuccessMessageMixin, CreateView):
|
class AuthorCreateView(SuccessMessageMixin, CreateView):
|
||||||
model = Author
|
model = Author
|
||||||
success_url = '/success/'
|
success_url = '/success/'
|
||||||
success_message = "%(name)s was created successfully"
|
success_message = "%(name)s was created successfully"
|
||||||
|
@ -386,7 +386,7 @@ method.
|
||||||
from django.views.generic.edit import CreateView
|
from django.views.generic.edit import CreateView
|
||||||
from myapp.models import ComplicatedModel
|
from myapp.models import ComplicatedModel
|
||||||
|
|
||||||
class ComplicatedCreate(SuccessMessageMixin, CreateView):
|
class ComplicatedCreateView(SuccessMessageMixin, CreateView):
|
||||||
model = ComplicatedModel
|
model = ComplicatedModel
|
||||||
success_url = '/success/'
|
success_url = '/success/'
|
||||||
success_message = "%(calculated_field)s was created successfully"
|
success_message = "%(calculated_field)s was created successfully"
|
||||||
|
|
|
@ -110,17 +110,17 @@ Now we need to define a view::
|
||||||
from django.views.generic import ListView
|
from django.views.generic import ListView
|
||||||
from books.models import Publisher
|
from books.models import Publisher
|
||||||
|
|
||||||
class PublisherList(ListView):
|
class PublisherListView(ListView):
|
||||||
model = Publisher
|
model = Publisher
|
||||||
|
|
||||||
Finally hook that view into your urls::
|
Finally hook that view into your urls::
|
||||||
|
|
||||||
# urls.py
|
# urls.py
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
from books.views import PublisherList
|
from books.views import PublisherListView
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('publishers/', PublisherList.as_view()),
|
path('publishers/', PublisherListView.as_view()),
|
||||||
]
|
]
|
||||||
|
|
||||||
That's all the Python code we need to write. We still need to write a template,
|
That's all the Python code we need to write. We still need to write a template,
|
||||||
|
@ -183,7 +183,7 @@ specifies the context variable to use::
|
||||||
from django.views.generic import ListView
|
from django.views.generic import ListView
|
||||||
from books.models import Publisher
|
from books.models import Publisher
|
||||||
|
|
||||||
class PublisherList(ListView):
|
class PublisherListView(ListView):
|
||||||
model = Publisher
|
model = Publisher
|
||||||
context_object_name = 'my_favorite_publishers'
|
context_object_name = 'my_favorite_publishers'
|
||||||
|
|
||||||
|
@ -210,7 +210,7 @@ you can override it to send more::
|
||||||
from django.views.generic import DetailView
|
from django.views.generic import DetailView
|
||||||
from books.models import Book, Publisher
|
from books.models import Book, Publisher
|
||||||
|
|
||||||
class PublisherDetail(DetailView):
|
class PublisherDetailView(DetailView):
|
||||||
|
|
||||||
model = Publisher
|
model = Publisher
|
||||||
|
|
||||||
|
@ -254,7 +254,7 @@ specify the list of objects using the ``queryset`` argument::
|
||||||
from django.views.generic import DetailView
|
from django.views.generic import DetailView
|
||||||
from books.models import Publisher
|
from books.models import Publisher
|
||||||
|
|
||||||
class PublisherDetail(DetailView):
|
class PublisherDetailView(DetailView):
|
||||||
|
|
||||||
context_object_name = 'publisher'
|
context_object_name = 'publisher'
|
||||||
queryset = Publisher.objects.all()
|
queryset = Publisher.objects.all()
|
||||||
|
@ -273,7 +273,7 @@ with the most recent first::
|
||||||
from django.views.generic import ListView
|
from django.views.generic import ListView
|
||||||
from books.models import Book
|
from books.models import Book
|
||||||
|
|
||||||
class BookList(ListView):
|
class BookListView(ListView):
|
||||||
queryset = Book.objects.order_by('-publication_date')
|
queryset = Book.objects.order_by('-publication_date')
|
||||||
context_object_name = 'book_list'
|
context_object_name = 'book_list'
|
||||||
|
|
||||||
|
@ -284,7 +284,7 @@ list of books by a particular publisher, you can use the same technique::
|
||||||
from django.views.generic import ListView
|
from django.views.generic import ListView
|
||||||
from books.models import Book
|
from books.models import Book
|
||||||
|
|
||||||
class AcmeBookList(ListView):
|
class AcmeBookListView(ListView):
|
||||||
|
|
||||||
context_object_name = 'book_list'
|
context_object_name = 'book_list'
|
||||||
queryset = Book.objects.filter(publisher__name='ACME Publishing')
|
queryset = Book.objects.filter(publisher__name='ACME Publishing')
|
||||||
|
@ -330,20 +330,20 @@ Here, we have a URLconf with a single captured group::
|
||||||
|
|
||||||
# urls.py
|
# urls.py
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
from books.views import PublisherBookList
|
from books.views import PublisherBookListView
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('books/<publisher>/', PublisherBookList.as_view()),
|
path('books/<publisher>/', PublisherBookListView.as_view()),
|
||||||
]
|
]
|
||||||
|
|
||||||
Next, we'll write the ``PublisherBookList`` view itself::
|
Next, we'll write the ``PublisherBookListView`` view itself::
|
||||||
|
|
||||||
# views.py
|
# views.py
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from django.views.generic import ListView
|
from django.views.generic import ListView
|
||||||
from books.models import Book, Publisher
|
from books.models import Book, Publisher
|
||||||
|
|
||||||
class PublisherBookList(ListView):
|
class PublisherBookListView(ListView):
|
||||||
|
|
||||||
template_name = 'books/books_by_publisher.html'
|
template_name = 'books/books_by_publisher.html'
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ The view can be constructed using a ``FormView``:
|
||||||
from myapp.forms import ContactForm
|
from myapp.forms import ContactForm
|
||||||
from django.views.generic.edit import FormView
|
from django.views.generic.edit import FormView
|
||||||
|
|
||||||
class ContactView(FormView):
|
class ContactFormView(FormView):
|
||||||
template_name = 'contact.html'
|
template_name = 'contact.html'
|
||||||
form_class = ContactForm
|
form_class = ContactForm
|
||||||
success_url = '/thanks/'
|
success_url = '/thanks/'
|
||||||
|
@ -119,15 +119,15 @@ here; we don't have to write any logic ourselves:
|
||||||
from django.views.generic.edit import CreateView, DeleteView, UpdateView
|
from django.views.generic.edit import CreateView, DeleteView, UpdateView
|
||||||
from myapp.models import Author
|
from myapp.models import Author
|
||||||
|
|
||||||
class AuthorCreate(CreateView):
|
class AuthorCreateView(CreateView):
|
||||||
model = Author
|
model = Author
|
||||||
fields = ['name']
|
fields = ['name']
|
||||||
|
|
||||||
class AuthorUpdate(UpdateView):
|
class AuthorUpdateView(UpdateView):
|
||||||
model = Author
|
model = Author
|
||||||
fields = ['name']
|
fields = ['name']
|
||||||
|
|
||||||
class AuthorDelete(DeleteView):
|
class AuthorDeleteView(DeleteView):
|
||||||
model = Author
|
model = Author
|
||||||
success_url = reverse_lazy('author-list')
|
success_url = reverse_lazy('author-list')
|
||||||
|
|
||||||
|
@ -150,13 +150,13 @@ Finally, we hook these new views into the URLconf:
|
||||||
:caption: urls.py
|
:caption: urls.py
|
||||||
|
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
from myapp.views import AuthorCreate, AuthorDelete, AuthorUpdate
|
from myapp.views import AuthorCreateView, AuthorDeleteView, AuthorUpdateView
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
# ...
|
# ...
|
||||||
path('author/add/', AuthorCreate.as_view(), name='author-add'),
|
path('author/add/', AuthorCreateView.as_view(), name='author-add'),
|
||||||
path('author/<int:pk>/', AuthorUpdate.as_view(), name='author-update'),
|
path('author/<int:pk>/', AuthorUpdateView.as_view(), name='author-update'),
|
||||||
path('author/<int:pk>/delete/', AuthorDelete.as_view(), name='author-delete'),
|
path('author/<int:pk>/delete/', AuthorDeleteView.as_view(), name='author-delete'),
|
||||||
]
|
]
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
@ -210,7 +210,7 @@ to edit, and override
|
||||||
from django.views.generic.edit import CreateView
|
from django.views.generic.edit import CreateView
|
||||||
from myapp.models import Author
|
from myapp.models import Author
|
||||||
|
|
||||||
class AuthorCreate(LoginRequiredMixin, CreateView):
|
class AuthorCreateView(LoginRequiredMixin, CreateView):
|
||||||
model = Author
|
model = Author
|
||||||
fields = ['name']
|
fields = ['name']
|
||||||
|
|
||||||
|
@ -259,6 +259,6 @@ works with an API-based workflow as well as 'normal' form POSTs::
|
||||||
}
|
}
|
||||||
return JsonResponse(data)
|
return JsonResponse(data)
|
||||||
|
|
||||||
class AuthorCreate(JsonableResponseMixin, CreateView):
|
class AuthorCreateView(JsonableResponseMixin, CreateView):
|
||||||
model = Author
|
model = Author
|
||||||
fields = ['name']
|
fields = ['name']
|
||||||
|
|
|
@ -229,7 +229,7 @@ We'll demonstrate this with the ``Author`` model we used in the
|
||||||
from django.views.generic.detail import SingleObjectMixin
|
from django.views.generic.detail import SingleObjectMixin
|
||||||
from books.models import Author
|
from books.models import Author
|
||||||
|
|
||||||
class RecordInterest(SingleObjectMixin, View):
|
class RecordInterestView(SingleObjectMixin, View):
|
||||||
"""Records the current user's interest in an author."""
|
"""Records the current user's interest in an author."""
|
||||||
model = Author
|
model = Author
|
||||||
|
|
||||||
|
@ -256,11 +256,11 @@ We can hook this into our URLs easily enough:
|
||||||
:caption: urls.py
|
:caption: urls.py
|
||||||
|
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
from books.views import RecordInterest
|
from books.views import RecordInterestView
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
#...
|
#...
|
||||||
path('author/<int:pk>/interest/', RecordInterest.as_view(), name='author-interest'),
|
path('author/<int:pk>/interest/', RecordInterestView.as_view(), name='author-interest'),
|
||||||
]
|
]
|
||||||
|
|
||||||
Note the ``pk`` named group, which
|
Note the ``pk`` named group, which
|
||||||
|
@ -307,13 +307,13 @@ object. In order to do this, we need to have two different querysets:
|
||||||
will add in the suitable ``page_obj`` and ``paginator`` for us
|
will add in the suitable ``page_obj`` and ``paginator`` for us
|
||||||
providing we remember to call ``super()``.
|
providing we remember to call ``super()``.
|
||||||
|
|
||||||
Now we can write a new ``PublisherDetail``::
|
Now we can write a new ``PublisherDetailView``::
|
||||||
|
|
||||||
from django.views.generic import ListView
|
from django.views.generic import ListView
|
||||||
from django.views.generic.detail import SingleObjectMixin
|
from django.views.generic.detail import SingleObjectMixin
|
||||||
from books.models import Publisher
|
from books.models import Publisher
|
||||||
|
|
||||||
class PublisherDetail(SingleObjectMixin, ListView):
|
class PublisherDetailView(SingleObjectMixin, ListView):
|
||||||
paginate_by = 2
|
paginate_by = 2
|
||||||
template_name = "books/publisher_detail.html"
|
template_name = "books/publisher_detail.html"
|
||||||
|
|
||||||
|
@ -434,7 +434,7 @@ code so that on ``POST`` the form gets called appropriately.
|
||||||
both of the views implement ``get()``, and things would get much more
|
both of the views implement ``get()``, and things would get much more
|
||||||
confusing.
|
confusing.
|
||||||
|
|
||||||
Our new ``AuthorDetail`` looks like this::
|
Our new ``AuthorDetailView`` looks like this::
|
||||||
|
|
||||||
# CAUTION: you almost certainly do not want to do this.
|
# CAUTION: you almost certainly do not want to do this.
|
||||||
# It is provided as part of a discussion of problems you can
|
# It is provided as part of a discussion of problems you can
|
||||||
|
@ -451,7 +451,7 @@ Our new ``AuthorDetail`` looks like this::
|
||||||
class AuthorInterestForm(forms.Form):
|
class AuthorInterestForm(forms.Form):
|
||||||
message = forms.CharField()
|
message = forms.CharField()
|
||||||
|
|
||||||
class AuthorDetail(FormMixin, DetailView):
|
class AuthorDetailView(FormMixin, DetailView):
|
||||||
model = Author
|
model = Author
|
||||||
form_class = AuthorInterestForm
|
form_class = AuthorInterestForm
|
||||||
|
|
||||||
|
@ -504,8 +504,8 @@ clear division here: ``GET`` requests should get the
|
||||||
data), and ``POST`` requests should get the :class:`FormView`. Let's
|
data), and ``POST`` requests should get the :class:`FormView`. Let's
|
||||||
set up those views first.
|
set up those views first.
|
||||||
|
|
||||||
The ``AuthorDisplay`` view is almost the same as :ref:`when we
|
The ``AuthorDetailView`` view is almost the same as :ref:`when we
|
||||||
first introduced AuthorDetail<generic-views-extra-work>`; we have to
|
first introduced AuthorDetailView<generic-views-extra-work>`; we have to
|
||||||
write our own ``get_context_data()`` to make the
|
write our own ``get_context_data()`` to make the
|
||||||
``AuthorInterestForm`` available to the template. We'll skip the
|
``AuthorInterestForm`` available to the template. We'll skip the
|
||||||
``get_object()`` override from before for clarity::
|
``get_object()`` override from before for clarity::
|
||||||
|
@ -517,7 +517,7 @@ write our own ``get_context_data()`` to make the
|
||||||
class AuthorInterestForm(forms.Form):
|
class AuthorInterestForm(forms.Form):
|
||||||
message = forms.CharField()
|
message = forms.CharField()
|
||||||
|
|
||||||
class AuthorDisplay(DetailView):
|
class AuthorDetailView(DetailView):
|
||||||
model = Author
|
model = Author
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
|
@ -525,18 +525,18 @@ write our own ``get_context_data()`` to make the
|
||||||
context['form'] = AuthorInterestForm()
|
context['form'] = AuthorInterestForm()
|
||||||
return context
|
return context
|
||||||
|
|
||||||
Then the ``AuthorInterest`` is a :class:`FormView`, but we have to bring in
|
Then the ``AuthorInterestForm`` is a :class:`FormView`, but we have to bring in
|
||||||
:class:`~django.views.generic.detail.SingleObjectMixin` so we can find the
|
:class:`~django.views.generic.detail.SingleObjectMixin` so we can find the
|
||||||
author we're talking about, and we have to remember to set ``template_name`` to
|
author we're talking about, and we have to remember to set ``template_name`` to
|
||||||
ensure that form errors will render the same template as ``AuthorDisplay`` is
|
ensure that form errors will render the same template as ``AuthorDetailView``
|
||||||
using on ``GET``::
|
is using on ``GET``::
|
||||||
|
|
||||||
from django.http import HttpResponseForbidden
|
from django.http import HttpResponseForbidden
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.views.generic import FormView
|
from django.views.generic import FormView
|
||||||
from django.views.generic.detail import SingleObjectMixin
|
from django.views.generic.detail import SingleObjectMixin
|
||||||
|
|
||||||
class AuthorInterest(SingleObjectMixin, FormView):
|
class AuthorInterestFormView(SingleObjectMixin, FormView):
|
||||||
template_name = 'books/author_detail.html'
|
template_name = 'books/author_detail.html'
|
||||||
form_class = AuthorInterestForm
|
form_class = AuthorInterestForm
|
||||||
model = Author
|
model = Author
|
||||||
|
@ -550,26 +550,26 @@ using on ``GET``::
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
return reverse('author-detail', kwargs={'pk': self.object.pk})
|
return reverse('author-detail', kwargs={'pk': self.object.pk})
|
||||||
|
|
||||||
Finally we bring this together in a new ``AuthorDetail`` view. We
|
Finally we bring this together in a new ``AuthorView`` view. We
|
||||||
already know that calling :meth:`~django.views.generic.base.View.as_view()` on
|
already know that calling :meth:`~django.views.generic.base.View.as_view()` on
|
||||||
a class-based view gives us something that behaves exactly like a function
|
a class-based view gives us something that behaves exactly like a function
|
||||||
based view, so we can do that at the point we choose between the two subviews.
|
based view, so we can do that at the point we choose between the two subviews.
|
||||||
|
|
||||||
You can pass through keyword arguments to
|
You can pass through keyword arguments to
|
||||||
:meth:`~django.views.generic.base.View.as_view()` in the same way you
|
:meth:`~django.views.generic.base.View.as_view()` in the same way you
|
||||||
would in your URLconf, such as if you wanted the ``AuthorInterest`` behavior
|
would in your URLconf, such as if you wanted the ``AuthorInterestFormView``
|
||||||
to also appear at another URL but using a different template::
|
behavior to also appear at another URL but using a different template::
|
||||||
|
|
||||||
from django.views import View
|
from django.views import View
|
||||||
|
|
||||||
class AuthorDetail(View):
|
class AuthorView(View):
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
view = AuthorDisplay.as_view()
|
view = AuthorDetailView.as_view()
|
||||||
return view(request, *args, **kwargs)
|
return view(request, *args, **kwargs)
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
view = AuthorInterest.as_view()
|
view = AuthorInterestFormView.as_view()
|
||||||
return view(request, *args, **kwargs)
|
return view(request, *args, **kwargs)
|
||||||
|
|
||||||
This approach can also be used with any other generic class-based
|
This approach can also be used with any other generic class-based
|
||||||
|
|
|
@ -150,7 +150,7 @@ uploads:
|
||||||
from django.views.generic.edit import FormView
|
from django.views.generic.edit import FormView
|
||||||
from .forms import FileFieldForm
|
from .forms import FileFieldForm
|
||||||
|
|
||||||
class FileFieldView(FormView):
|
class FileFieldFormView(FormView):
|
||||||
form_class = FileFieldForm
|
form_class = FileFieldForm
|
||||||
template_name = 'upload.html' # Replace with your template.
|
template_name = 'upload.html' # Replace with your template.
|
||||||
success_url = '...' # Replace with your URL or reverse().
|
success_url = '...' # Replace with your URL or reverse().
|
||||||
|
|
|
@ -90,7 +90,7 @@ your view class, for example::
|
||||||
|
|
||||||
from myapp.models import Contact
|
from myapp.models import Contact
|
||||||
|
|
||||||
class ContactList(ListView):
|
class ContactListView(ListView):
|
||||||
paginate_by = 2
|
paginate_by = 2
|
||||||
model = Contact
|
model = Contact
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue