Làm cách nào để nhận được Request.User trong bộ tuần tự Django-Rest-Framework?


124

Tôi đã thử một cái gì đó như thế này, nó không hoạt động.

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

Tôi cần một cách để có thể truy cập request.user từ lớp Serializer của mình.


DRF CurrentUserDefaultlà hoàn toàn ❤️ django-rest-framework.org/api-guide/validators/…
andilabs

Câu trả lời:


230

Bạn không thể truy cập request.user trực tiếp. Bạn cần truy cập đối tượng yêu cầu, sau đó tìm nạp thuộc tính người dùng.

Như thế này:

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

Hoặc để an toàn hơn,

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

thể đọc thêm về ngữ cảnh bổ sung ở đây


1
nó nóiNameError: name 'self' is not defined
Coderaemon

tất nhiên, điều này là trong bối cảnh của một lớp học. Bạn có nhiều khả năng không trong bối cảnh của một lớp
karthikr

3
Trong bộ tuần tự của tôi, trong validate()phương thức, self.context là một chính tả trống. Tại sao?
David D.

14
David - có thể bạn đã giải quyết vấn đề này từ lâu, nhưng nếu bất kỳ ai khác gặp sự cố này, có thể là do bạn đang xây dựng bộ tuần tự của mình theo cách thủ công. Tôi đã gặp sự cố này trong một bộ tuần tự lồng nhau được khởi tạo cho một mối quan hệ chung. Các tài liệu nói làm serializer = NoteSerializer (value) nhưng điều này sẽ chỉ chuyển phiên bản của bạn, không phải ngữ cảnh chứa yêu cầu. Bạn có thể vượt qua kwargs để các nhà xây dựng và gửi các thông tin cần thiết (xem get_serializer hoặc GenericAPIView cho nó như thế nào hiện nó)
Jon Vaughan

2
@JonVaughan bất kỳ thông tin chi tiết nào về cách chuyển kwargs vào phiên bản serializer ??
tyan

74

Trên thực tế, bạn không cần phải bận tâm đến ngữ cảnh. Có một cách tốt hơn nhiều để làm điều đó:

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
Nó không hoạt động, nó trả về một đối tượng Null. user_edit = serializers.CurrentUserDefault ()
Enderson Menezes

39

Như Igor đã đề cập trong câu trả lời khác, việc sử dụng có thể sử dụng CurrentUserDefault. Nếu bạn không muốn ghi đè phương thức lưu chỉ cho điều này, hãy sử dụng doc :

from rest_framework import serializers

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

liên kết doc hiện đã bị liên kết sai.
coler-j

Liên kết đến tài liệu DRF chính thức có cùng ví dụ này django-rest-framework.org/api-guide/serializers/…
Paolo Melchiorre

2

Bạn có thể vượt qua request.userkhi gọi .save(...)bên trong một khung nhìn:

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)

Đây là mô hình:

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

Bạn cần một chỉnh sửa nhỏ trong bộ tuần tự của mình:

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

Dưới đây là một ví dụ, sử dụng các tập xem trộn Mô hình. Trong createphương pháp này, bạn có thể tìm thấy cách thích hợp để gọi bộ nối tiếp. get_serializerPhương thức điền đúng từ điển ngữ cảnh. Nếu bạn cần sử dụng một bộ tuần tự khác được xác định trên bộ khung nhìn, hãy xem updatephương pháp về cách khởi tạo bộ tuần tự bằng từ điển ngữ cảnh, phương pháp này cũng chuyển đối tượng yêu cầu đến bộ tuần tự.

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)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.