Nit*_*hin 6 python django django-rest-framework
TDLR:在 django-rest-framework 中实现标签的最佳方式是什么。其中标签有一个created_by字段,它是当前经过身份验证的用户。
我试图实现一个非常简单/常见的事情,为帖子添加标签。但显然它不是小菜一碟。
所以我有一个帖子模型和一个标签模型(可能有很多关系)。我希望用户能够更新和创建帖子。创建或更新帖子时,他应该能够更新帖子的标签。当帖子被标记为新标签时,如果该标签不存在,则应创建该标签。我还希望用户能够将标签指定为请求中的字符串列表。
示例请求
{
"name": "testpost1",
"caption": "test caption",
"tags": ["tag1", "tag2"],
},
Run Code Online (Sandbox Code Playgroud)
模型.py
class Tags(models.Model):
id = models.UUIDField(default=uuid.uuid4, primary_key=True, editable=False)
name = models.CharField(max_length=50, unique=True)
created_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name="created_tags")
class Posts(models.Model):
id = models.UUIDField(default=uuid.uuid4, primary_key=True, editable=False)
name = models.CharField(max_length=50)
caption = models.TextField(max_length=1000)
created_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name='posts')
tags = models.ManyToManyField('Tags', related_name='posts')
Run Code Online (Sandbox Code Playgroud)
序列化程序.py
class TagsSerializerMini(serializers.ModelSerializer):
created_by = serializers.PrimaryKeyRelatedField(default=serializers.CurrentUserDefault(), queryset=User.objects.all())
class Meta:
model = Tags
fields = ('name', 'created_by')
extra_kwargs = {
'created_by': {'write_only': True},
'name': {'validators': []},
}
def create(self, validated_data):
tag, created = Tags.objects.get_or_create(**validated_data)
if not created:
raise exceptions.ValidationError(validated_data['name']+" already exists.")
return tag
def to_representation(self, instance):
ret = super(TagsSerializerMini, self).to_representation(instance)
data = dict()
data['name'] = ret['name']
return data
Run Code Online (Sandbox Code Playgroud)
我试过两种方法。使用嵌套序列化程序和使用 slug 相关字段。
当使用 SlugRealtedfield 时,它会抛出标签对象不存在的验证错误。我正在计划是否可以取消此检查,我可以在 create() 之前创建所有标签并调用 super create。但我无法绕过该验证检查。我也无法弄清楚如何将当前用户传递给 slugrelatedfield。
经过一番搜索,我计划使用嵌套序列化程序。但我必须将标签指定为 dict [{"name":"tag1"}]。我还必须定义自定义创建和更新。我可以让创建工作,但不能让更新工作。
{
"name": "testpost1",
"caption": "test caption",
"tags": ["tag1", "tag2"],
},
Run Code Online (Sandbox Code Playgroud)
在我看来,使用 SlugRelatedField 而不是嵌套序列化器更优雅,因为这样您将拥有一个标签数组(以及响应中的标签名称数组)而不是一个字典数组 [{ "name": “标签名” }]
正如您所提到的,如果标签不存在,验证检查就会失败。我设法通过子类化 SlugRelatedField 并覆盖“to_internal_value”方法来克服这个问题。在原始实现中,此方法尝试从查询集中获取对象,如果对象不存在,则验证失败。因此,我不调用“get”方法,而是调用“get_or_create”:
class CustomSlugRelatedField(serializers.SlugRelatedField):
def to_internal_value(self, data):
try:
obj, created = self.get_queryset().get_or_create(**{self.slug_field: data})
return obj
except (TypeError, ValueError):
self.fail('invalid')
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2188 次 |
| 最近记录: |