Django REST Framework(DRF):将当前用户ID设置为字段值

Dun*_*xim 15 django django-rest-framework

我有他的模型NewsModel和2个序列化器:

models.py

class NewsModel(models.Model):
    title = models.CharField('?????????', max_length=255, help_text='???????????? ????? - 255 ????????')
    announce = models.TextField('?????', help_text='??????? ????? ???????')
    author = models.ForeignKey(settings.AUTH_USER_MODEL, help_text='????? ???????', related_name='news')
    full_text = models.TextField('?????? ????? ???????', help_text='?????? ????? ???????')
    pub_date = models.DateTimeField('???? ??????????', auto_now_add=True, default=timezone.now, help_text='???? ??????????')

    def comments_count(self):
        return NewsComment.objects.filter(news=self.id).count()

    def get_author_full_name(self):
        return self.author.get_full_name()

    class Meta:
        db_table = 'news'
        ordering = ('-pub_date',)
Run Code Online (Sandbox Code Playgroud)

serilizers.py:

from rest_framework import serializers
from .models import NewsModel
from extuser.serializers import UserMiniSerializer

class NewsReadSerializer(serializers.ModelSerializer):

    author = UserMiniSerializer()

    class Meta:
        model = NewsModel
        fields = ('id', 'title', 'announce', 'comments_count', 'reviews', 'author_name')

    def get_author_full_name(self, obj):
        return obj.get_author_full_name()


class NewsWriteSerializer(serializers.ModelSerializer):

    def validate_author(self, value):
        value = self.request.user.id
        return value

    class Meta:
        model = NewsModel        
Run Code Online (Sandbox Code Playgroud)

我在api.py中选择了序列化:

class NewsList(ListCreateAPIView):
    queryset = NewsModel.objects.order_by('-pub_date')
    def get_serializer_class(self, *args, **kwargs):
        if self.request.method == 'GET':
            return NewsReadSerializer
        return NewsWriteSerializer

    class Meta:
        model = NewsModel
Run Code Online (Sandbox Code Playgroud)

但是当我创建NewsModel项时,我看到错误400:错误的请求[{'author':'此字段是必需的'}]

如何在创建新项目时将当前用户ID设置为NewsItem.author值?

mar*_*dev 28

我认为您没有正确使用序列化程序.设置请求相关数据的更好做法是perform_create在视图中覆盖:

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

def perform_update(self, serializer):
    serializer.save(author=self.request.user)
Run Code Online (Sandbox Code Playgroud)

然后将您的作者序列化程序设置为只读:

author = UserMiniSerializer(read_only=True)
Run Code Online (Sandbox Code Playgroud)

通过这种方式,您可以简单地使用一个单独NewsSerializer的读取和写入操作.

  • 哇谢谢你! - 它应该是这样做的 - 特别是在扩展通用/模型视图集时.这似乎很明显,但不适合我.(那里有很多糟糕的解决方案,包括request.data修改.) (3认同)

Dun*_*xim 7

在DRF版本中,先前3字段必须声明为allow_null = True且default = None.没有此参数,DRF不会运行检查字段.结果代码:

class NewsReadSerializer(serializers.ModelSerializer):

    """
    Serializer only for reading.

    author field serialized with other custom serializer
    """

    author = UserMiniSerializer()

    class Meta:
        model = NewsModel
        fields = ('id', 'title', 'announce', 'comments_count', 'reviews', 'author', 'pub_date',)


class NewsWriteSerializer(serializers.ModelSerializer):

    """
    Serializer for creating and updating records.

    author here is the instance of PrimaryKeyRelatedField, linked to all users
    """

    author = serializers.PrimaryKeyRelatedField(
        queryset=User.objects.all(), # Or User.objects.filter(active=True)
        required=False, 
        allow_null=True, 
        default=None
    )

    # Get the current user from request context
    def validate_author(self, value):
        return self.context['request'].user

    class Meta:
        model = NewsModel      
        fields = ('title', 'announce', 'full_text', 'author',)
Run Code Online (Sandbox Code Playgroud)


小智 7

在新的DRF中,您可以编写

owner = serializers.HiddenField(
    default=serializers.CurrentUserDefault()
)
Run Code Online (Sandbox Code Playgroud)

参见http://www.django-rest-framework.org/api-guide/validators/#currentuserdefault

  • 请注意,如果希望将该字段返回给用户,则可以改用PrimaryKeyRelatedField并设置read_only = True (2认同)

