how do i wrtite django fbv to class based view - python-3.x

I have two user types a and b i need to write the below fbv into class based Logoutview(auth.view) how do i write the below fbv to cbv
views.py
#login_required
def logout(request):
if request.user.usertype_a:
logout(request)
return redirect(reverse('user_a_login'))
else:
logout(request)
return redirect(reverse('user_b_login'))

Give this a try
from django.views import View
class LogOutView(View):
def get(self, request, *args, **kwargs):
logout(request)
if request.user.usertype_a:
return redirect(reverse('user_a_login'))
return redirect(reverse('user_b_login'))
Or you can Use LogoutView and override its dispatch method for custom redirections

Try to add this to your urls.py:
from django.contrib.auth import views as auth_views
path('logout/', auth_views.LogoutView.as_view(), name='logout'),

Related

How do I use permission_classes in a custom method of a Viewset in DjangoRestFramework?

Suppose that I have a Viewset named UserViewset, and I have assigned IsAuthenticated permission to UserViewset Viewset. Now, I want to create a normal method (not an action method), and I want to assign another permission to that method which is IsAdminUser, how would I do that?
Below is the code with the method which I tried:
from rest_framework.viewsets import GenericViewSet
from rest_framework.permissions import IsAuthenticated, IsAdminUser
class UserViewset(GenericViewSet):
permission_classes = (IsAuthenticated,) # THIS IS THE DEFAULT PERMISSION I HAVE SET FOR THIS VIEWSET WHICH WILL APPLY TO ALL METHODS OR ACTION METHODS
def create(self, *args, **kwargs): # THIS IS MY CUSTOM METHOD
permission_classes = (IsAuthenticated, IsAdminUser) # I WANT SOMETHONG LIKE THIS, BUT IT DOES NOT WORK
.
.
.
You can override get_permission class
def get_permissions(self):
# check the action and return the permission class accordingly
if self.action == 'create':
return [IsAdminUser(),]
return [IsAuthenticated(), ]

Django rest-framework , Serializer returning assertion Error

I'm extending my current model to have some common properties from other base classes.
Before extending the model, everything was working fine. But after extending, I'm getting the assertion error while performing put and post Operation. I tried my best to resolve it by my own. But not getting where it is going wrong. Can anyone help me on this?
Please find my model and serializers below.
basemodel.py
from django.db import models
class BaseModel(models.Model):
created_at=models.DateTimeField(auto_now=True)
updated_at=models.DateTimeField(auto_now=True)
class Meta:
abstract = True
softdelete.py
from django.db import models
class SoftDeleteModel(models.Model):
is_deleted = models.BooleanField(default=False)
def delete(self):
self.is_deleted = True
self.save()
def restore(self):
self.is_deleted = False
self.save()
class Meta:
abstract = True
movies.py
from django.db import models
from cinimateApp.models.comman.softdelete import SoftDeleteModel
from cinimateApp.models.comman.basemodel import BaseModel
# Create your models here.
class Movies(SoftDeleteModel,BaseModel):
name=models.CharField(max_length=250)
description=models.CharField(max_length=250)
active=models.BooleanField(default=False)
def __str__(self):
return self.name
movieSerializer.py
#Model Serializer
from rest_framework import serializers
from cinimateApp.models.movies import Movies
class MovieSerializer(serializers.ModelSerializer):
class Meta:
model = Movies
fields = '__all__'
# fields=['id', 'name', 'description', 'active']
# exclude=['name']
# field Level Validation
def validate_name(self,value):
if(len(value)<3):
raise serializers.ValidationError('name is too short')
return value
#Objectlevel validation
def validate(self,data):
if(data['name']==data['description']):
raise serializers.ValidationError('name and description should be different')
return
#custome serializer field
name_length=serializers.SerializerMethodField()
def get_name_length(self,object):
return len(object.name)
views.py
from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework import status
from rest_framework.response import Response
from cinimateApp.serializers.movieSerializer import MovieSerializer
from cinimateApp.models.movies import Movies
# Create your views here.
class MovieList(APIView):
def get(self,request):
movies=Movies.objects.all()
serializer=MovieSerializer(movies,many=True)
return Response(serializer.data,status=status.HTTP_200_OK)
def post(self,request):
serialiser=MovieSerializer(data=request.data)
if(serialiser.is_valid()):
serialiser.save()
return Response(serialiser.data,status=status.HTTP_201_CREATED)
else:
return Response(serialiser.errors,status=status.HTTP_500_INTERNAL_SERVER_ERROR)
class MovieDetailsAV(APIView):
def get(self,request,id):
try:
movie=Movies.objects.get(pk=id)
serializer=MovieSerializer(movie)
return Response(serializer.data,status=status.HTTP_200_OK)
except Movies.DoesNotExist:
return Response({'Error':'Movie not found'},status=status.HTTP_404_NOT_FOUND)
def put(self,request,id):
try:
movie=Movies.objects.get(pk=id)
serializer=MovieSerializer(movie,data=request.data)
if(serializer.is_valid()):
serializer.save()
return Response(serializer.data,status=status.HTTP_200_OK)
return Response(serializer.errors,status=status.HTTP_500_INTERNAL_SERVER_ERROR)
except Movies.DoesNotExist:
return Response({'Error':'Movie not found'},status=status.HTTP_404_NOT_FOUND)
def delete(self,request,id):
try:
movie=Movies.objects.get(pk=id)
movie.delete()
return Response({'message' : 'Content deleted successfully'},status=status.HTTP_204_NO_CONTENT)
except Movies.DoesNotExist:
return Response({'Error':'Movie not found'},status=status.HTTP_404_NOT_FOUND)
def patch(self,request,id):
try:
movie=Movies.objects.get(pk=id)
serializer=MovieSerializer(movie,data=request.data,partial=True)
if(serializer.is_valid()):
serializer.save()
return Response(serializer.data,status=status.HTTP_200_OK)
return Response(serializer.errors,status=status.HTTP_500_INTERNAL_SERVER_ERROR)
except Movies.DoesNotExist:
return Response({'Error':'Movie not found'},status=status.HTTP_404_NOT_FOUND)
I'm getting following errors for put and post requests.
assert value is not None, '.validate() should return the validated data'
AssertionError: .validate() should return the validated data
validate() function should return data so:
def validate(self,data):
if(data['name']==data['description']):
raise serializers.ValidationError('name and description should be different')
return data

