programing

다에서 다로 필드를 직렬화하는 장고레스트 프레임워크

luckcodes 2023. 7. 22. 15:55

다에서 다로 필드를 직렬화하는 장고레스트 프레임워크

다대다 필드를 목록으로 직렬화하고 휴식 프레임워크를 통해 반환하려면 어떻게 해야 합니까?아래의 예에서, 저는 게시물과 관련된 태그 목록을 함께 반환하려고 합니다.

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입니다.

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

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의 답 "tags"에 [{"name": "tag1"}]를 추가하면 다음과 같이 "tags": ["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플랫 표현으로 되돌리기 전에 통과해야 하는 관계의 깊이를 나타내는 정수 값으로 옵션을 설정해야 합니다.

이것은 나에게 효과가 있습니다.

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

장고 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',)

init의 serializer 메서드에서 쿼리 세트를 필드로 전달하고 rest_framework에서 해당 쿼리 세트의 ids를 검증할 수 있습니다.

먼저 직렬화기에서 직렬화기를 확장합니다.모델 직렬화 장치

class YourSerializer(serializers.ModelSerializer):

메타 클래스에 필드 포함

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

init 방법:

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

일반적으로 하는 것처럼 필터 또는 제외를 사용하여 인수에서 해당 필드에 대한 쿼리 집합을 제한할 수 있습니다.모두 포함시키고 싶은 경우 그냥 use .objects.all()

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)

serialiazers.py

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

views.py

## 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

NB: 태그, 포스트는 두 가지 모델이며 우리는 그것들을 연재해야 합니다.여기서 포스트 모델은 태그 모델의 종속성을 가지므로 여기서는 [tag=TagSerializer(many=True, read_only=True)] 또는 이를 반환하는 기본 필드 값을 명시적으로 언급합니다.

자세한 내용은 여기

안녕하세요. 업데이트 및 생성을 위해 많은 분들께 보여드리겠습니다.그 행사는 많은 춤을 출 수 있고 춤은 많은 행사를 할 수 있다는 맥락입니다.

요청 사항은 다음과 같습니다.

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

The Create Function will be as followed.
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})

The Update Function will be as followed.
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'])

파트. 이것이 여러분에게 도움이 될 수 있기를 바랍니다!

먼저, 태그도 자체 직렬화기가 필요합니다.

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

이렇게 하면 포스트의 태그 필드가 태그 ID의 배열이 됩니다.".data" 부분을 넣지 않으면 태그의 모든 속성을 넣을 것이며, 대부분의 경우에는 너무 많을 것입니다.

직렬화기를 사용할 수 있습니다.SlugRelatedField() 또는 직렬화자.StringRelatedField(다수=참) 직렬화 도구 관계

당신의 경우:

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


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

언급URL : https://stackoverflow.com/questions/33182092/django-rest-framework-serializing-many-to-many-field