小智 5

我会尝试这样的事情:

\n\n

你的模型.py

\n\n
class NewsModel(models.Model):\n    title = models.CharField(\n        \'\xd0\x97\xd0\xb0\xd0\xb3\xd0\xbe\xd0\xbb\xd0\xbe\xd0\xb2\xd0\xbe\xd0\xba\', max_length=255,\n        help_text=\'\xd0\x9c\xd0\xb0\xd0\xba\xd1\x81\xd0\xb8\xd0\xbc\xd0\xb0\xd0\xbb\xd1\x8c\xd0\xbd\xd0\xb0\xd1\x8f \xd0\xb4\xd0\xbb\xd0\xb8\xd0\xbd\xd0\xb0 - 255 \xd1\x81\xd0\xb8\xd0\xbc\xd0\xb2\xd0\xbe\xd0\xbb\xd0\xbe\xd0\xb2\')\n    announce = models.TextField(\'\xd0\x90\xd0\xbd\xd0\xbe\xd0\xbd\xd1\x81\',\n        help_text=\'\xd0\x9a\xd1\x80\xd0\xb0\xd1\x82\xd0\xba\xd0\xb8\xd0\xb9 \xd0\xb0\xd0\xbd\xd0\xbe\xd0\xbd\xd1\x81 \xd0\xbd\xd0\xbe\xd0\xb2\xd0\xbe\xd1\x81\xd1\x82\xd0\xb8\')\n    author = models.ForeignKey(\n        settings.AUTH_USER_MODEL,\n        help_text=\'\xd0\x90\xd0\xb2\xd1\x82\xd0\xbe\xd1\x80 \xd0\xbd\xd0\xbe\xd0\xb2\xd0\xbe\xd1\x81\xd1\x82\xd0\xb8\', related_name=\'news\')\n    full_text = models.TextField(\n        \'\xd0\x9f\xd0\xbe\xd0\xbb\xd0\xbd\xd1\x8b\xd0\xb9 \xd1\x82\xd0\xb5\xd0\xba\xd1\x81\xd1\x82 \xd0\xbd\xd0\xbe\xd0\xb2\xd0\xbe\xd1\x81\xd1\x82\xd0\xb8\',\n        help_text=\'\xd0\x9f\xd0\xbe\xd0\xbb\xd0\xbd\xd1\x8b\xd0\xb9 \xd1\x82\xd0\xb5\xd0\xba\xd1\x81\xd1\x82 \xd0\xbd\xd0\xbe\xd0\xb2\xd0\xbe\xd1\x81\xd1\x82\xd0\xb8\')\n    pub_date = models.DateTimeField(\n        \'\xd0\x94\xd0\xb0\xd1\x82\xd0\xb0 \xd0\xbf\xd1\x83\xd0\xb1\xd0\xbb\xd0\xb8\xd0\xba\xd0\xb0\xd1\x86\xd0\xb8\xd0\xb8\', auto_now_add=True,\n        default=timezone.now, help_text=\'\xd0\x94\xd0\xb0\xd1\x82\xd0\xb0 \xd0\xbf\xd1\x83\xd0\xb1\xd0\xbb\xd0\xb8\xd0\xba\xd0\xb0\xd1\x86\xd0\xb8\xd0\xb8\')\n\ndef comments_count(self):\n    return NewsComment.objects.filter(news=self.id).count()\n\ndef get_author_full_name(self):\n    return self.author.get_full_name()\n\nclass Meta:\n    db_table = \'news\'\n    ordering = (\'-pub_date\',)\n
Run Code Online (Sandbox Code Playgroud)\n\n

序列化器.py

\n\n

(参考:http://www.django-rest-framework.org/api-guide/validators/#currentuserdefault

\n\n
from <yourapp>.models import NewsModel\nfrom rest_framework import serializers\n\n\nclass NewsModelSerializer(serializers.ModelSerializer):\n    author = serializers.HiddenField(default=serializers.CurrentUserDefault())\n    class Meta:\n        model = NewsModel\n
Run Code Online (Sandbox Code Playgroud)\n\n

另外,您应该将settings.py设置为如下所示:

\n\n
REST_FRAMEWORK = {\n    \'DEFAULT_PERMISSION_CLASSES\': (\n        \'rest_framework.permissions.IsAuthenticated\',)\n}\n
Run Code Online (Sandbox Code Playgroud)\n