django-rest-framework - 如何从模型 m2m 关系中预先选择自定义 DRF MultipleChoiceField 中的选项?
问题描述
我的Book
模型可以Tag
通过 m2m 关系拥有与之关联的模型,这些标签总是通过 FKTagCategory
模型进一步分类。
class TagCategory(models.Model):
name = models.CharField(...)
class Tag(models.Model):
name = models.CharField(...)
category = models.ForeignKey(to=TagCategory, ...)
class Book(models.Model):
tags = models.ManyToManyField(to=Tag, ...)
使用来自 DRF 的序列化程序,我希望为最终用户BookSerializer
提供一个MultipleChoiceField
从中选择多个标签的选项。如果我使用serializers.ModelSerializer
并且不触摸任何东西,它就可以正常工作。
但我实际上想按类别对标签/选择进行分组,这不是默认行为,所以我必须定义自己的MultipleChoiceField
并在其中进行选择分组并提醒字段从模型的正确属性中choices
获取它:source
Book
class BookSerializer(serializers.ModelSerializer):
tags_input = serializers.MultipleChoiceField(
choices=[
[category.name, [[tag.pk, tag.name]
for tag in category.tags.all()]] for category in Category.objects.all()],
source="tags",
write_only=True,
)
fields = ("tags_input",)
这似乎适用于Book
通过 m2m 创建模型和分配标签。但是,当使用标签序列化现有模型以进行更新时,初始标签/选项未按预期预先选择。设置initial="tags"
似乎没有改变任何东西。
如何在序列化模型时成功检索和预选标签/选项Book.tags
?
解决方案
好的,所以我在这里的困惑是认为它ModelSerializer
实际上会使用MultipleChoiceField
,所以我可以击败它并自己定义它:不。tags
是 m2m 关系,所以我需要一个RelatedField
与many=True
某个地方。
首先,由于我从同一个模型字段序列化和反序列化,我不应该做tags_input
我想出的解决方法。我需要一个可以做所有事情的领域:
class TagChoiceRelatedField(serializers.RelatedField):
queryset = Tags.objects.all()
def to_representation(self, value):
return value.pk
def get_choices(self, cutoff=None):
return {
category.name:
{tag.pk: tag.name for tag in category.tags.all()}
for category in TagCategory.objects.all()
}
def to_internal_value(self, data):
try:
tag = self.get_queryset().get(pk=data)
except ObjectDoesNotExist:
raise ValidationError()
return tag
class BookSerializer(serializers.ModelSerializer):
tags = TagChoiceRelatedField(many=True)
class Meta:
fields = ("tags",)
序列化程序现在使用该字段来:
- 预期用其 pk (to_representation) 序列化每个标签
- 预期使用 pk (to_internal_value) 反序列化每个标签
- 根据类别(get_choices)很好地对标签/选择进行分组
- 如果适用,最后用书实例的标签初始化后者(内部的东西)
推荐阅读
- r - 如何在R中的绘图中添加图例
- java - 内部类对象
- python - 如何在 Python 中获得高精度的数学计算
- r - 如何确保只能从 4 个不同的单选按钮组中选择一个单选按钮 R Shiny
- django-allauth - 如何从我的数据中安全地删除 django-allauth socialaccounts 表
- php - 从 laravel 中的另一个文件夹访问 css/js 文件
- asp.net-core - NGINX 反向代理背后的 ASP.NET Core
- html - 第一个元素已经被点击
- objective-c - 在 iOS 14 Objective-C 中连接多个键盘
- python - Pygame中没有显示文本?我尝试了其他一些方法来修复,但没有任何帮助