Django-Rest-Framework serileştiricisinde Request.User nasıl edinilir?


124

Böyle bir şey denedim, işe yaramıyor.

class PostSerializer(serializers.ModelSerializer):

    class Meta:
        model = Post

    def save(self):
        user = self.context['request.user']
        title = self.validated_data['title']
        article = self.validated_data['article']

Serializer sınıfımdan request.user'a erişebilmenin bir yoluna ihtiyacım var.


DRF CurrentUserDefaultkesinlikle ❤️ django-rest-framework.org/api-guide/validators/…
andilabs

Yanıtlar:


231

request.userDoğrudan erişemezsiniz . İstek nesnesine erişmeniz ve ardından kullanıcı özelliğini getirmeniz gerekir.

Bunun gibi:

user =  self.context['request'].user

Veya daha güvenli olmak için

user = None
request = self.context.get("request")
if request and hasattr(request, "user"):
    user = request.user

Ekstra bağlam hakkında daha fazla bilgiyi buradan okuyabilirsiniz


1
diyorNameError: name 'self' is not defined
Coderaemon

elbette bu bir sınıf bağlamındaydı. Muhtemelen bir sınıf bağlamında değilsiniz
karthikr

3
Serileştiricimde, validate()yöntemde self.context boş bir diktedir. Neden?
David D.

14
David - muhtemelen bunu uzun zaman önce çözdünüz, ancak başka biri bu sorunu yaşıyorsa, bunun nedeni serileştiricinizi manuel olarak oluşturmanız olabilir. Genel bir ilişki için örneklenen iç içe geçmiş bir serileştiricide bu sorunu yaşadım. Dokümanlar seri hale getirici = NoteSerializer (değer) yapmamızı söylüyor, ancak bu, isteği içeren bağlamı değil, yalnızca örneğinizi iletecektir. Kwargs'ı kurucuya iletebilir ve ona ihtiyaç duyduğu bilgileri gönderebilirsiniz (nasıl yaptığını öğrenmek için get_serializer veya GenericAPIView'a bakın)
Jon Vaughan

2
@JonVaughan herhangi bir ayrıntı kwargs serileştirici örneğine nasıl geçirilir?
tyan

74

Aslında bağlamla uğraşmanıza gerek yok. Bunu yapmanın çok daha iyi bir yolu var:

from rest_framework.fields import CurrentUserDefault

class PostSerializer(serializers.ModelSerializer):

    class Meta:
        model = Post

   def save(self):
        user = CurrentUserDefault()  # <= magic!
        title = self.validated_data['title']
        article = self.validated_data['article']

1
Çalışmadı, bir Null nesnesi döndürüyor. user_edit = serializers.CurrentUserDefault ()
Enderson Menezes

39

Igor'un diğer yanıtta da bahsettiği gibi, kullanım CurrentUserDefault'u kullanabilir. Sadece bunun için kaydetme yöntemi geçersiz kılmak istemiyorsanız, o zaman kullanmak doc :

from rest_framework import serializers

class PostSerializer(serializers.ModelSerializer):
    user = serializers.PrimaryKeyRelatedField(read_only=True, default=serializers.CurrentUserDefault())
    class Meta:
        model = Post

doc bağlantısı artık yanlış bağlanmıştır.
coler-j

Aynı örnekle resmi DRF belgelerine bağlantı django-rest-framework.org/api-guide/serializers/…
Paolo Melchiorre

2

Bir görünümün içinde request.userarama yaparken geçebilirsiniz .save(...):

class EventSerializer(serializers.ModelSerializer):

    class Meta:
        model = models.Event
        exclude = ['user']


class EventView(APIView):

    def post(self, request):
        es = EventSerializer(data=request.data)
        if es.is_valid():
            es.save(user=self.request.user)
            return Response(status=status.HTTP_201_CREATED)
        return Response(data=es.errors, status=status.HTTP_400_BAD_REQUEST)

Bu model:

class Event(models.Model):
    user = models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    date = models.DateTimeField(default=timezone.now)
    place = models.CharField(max_length=255)

0

Serileştiricinizde küçük bir düzenlemeye ihtiyacınız var:

class PostSerializer(serializers.ModelSerializer):

    class Meta:
        model = Post

    def save(self):
        user = self.context['request'].user
        title = self.validated_data['title']
        article = self.validated_data['article']

İşte Model karıştırma görünüm kümelerinin kullanıldığı bir örnek. Gelen createyöntemle Eğer seri hale çağırarak doğru yolunu bulabilirsiniz. get_serializer yöntemi bağlam sözlüğünü düzgün bir şekilde doldurur. Farklı bir serileştirici kullanmanız gerekiyorsa, daha sonra görünüm kümesinde tanımlanmışsa update, aynı zamanda istek nesnesini serileştiriciye aktaran bağlam sözlüğü ile serileştiricinin nasıl başlatılacağına ilişkin yönteme bakın .

class SignupViewSet(mixins.UpdateModelMixin, mixins.CreateModelMixin, viewsets.GenericViewSet):

    http_method_names = ["put", "post"]
    serializer_class = PostSerializer

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        kwargs['context'] = self.get_serializer_context()
        serializer = PostSerializer(instance, data=request.data, partial=partial, **kwargs)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)    
        return Response(serializer.data)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.