다 대다 필드를 직렬화하는 Django 나머지 프레임 워크


84

다 대다 필드를 무언가 목록으로 직렬화하고 나머지 프레임 워크를 통해 반환하는 방법은 무엇입니까? 아래 예제에서는 관련된 태그 목록과 함께 게시물을 반환하려고합니다.

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

@Brian의 도움말을 사용하여 "태그": [{ "name": "tag1"}] 형식으로 항목을 나열합니다. 목록으로 단순화하고 싶습니다.
가능한가요?

2
`태그를 사용 serializers.SlugRelatedField =`PostSerializers에 (많은 = 사실, READ_ONLY = 사실, slug_field = '제목', // 태그의 fireld 당신은 allow_null이 True = 보여주고 싶은)
M. Dhaouadi

답변:


105

당신은 필요합니다 TagSerializer, 그 class Meta있습니다 model = Tag. TagSerializer가 생성 된 후 관계에 대해 PostSerializerwith many=True를 수정합니다 ManyToManyField.

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

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

답은 DRF 3입니다.


효과가있다!!! : D이 serializer를 쉼표로 구분 된 목록으로 바꾸는 방법을 아십니까? class TagSerializer (serializers.ModelSerializer) : class Meta : model = 태그 필드 = ( 'name')
kengcc

1
바로 지금, "tags": [{ "name": "tag1"}] 단순화하고 싶습니다 : "tags": [ "tag1", "tag2", ...]
kengcc

태그 = serializers.ListField (source = 'tag'). 그러면 태그의 각 객체에 대한 str 표현 목록이 표시됩니다
Sachin Gupta

2
게시물을 통해 태그를 업데이트하려면 어떻게해야합니까? (예 : read_only 아님) read_only를 제거하고 태그 필드에 대한 업데이트를 PATCH하려고 할 때 이상한 동작이 발생합니다 (이미 존재하는 태그에 대한 오류가 발생 함)
getup8

1
read_only=True부분은 여기에 설명 : django-rest-framework.org/api-guide/relations/...
파벨 Vergeev

25

이것이 제가 한 일입니다. 한 책이 한 명 이상의 저자를 가질 수 있고 한 명의 저자가 한 권 이상의 책을 가질 수 있다고 가정 해 보겠습니다. 모델 :

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')

어떻게 우리가 책 엔터티를 만들 때 저자를 만들 수 있습니까 ??
Kishan Mehta

2
좀 더 자세한 답변을 원하는 경우 뷰 클래스에서 수행하는 네, 한 것은, 또 다른 질문을 게시하시기 바랍니다
예수 Almaral - Hackaprende

8

@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


4

이것은 나를 위해 작동합니다.

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

4

장고 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))
bdoubleu

2

init 메서드 의 serializer에서 쿼리 집합을 필드에 전달할 수 있으며 rest_framework는 해당 쿼리 집합의 ID를 확인합니다.

1) 먼저 serializer에서 serializer를 확장하십시오.

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 () 사용하십시오.


1

기본값 ModelSerializer은 관계에 기본 키를 사용합니다. 그러나 다음 Meta depth속성을 사용하여 중첩 된 표현을 쉽게 생성 할 수 있습니다 .

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

문서 에서 언급했듯이 :

depth옵션은 플랫 표현으로 되돌리기 전에 통과해야하는 관계의 깊이를 나타내는 정수 값으로 설정되어야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.