จะรับ Request.User ใน Django-Rest-Framework serializer ได้อย่างไร?


124

เคยลองทำแบบนี้แล้วไม่ได้ผล

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']

ฉันต้องการวิธีในการเข้าถึง request.user จากคลาส Serializer ของฉัน


DRF CurrentUserDefaultอย่างแน่นอน❤️django- rest
framework.org/api

คำตอบ:


232

คุณไม่สามารถเข้าถึงไฟล์request.user. คุณต้องเข้าถึงออบเจ็กต์คำขอจากนั้นดึงแอตทริบิวต์ของผู้ใช้

แบบนี้:

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

หรือเพื่อความปลอดภัยมากขึ้น

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

สามารถอ่านเพิ่มเติมเกี่ยวกับบริบทเพิ่มเติมได้ที่นี่


1
มันบอกว่าNameError: name 'self' is not defined
Coderaemon

แน่นอนว่านี่เป็นบริบทของชั้นเรียน คุณมักจะไม่ได้อยู่ในบริบทของชั้นเรียน
karthikr

3
ใน serializer ของฉันในvalidate()วิธีการ self.context เป็น dict ว่างเปล่า ทำไม?
David D.

14
เดวิด - คุณคงแก้ปัญหานี้มานานแล้ว แต่หากใครก็ตามที่มีปัญหานี้อาจเป็นเพราะคุณกำลังสร้างซีเรียลไลเซอร์ด้วยตนเอง ฉันมีปัญหานี้ในซีเรียลไลเซอร์แบบซ้อนที่สร้างอินสแตนซ์สำหรับความสัมพันธ์ทั่วไป เอกสารบอกว่าให้ทำ serializer = NoteSerializer (value) แต่จะส่งผ่านอินสแตนซ์ของคุณเท่านั้นไม่ใช่บริบทที่มีคำขอ คุณสามารถส่ง kwargs ไปยังตัวสร้างและส่งข้อมูลที่ต้องการ (ดู get_serializer หรือ GenericAPIV ดูวิธีการทำงาน)
Jon Vaughan

2
@JonVaughan รายละเอียดวิธีการส่ง kwargs ไปยังอินสแตนซ์ serializer ??
tyan

74

จริงๆแล้วคุณไม่ต้องกังวลกับบริบท มีวิธีที่ดีกว่านี้มาก:

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
มันใช้งานไม่ได้มันส่งคืนวัตถุ Null user_edit = serializers.CurrentUserDefault ()
Enderson Menezes

@EndersonMenezes มันอาจจะทำงานได้ดีที่สุดเมื่อIsAuthenticatedได้รับอนุญาต
Micheal J. Roberts

40

ดังที่อิกอร์กล่าวไว้ในคำตอบอื่น ๆ การใช้งานสามารถใช้ CurrentUserDefault หากคุณไม่ต้องการแทนที่วิธีการบันทึกเพียงแค่นี้ให้ใช้doc :

from rest_framework import serializers

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

ขณะนี้ลิงก์ doc ลิงก์ผิด
coler-j

ลิงก์ไปยังเอกสาร DRF อย่างเป็นทางการพร้อมตัวอย่างเดียวกันนี้django-rest-framework.org/api-guide/serializers/…
Paolo Melchiorre

2

คุณสามารถส่งผ่านrequest.userเมื่อโทร.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)

นี่คือรุ่น:

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

คุณต้องมีการแก้ไขเล็กน้อยใน Serializer ของคุณ:

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']

นี่คือตัวอย่างการใช้ชุดมุมมองการผสมโมเดล ในcreateวิธีนี้คุณสามารถค้นหาวิธีที่เหมาะสมในการโทรหา serializer เมธอดget_serializerเติมพจนานุกรมบริบทให้ถูกต้อง หากคุณต้องการใช้ซีเรียลไลเซอร์อื่นที่กำหนดไว้บนวิวเซ็ตโปรดดูupdateวิธีการเริ่มต้นซีเรียลไลเซอร์ด้วยพจนานุกรมบริบทซึ่งจะส่งอ็อบเจ็กต์คำขอไปยังซีเรียลไลเซอร์ด้วย

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)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.