DRF's not calling post() method when receiving POST request

I have a viewset like this:
class MyViewSet(CreateAPIView, RetrieveModelMixin, ListModelMixin, GenericViewSet):
queryset = MyModel.objects.all()
serializer_class = MySerializer
def post(self, request, *args, **kwargs):
import pdb; pdb.set_trace()
class MySerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = MyModel
fields = ['id', 'field1', 'field2'] #only field1 is required in the model
The GET requests for list, and retrieve works perfectly. When I make a POST request, sending the field1 I get a status 201 and a new record is added to the database, so it works too.
But my method MyViewSet.post() that should overwrite the same one from generics.CreateAPIView never gets called.
Not only that, but I've tried to add the pdb.set_trace(), literally inside the generics.CreateAPIView.post() and in the CreateModelMixin.create() functions and neither stopped once I made the POST request.
So something else is handling this POST request and inserting into the DB, I just don't know what. And how can I overwrite it, so I can customize what should be done with a post request?
PS.: Also, I don't think it's a routing problem, my urls.py:
from rest_framework import routers
from myapp.views import MyViewSet, AnotherViewSet
router = routers.DefaultRouter()
router.register(r'route_one', MyViewSet)
router.register(r'route_two', AnotherViewSet)
I think you need to use the exact class in order to use POST api.
class MyView(CreateModelMixin, ListModelMixin, generics.GenericAPIView):
queryset = MyModel.objects.all()
serializer_class = MySerializer
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
In urls.py
from django.urls import path
from .views import MyView
urlpatterns = [
path('route_one', MyView.as_view(), name="my_view_detail")
]

how to add a method to a class template view

happy new year everyone...I am new to django and i am working on a project a resume page i need help with the contact me section, i want to do something i seen in a video https://www.youtube.com/watch?v=w4ilq6Zk-08. The book i used to learn only uses class to view templates. below is my code
from django.views.generic import TemplateView
from django.shortcuts import render
# Create your views here.
class ProfilePageView(TemplateView):
template_name = 'femi_profile.html'
def contact(request):
if request.method == "POST":
name = request.POST['name']
email = request.POST['email']
subject = request.POST['subject']
message = request.POST['message']
return render(request, 'femi_profile.html', {'contact_name': name})
else:
return render(request, 'femi_profile.html', {})
After reading the django documentation https://docs.djangoproject.com/en/3.1/topics/class-based-views/intro/ once more and trying different lines of code i finally got that run and i am not asking why is it runing? i figured out how to go about this.
find the correct code below
from django.views.generic import TemplateView
from django.shortcuts import render
# Create your views here.
class ProfilePageView(TemplateView):
template_name = 'femi_profile.html'
def get(self, request, *args, **kwargs):
return render(request, self.template_name, {})
def post(self, request, *args, **kwargs):
if request.method == "POST":
name = request.POST['name']
email = request.POST['email']
subject = request.POST['subject']
message = request.POST['message']
return render(request, self.template_name, {'contact_name': name})

Django: How to fetch id in class based views?

views.py
from paitent.mixini import HttpResponseMixin,SerializeMixin
from paitent.models import Paitent_Details
class PaitentCRUDCBV(View, HttpResponseMixin, SerializeMixin):
def get(self, id, *args, **kwargs):
paitent = Paitent_Details.objects.get(id=id)
json_data = self.render_to_serialize([paitent,])
return self.render_to_http_response(json_data)
urls.py
urlpatterns = [
url(r'^api/json',views.PaitentCRUDCBV.as_view()),
]
My requirement is based on id i have to fetch particular row form data base,from Frontend side i am passing id in url like:(url: "http://127.0.0.1:8000/api/json/?id=2").But i am not finding id inside my class ,don't know where i am doing wrong. please help me.
You can use query_params in view:
def get(self, request):
id = self.request.query_params.get('id')
....
You can get more information from documentation
1)I have edited your following code, you have to pass *request* in your function,
2)Inside the function calling request.query_params.get, you will get parameters value from the url
from paitent.mixini import HttpResponseMixin,SerializeMixin
from paitent.models import Paitent_Details
class PaitentCRUDCBV(View, HttpResponseMixin, SerializeMixin):
def get(self, request, *args, **kwargs):
id=self.request.query_params.get('id')
paitent = Paitent_Details.objects.get(id=id)
json_data = self.render_to_serialize([paitent,])
return self.render_to_http_response(json_data)

Resources