如何获取用户名而不是ID?

时间:2019-09-09 13:12:54

标签: django django-rest-framework serializer

我想编写一个类似高音的应用程序,我想获取作者的用户名而不是作者的ID。但是现在当我创建新的Tweet时出现此错误:NOT NULL约束失败:tweets_tweet.author_id

我首先尝试在我的seriliazer中使用get_ field 方法。

这是模型:

class Tweet(models.Model):
    slug = models.CharField(max_length=100, unique=True, null=True, 
    blank=True)
    content = models.TextField(max_length=150)
    datestamp = models.DateTimeField(auto_now_add=True)
    nb_likes = models.PositiveIntegerField(default=0)
    nb_comments = models.PositiveIntegerField(default=0)
    author = models.ForeignKey(
        User,
        on_delete = models.CASCADE,
        related_name = "tweets",
        related_query_name = "post",
        null=False
    )
    def save(self, *args, **kwargs):
        self.slug = slugify(self.content[:10]) + '-' + randomString()
        super(Tweet, self).save(*args, **kwargs)

这是我的序列化器:

class TweetSerializer(serializers.ModelSerializer):

    author = serializers.SerializerMethodField()

    def get_author(self, obj):
        return obj.user.username

    class Meta:
        model = Tweet
        fields = ["content", "author", "nb_likes", "nb_comments", "slug"]


    def to_representation(self, obj):
        representation = super().to_representation(obj)
        if obj.nb_likes > 50:
        representation['super_popular'] = True
        return representation

和我的JSON看起来像:

{
"content": "blablabla",
"author_username": "valentin",
"author": 1,
"nb_likes": 0,
"nb_comments": 0,
"slug": "blablabla-2159054817"
}

1 个答案:

答案 0 :(得分:1)

您可以看到hereSerializerMethodField是一个只读字段。因此,您已经将author设为只读,而您仍然希望能够使用Tweet创建一个author

现在,如果您要使用username而不是id进行读写,并且假设username是唯一的,那么this document会为您显示可供选择的选项相关字段:将SlugRelatedField设置为slug_field的{​​{1}}允许您将“作者”作为用户名传递,也将其作为“用户名”返回:

author

请注意,这意味着您需要更改输入的JSON,因为现在“作者”键映射到ID。

但是,如果您想使用author = SlugRelatedField(slug_field="username", queryset=User.objects.all()) 作为输入并使用id作为输出,则需要将其设置为自定义关系字段,其 representation 与< em>内部价值:

username

我在这里将class TweetAuthorField(serializers.PrimaryKeyRelatedField): def to_representation(self, value): return value.username 子类化,因为它已经完成了使用主键(id)将数据映射到对象的所有正确操作,因此无需重写该代码。