Как мне сериализовать поле «многие ко многим» в список чего-либо и вернуть их через структуру отдыха? В моем примере ниже я пытаюсь вернуть сообщение вместе со списком связанных с ним тегов.
models.py
class post(models.Model):
tag = models.ManyToManyField(Tag)
text = models.CharField(max_length=100)
serializers.py
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = ("text", "tag"??)
views.py
class PostViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
Ответы:
Вам понадобится тот
TagSerializer
, у когоclass Meta
естьmodel = Tag
. ПослеTagSerializer
создания изменитеPostSerializer
сmany=True
помощьюManyToManyField
отношения:class PostSerializer(serializers.ModelSerializer): tag = TagSerializer(read_only=True, many=True) class Meta: model = Post fields = ('tag', 'text',)
Ответ для DRF 3
источник
read_only=True
Часть объясняется здесь: django-rest-framework.org/api-guide/relations/...Вот что я сделал. Предположим, что у книги может быть более одного автора, а у автора может быть более одной книги: О модели:
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 "тегов": [{"name": "tag1"}] можно упростить до "тегов": ["tag1", "tag2", ...] следующим образом:
class PostSerializer(serializers.ModelSerializer): tag = TagSerializer(read_only=True, many=True) class Meta: ... class TagSerializer(serializers.RelatedField): def to_representation(self, value): return value.name class Meta: model = Tag
Подробнее здесь: https://www.django-rest-framework.org/api-guide/relations/#custom-relational-fields
источник
У меня это работает.
tag = TagSerializer(source="tag", read_only=True, many=True)
источник
Django 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',)
источник
get_topics_list
вы могли упроститьreturn list(instance.topics.values_list('desc', flat=True))
В сериализаторе метода инициализации вы можете передать набор запросов в поле, а rest_framework проверить идентификаторы в этом наборе запросов.
1) сначала расширите свой сериализатор из сериализаторов.ModelSerializer
class YourSerializer(serializers.ModelSerializer):
2) включить поле в мета-класс
class YourSerializer(serializers.ModelSerializer): class Meta: fields = (..., 'your_field',)
3) в методе инициализации:
def __init__(self, *args, **kwargs): super(YourSerializer, self).__init__(*args, **kwargs) self.fields['your_field].queryset = <the queryset of your field>
Вы можете ограничить набор запросов для этого поля любым аргументом, используя фильтр или исключить, как обычно. Если вы хотите включить все, просто используйте .objects.all ()
источник
По умолчанию
ModelSerializer
для отношений используются первичные ключи. Однако вы можете легко создавать вложенные представления, используяMeta
depth
атрибут:class PostSerializer(serializers.ModelSerializer): class Meta: model = Post fields = ("text", "tag") depth = 1
Как упоминалось в документации :
источник