mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	[3.2.x] Fixed #32271 -- Improved consistency of docs CBV examples.
Co-Authored-By: Carles Pina i Estany <carles@pina.cat>
Backport of 5fd4f22d19 from master
			
			
This commit is contained in:
		
				
					committed by
					
						 Mariusz Felisiak
						Mariusz Felisiak
					
				
			
			
				
	
			
			
			
						parent
						
							7e6e822162
						
					
				
				
					commit
					9f277c3a7c
				
			| @@ -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 | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user