【问题标题】:How to make a field the same as int:pk in django rest framework?如何在 django rest 框架中使字段与 int:pk 相同?
【发布时间】:2022-02-03 02:03:51
【问题描述】:

我有一个序列化器

class AnswerQuestionsSerializer(serializers.ModelSerializer):
    user = serializers.PrimaryKeyRelatedField(read_only=True, default=serializers.CurrentUserDefault())

    class Meta:
        model = Answer
        fields = ('answer', 'user', 'question', 'number_of_points', 'moderate_status',)

还有风景

class AnswerQuestions(generics.CreateAPIView, generics.GenericAPIView):
    queryset = Answer.objects.all()
    serializer_class = AnswerQuestionsSerializer

    def perform_create(self, serializer):
        return serializer.save(user=self.request.user)

    def get_queryset(self):
        return super().get_queryset().filter(
            question_id=self.kwargs['pk']
        )

模型是这样的

    answer = models.TextField()
    created_at = models.DateTimeField(editable=False, default=timezone.now)
    updated_at = models.DateTimeField(default=timezone.now)
    user = models.ForeignKey('users.CustomUser', on_delete=models.PROTECT)
    question = models.ForeignKey('Question', on_delete=models.PROTECT)
    number_of_points = models.IntegerField(default=0)
    moderate_status = models.BooleanField(default=False)

网址

path('answerQuestions/<int:pk>', AnswerQuestions.as_view()),

我将 url 设置为 answerQuestions/int:pk,所以当我使用 post 请求时,可以说 answerQuestions/3 我仍然需要将 "question": "3" 放在正文中,因为它不会自动读取它。你知道如何让它自动点击 url 中提供的 id 的问题吗?在这种情况下是 3。

Internal Server Error: /api/v1/answerQuestions/3
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/django/core/handlers/base.py", line 179, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/django/views/generic/base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/rest_framework/views.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/rest_framework/views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
    raise exc
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/rest_framework/views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/rest_framework/generics.py", line 190, in post
    return self.create(request, *args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/rest_framework/mixins.py", line 19, in create
    self.perform_create(serializer)
  File "/Users/jakubstrawa/programming/gitlabdeor/api/questions/views.py", line 16, in perform_create
    return serializer.create(**self.perform_create_kwargs())
TypeError: create() got an unexpected keyword argument 'user'

【问题讨论】:

  • 分享urls.py
  • path('answerQuestions/', AnswerQuestions.as_view()),

标签: django django-rest-framework


【解决方案1】:

您可以将问题标记为read_only=True 字段:

class AnswerQuestionsSerializer(serializers.ModelSerializer):
    user = serializers.PrimaryKeyRelatedField(read_only=True, default=serializers.CurrentUserDefault())
    question = serializers.PrimaryKeyRelatedField(read_only=True)

    class Meta:
        model = Answer
        fields = ('answer', 'user', 'question', 'number_of_points', 'moderate_status',)

并在视图中将其注入序列化程序的create 方法中:

class AnswerQuestions(generics.CreateAPIView, generics.GenericAPIView):
    queryset = Answer.objects.all()
    serializer_class = AnswerQuestionsSerializer

    def perform_create(self, serializer):
        return serializer.save(user=self.request.user, question_id=self.kwargs['pk'])

    def get_queryset(self):
        return super().get_queryset().filter(
            question_id=self.kwargs['pk']
        )

您可以使用 mixin,例如:

class ParentKeyAPIView:
    parent_url_pk = 'pk'
    parent_model_field = None

    def perform_create_kwargs(self, **kwargs):
        kwargs[self.parent_model_field] = self.kwargs[self.parent_url_pk]
        return kwargs

    def perform_create(self, serializer):
        return serializer.save(**self.perform_create_kwargs())

    def get_queryset(self):
        return super().get_queryset().filter(
            **{self.parent_model_field: self.kwargs[self.parent_url_pk]}
        )

那么你可以使用这样的mixin:

class AnswerQuestions(ParentKeyAPIView, generics.CreateAPIView):
    model = Answer
    parent_model_field = 'question_id'
    serializer_class = AnswerQuestionsSerializer

    def perform_create_kwargs(self, **kwargs):
        return super().perform_create_kwargs(user=self.request.user, **kwargs)

那么 mixin 至少会同时兼顾过滤对象的创建。

【讨论】:

    猜你喜欢
    • 2017-02-04
    • 2013-03-06
    • 2016-11-09
    • 1970-01-01
    • 2017-11-02
    • 2016-10-04
    • 2013-06-21
    相关资源
    最近更新 更多