Remove authentication and permission classes only on one action - django-rest-framework

I have a generic view set custom action and i want to remove only from this action the authentication and permission classes. I tried the following but it does not work.
class ExampleView(GenericViewSet,
mixins.ListModelMixin,
mixins.DestroyModelMixin,
mixins.CreateModelMixin,
):
authentication_classes = [SessionAuthentication, BasicAuthentication]
permission_classes = [IsAuthenticated]
def custom_action(self, request, format=None):
self.authentication_classes = []
self.permission_classes = []

When you mark the custom action for routing with the action decorator, you should be able to specify the permission classes and authentication classes.
For example:
class ExampleView(GenericViewSet,
mixins.ListModelMixin,
mixins.DestroyModelMixin,
mixins.CreateModelMixin,
):
authentication_classes = [SessionAuthentication, BasicAuthentication]
permission_classes = [IsAuthenticated]
#action(detail=False, permission_classes=[AllowAny], authentication_classes=[])
def custom_action(self, request, format=None):
...

Related

DRF - how to return SerializerMethodField() value in json response

How to return SerializerMethodField() field value as a json reponse in APIView?
am not sure if i understand the question correctly but
you don't return SerializerMethodField() value as json reponse in APIView directly,
SerializerMethodField() is to be used inside the serializer as it shows in the docs here
from django.contrib.auth.models import User
from django.utils.timezone import now
from rest_framework import serializers
class UserSerializer(serializers.ModelSerializer):
days_since_joined = serializers.SerializerMethodField()
class Meta:
model = User
fields = '__all__'
def get_days_since_joined(self, obj):
return (now() - obj.date_joined).days
after
you can use the serializer in the view as show here
from snippets.models import Snippet
from users.serializers import UserSerializer
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
class UsersList(APIView):
def get(self, request, format=None):
users = User.objects.all()
serializer = UserSerializer(users, many=True)
return Response(serializer.data)
def post(self, request, format=None):
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Django Rest Framework nested serialization validators

Is there a way to bypass Django Rest Framework validators in nested serialization without overwriting the validators on the original serializers?
Example :
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username')
class TaskSerializer(serializers.ModelSerializer):
owner = UserSerializer()
class Meta:
model = models.Task
If I try to update or create a Task I'll get a unicity error, because DRF use the unique constraint on the username field of the User model.
The solution I have found is to overwrite the validators on the UserSerializer:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username')
extra_kwargs = {
'username': {
'validators': []
}
Is there a way to bypass this validation without overwriting the validators directly in the UserSerializer?
By overwriting this validator I have to rewrite every constraints that I defined on my model.
A solution like below would have been nice, since it would have allow to bypass the validators only in the TaskSerializer without overwriting the initial UserSerializer.
class TaskSerializer(serializers.ModelSerializer):
owner = UserSerializer(validators=[])
class Meta:
model = models.Task

django-rest-auth: how to get user info after successful authentication?

The django-rest-auth returns a token after successful authentication using rest_auth.serializers.TokenSerializer. How can I override this serializer or add my own so that I can get the user info like username, instead of token key after successful authentication?
I solved the problem by defining a custom serializer.
from django.contrib.auth.models import User
from rest_framework import serializers
from rest_auth.models import TokenModel
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username', 'email')
class TokenSerializer(serializers.ModelSerializer):
user = UserSerializer()
class Meta:
model = TokenModel
fields = ('key', 'user')
You can also use the depth option to easily generate nested representations, but in that case, you will receive the password field as well, which is not expected and intended.

DRF 3.0: Sharing a single UniqueTogetherValidator among related Serializers with Django Rest Framework

I’m dealing with a set of Model classes which share some common attributes via inheritance:
class MyBaseModel(models.Model):
class Meta:
abstract = True
unique_together = (('system', 'code',),)
id = models.UUIDField(default=uuid.uuid4, primary_key=True, unique=True, ...
system = models.ForeignKey(System, ...
code = models.CharField(...
...
class ModelA(MyBaseModel):
...
class ModelB(MyBaseModel):
...
Please note the presence of a unique_together constraint in Meta class.
A similar hierarchy would be convenient for the corresponding serializers;
I'm not sure whether I need to explicitly specify a UniqueTogetherValidator,
and currently investigating on this.
But in case, I wonder how to express it in the base serializer class, as it
requires a queryset which is not known in advance:
from rest_framework import serializers
from rest_framework.validators import UniqueTogetherValidator
class MyBaseModelSerializer(serializers.ModelSerializer):
class Meta:
exclude = ['date_created', 'created_by', ...
validators = [
UniqueTogetherValidator(
queryset=???.objects.all(),
fields=('system', 'code')
)
]
class ModelASerializer(MyBaseModelSerializer):
class Meta(MyBaseModelSerializer.Meta):
model = ModelA
...
class ModelBSerializer(MyBaseModelSerializer):
class Meta(MyBaseModelSerializer.Meta):
model = ModelB
...
How can I avoid repeating it for every single derived class, as in the following
example ?
from rest_framework import serializers
from rest_framework.validators import UniqueTogetherValidator
class MyBaseModelSerializer(serializers.ModelSerializer):
class Meta:
exclude = ['date_created', 'created_by', ...
class ModelASerializer(MyBaseModelSerializer):
class Meta(MyBaseModelSerializer.Meta):
model = ModelA
validators = [
UniqueTogetherValidator(
queryset=ModelA.objects.all(),
fields=('system', 'code')
)
]
...
class ModelBSerializer(MyBaseModelSerializer):
class Meta(MyBaseModelSerializer.Meta):
model = ModelB
validators = [
UniqueTogetherValidator(
queryset=ModelB.objects.all(),
fields=('system', 'code')
)
]
...
Model Serializer adds the UniqueTogetherValidator from model's unique_together constraints. You don't have give seperately.
need override
unique_together = (('system', 'code',),)
in non abstract model

how to apply permission class to particular method in class based views in Django-Rest Framework?

I want to apply permission only for "PUT" method not for "POST"
class Signup(APIView):
def post(self, request, format=None):
something...something
#authentication_classes((ExpiringTokenAuthentication,))
#permission_classes((IsAuthenticated,))
def put(self, request, format=None):
something...something
Check the HTTP method on your permission class has_permission method and apply your checks if it was PUT:
class ExpiringTokenAuthentication(permissions.BasePermission):
def has_permission(self, request, view):
if request.method == 'PUT':
# do it here
class Signup(APIView):
permission_classes = (BlacklistPermission,)

Resources