'django convert function view to class view
I have a problem converting from a function-based view to a class-based view, function
VIEWS.PY
@ login_required
def favourite_add(request, id):
post = get_object_or_404(Perfumes, id=id)
if post.favourites.filter(id=request.user.id).exists():
post.favourites.remove(request.user)
else:
post.favourites.add(request.user)
return HttpResponseRedirect(request.META['HTTP_REFERER'])
URLS.PY
urlpatterns = [
path('fav/<int:id>/', views.favourite_add, name='favourite_add'),
]
TEMPLATE.HTML
<div>
<a href="{% url 'favourite_add' perfume.id %}" class="btn btn-outline-primary">Add</a>
</div>
In general, the goal is to get the id of a certain perfume on the page, and using the get_object_or_404 function, I'm pulling its object from the Perfumes database - the post variable. Next, I want to retrieve the id of the logged-in user and check if the id of the above user is in the favourites section of the post variable. If not then add, otherwise remove the user id to the favourites section of the post variable.
Solution 1:[1]
You should not do this through a GET request, as the safe methods section of the HTTP specifications [w3.org] says:
In particular, the convention has been established that the GET and HEAD methods SHOULD NOT have the significance of taking an action other than retrieval. These methods ought to be considered "safe".
GET and HEAD are thus supposed to have no side effects. You can for example work with a POST request:
from django.views import View
from django.contrib.auth.mixins import LoginRequiredMixin
class FavouriteView(LoginRequiredMixin, View):
def post(self, request, id):
perfume = get_object_or_404(Perfumes, id=id)
if request.user in perfume.favourites.all():
perfume.favourites.remove(request.user)
else:
perfume.favourites.add(request.user)
return HttpResponseRedirect(request.META['HTTP_REFERER'])
You then make a mini-form to make a POST request:
<form method="post" action="{% url 'favourite_add' perfume.id %}">
{% csrf_token %}
<button class="btn btn-outline-primary">Add</button>
</form>
Note: normally a Django model is given a singular name, so
Perfumeinstead of.Perfumes
Solution 2:[2]
A function based one probably works fine for what you require.
Anyway, here is a view that should perform the same job as yours:
urls.py:
urlpatterns = [
path('fav/<int:id>/', views.FavouriteView.as_view(), name='favourite_add'),
]
views.py:
from django.views import View
from django.contrib.auth.mixins import LoginRequiredMixin
class FavouriteView(LoginRequiredMixin, View):
def get(self, *args, **kwargs):
post = get_object_or_404(Perfumes, id=self.kwargs.get('id'))
if post.favourites.filter(id=self.request.user.id).exists():
post.favourites.remove(self.request.user)
else:
post.favourites.add(self.request.user)
return HttpResponseRedirect(self.request.META['HTTP_REFERER'])
I recommend looking at something like https://ccbv.co.uk/ to help you understand class based views
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | iri |
