Django 静止框架序列化多到多字段

如何将一个多对多字段序列化为某个列表,并通过 rest 框架返回它们?在下面的示例中,我试图返回文章以及与之相关联的标记列表。

Models.py

class post(models.Model):
tag = models.ManyToManyField(Tag)
text = models.CharField(max_length=100)

序列化器 py

class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = ("text", "tag"??)

视野,视野

class PostViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
133951 次浏览

You will need a TagSerializer, whose class Meta has model = Tag. After TagSerializer is created, modify the PostSerializer with many=True for a ManyToManyField relation:

class PostSerializer(serializers.ModelSerializer):
tag = TagSerializer(read_only=True, many=True)


class Meta:
model = Post
fields = ('tag', 'text',)

答案是 DRF3

这对我有用。

tag = TagSerializer(source="tag", read_only=True, many=True)

Init方法的序列化程序中,您可以将查询集传递给字段,rest _ Framework 验证该查询集上的 id

1)首先从序列化器扩展序列化器

class YourSerializer(serializers.ModelSerializer):

2)在元类中包含字段

class YourSerializer(serializers.ModelSerializer):
class Meta:
fields = (..., 'your_field',)

3)在 init 方法中:

def __init__(self, *args, **kwargs):
super(YourSerializer, self).__init__(*args, **kwargs)
self.fields['your_field].queryset = <the queryset of your field>

可以像通常那样使用过滤器或排除器在任何参数下限制该字段的查询集。如果你想包括所有只是使用。Objects.all ()

姜戈2.0

对于多对多领域,如果您想要特定的一个:

class QuestionSerializer(serializers.ModelSerializer):


topics_list = serializers.SerializerMethodField()


def get_topics_list(self, instance):
names = []
a = instance.topics.get_queryset()
for i in a:
names.append(i.desc)
return names
class Meta:
model = Question
fields = ('topics_list',)

这就是我所做的,让我们假设一本书可以有不止一个作者,一个作者可以有不止一本书: 关于模型:

class Author(models.Model):
name = models.CharField(max_length=100, default="")
last_name = models.IntegerField(default=0)


class Book(models.Model):
authors = models.ManyToManyField(Author, related_name="book_list", blank=True)
name = models.CharField(max_length=100, default="")
published = models.BooleanField(default=True)

关于序列化器:

class BookSerializer(serializers.ModelSerializer):
authors = serializers.PrimaryKeyRelatedField(queryset=Author.objects.all(), many=True)


class Meta:
model = Book
fields = ('id', 'name', 'published', 'authors')




class AuthorSerializer(serializers.ModelSerializer):
book_list = BookSerializer(many=True, read_only=True)


class Meta:
model = Author
fields = ('id', 'name', 'last_name', 'book_list')

补充@Brian 的回答 “ tag”: [{“ name”: “ tag1”}]可以简化为“ tag”: [“ tag1”,“ tag2”,... ]这样:

class TagListingField(serializers.RelatedField):
 

def to_representation(self, value):
return value.name


class PostSerializer(serializers.ModelSerializer):
tag = TagListingField(many=True, read_only=True)


class Meta:
...

更多信息请点击: https://www.django-rest-framework.org/api-guide/relations/#custom-relational-fields

默认的 ModelSerializer对关系使用主键。但是,您可以使用 Meta depth属性轻松地生成嵌套表示:

class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = ("text", "tag")
depth = 1

文件所述:

depth选项应该设置为一个整数值,该值指示在恢复为平面表示形式之前应该遍历的关系的深度。

嗨,我将显示许多对许多更新和创建。上下文就是活动可以有很多舞蹈,舞蹈可以有很多活动。

请求如下。

 {
"competition": 2,
"title": "the title",
"dances":[ {"id":1},{"id":2}],
"description": "the desc"
}

创建函数如下所示。
def create(self, validated_data):
try:
dance_ids = []
for dance in self.initial_data['dances']:
if 'id' not in dance:
raise serializers.ValidationError({'detail': 'key error'})
dance_ids.append(dance['id'])


new_event = models.Event.objects.create(**validated_data)
        

if dance_ids:
for dance_id in dance_ids:
new_event.dances.add(dance_id)
new_event.save()
return new_event


except Exception as e:
raise serializers.ValidationError({'detail': e})

更新函数如下所示。
def update(self, instance, validated_data):
# Delete all records of genres.
try:
for current_genre in instance.dances.all():
instance.dances.remove(current_genre)


# Repopulate genres into instance.
for dance in self.initial_data['dances']:
if 'id' not in dance:
raise serializers.ValidationError({'detail': 'key error'})
dance_obj = models.Dance.objects.get(pk=dance['id'])
instance.dances.add(dance_obj)


event_updated = super().update(instance, validated_data)


return event_updated
except Exception as e:
raise serializers.ValidationError({'detail': e})

如果你只想做“舞蹈”: [1,2] ,只需要对

for dance in self.initial_data['dances']:
if 'id' not in dance:
raise serializers.ValidationError({'detail': 'key error'})
dance_ids.append(dance['id'])

我希望这能帮助你们! :)

Models.py

class Tag(models.Model):
name = models.CharField(max_length=100)
# ===============
# ... rest of the fields ...


class Post(models.Model):
tag = models.ManyToManyField(Tag)
text = models.CharField(max_length=100)

连环杀手

class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tag
fields = '__all__'




class PostSerializer(serializers.ModelSerializer):
tags = TagSerializer(many=True, read_only=True)


class Meta:
model = Post
fields = ("text", "tag")

视野,视野

## FUNCTION BASED VIEW
def fbvPost_ListView(request):
# list
if request.method == "GET":
posts = Post.objects.all()
serializer = PostSerializer(instance=posts, many=True)
return JsonResponse(serializer.data, safe=False)


return JsonResponse({"success": False})


# ===========================================================


## CLASS BASED VIEW
class cbvPost_ListView(viewsets.ReadOnlyModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer

注意: 标签,邮件是两个模型,我们需要序列化他们。在这里,Post 模型依赖于 Tag 模型,所以我们在这里明确提到它,[ Tag = TagSerializer (many = True,read _ only = True)]或者它返回它的主字段值。

详情在这里

首先,Tag 也需要自己的序列化程序

class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tag
fields = '__all__'

然后在 PostSerializer 中添加一行

class PostSerializer(serializers.ModelSerializer):
tag = TagSerializer(read_only=True, many=True).data
class Meta:
model = Post
fields = ("text", "tag")

这将使 Post 中的 Tag 字段成为一个标记 ID 数组。如果你不把。“ data”部分,它将把所有属性的标签,这可能是在大多数情况下太多

可以使用序列化器.slugRelatedField ()或序列化器.StringRelatedField (many = True) 序列化关系

就你而言:

class PostSerializer(serializers.ModelSerializer):
tag = serializers.StringRelatedField(many=True) # this will return a list




class Meta:
model = Post
fields = ('tag', 'text',)