Python Django rest框架

Python Django rest框架,python,django,django-rest-framework,Python,Django,Django Rest Framework,我正在尝试使用外键关系发布到我的API。这让我回想起了一个错误,它说它需要一个字典,而不是字符、字符和阶段的int。这是因为我的模型的设置方式。他们有外键关系。所讨论的模型如下所示: import uuid from django.db import models from django.utils import timezone from analysis.models import Analysis from characters.models import Character from s

我正在尝试使用外键关系发布到我的API。这让我回想起了一个错误,它说它需要一个字典,而不是
字符
字符
阶段
的int。这是因为我的模型的设置方式。他们有外键关系。所讨论的模型如下所示:

import uuid
from django.db import models
from django.utils import timezone
from analysis.models import Analysis
from characters.models import Character
from stages.models import Stage

class Match(models.Model):
    analysis = models.ForeignKey(Analysis, on_delete=models.CASCADE)
    character = models.ForeignKey(Character, on_delete=models.CASCADE, related_name='character')
    character_won = models.BooleanField()
    character_opponent = models.ForeignKey(Character, on_delete=models.CASCADE, related_name='character_opponent')
    character_opponent_won = models.BooleanField()
    created_at = models.DateTimeField(editable=False)
    id = models.UUIDField(primary_key=True, default=uuid.uuid4)
    updated_at = models.DateTimeField(editable=False)
    stage = models.ForeignKey(Stage, on_delete=models.CASCADE)

    def __str__(self): 
        return '%s vs. %s on %s' % (self.character, self.character_opponent, self.stage)

    def save(self, *args, **kwargs):
        ''' On save, update timestamps '''
        if not self.created_at:
            self.created_at = timezone.now()
        self.updated_at = timezone.now()
        return super(Match, self).save(*args, **kwargs)

    class Meta:
        db_table = "matches"
这是我的序列化程序:

from rest_framework import serializers
from matches.models import Match
from characters.serializers import CharacterSerializer
from stages.serializers import StageSerializer

class MatchSerializer(serializers.ModelSerializer):
    character = CharacterSerializer()
    character_opponent = CharacterSerializer()
    stage = StageSerializer()

    class Meta:
        model = Match
        fields = ('id', 'analysis', 'character', 'character_won', 'character_opponent', 'character_opponent_won', 'stage')

是否有一些选择,我在这里错过了能够正确张贴?很明显,我不应该每次发布内容时都要传递整个角色对象,对吗?我应该能够传递主键。

当您使用另一个序列化程序声明与序列化程序相关的字段时,如下所示

character = CharacterSerializer()
您正在告诉django rest框架您需要一个嵌套序列化程序。你想要的是这样的东西

character = serializers.PrimaryKeyRelatedField()

或者您实际上可以将显式字段声明保留在序列化程序之外(因为这是默认设置),请参见。

当您使用其他序列化程序声明与序列化程序相关的字段时,如下图所示

character = CharacterSerializer()
您正在告诉django rest框架您需要一个嵌套序列化程序。你想要的是这样的东西

character = serializers.PrimaryKeyRelatedField()

或者您实际上可以将显式字段声明保留在序列化程序之外(因为这是默认设置),请参见。

这将取决于您的CharacterSerializer和StageSerializer。如果您想输入一种格式(使用
serialiser.PrimaryKeyRelatedField()
),但输出另一种格式(
CharacterSerializer
StageSerializer
),最好使用两种serialiser并在视图中切换


在您的视图中,您可以覆盖
get\u serializer\u class
并检查您的请求方法,或者在视图集的情况下,您可以检查正在调用的方法。

这将取决于您的CharacterSerializer和StageSerializer。如果您想输入一种格式(使用
serialiser.PrimaryKeyRelatedField()
),但输出另一种格式(
CharacterSerializer
StageSerializer
),最好使用两种serialiser并在视图中切换


在您的视图中,您可以覆盖
get\u serializer\u类
并检查您的请求方法,或者在视图集的情况下,您可以检查正在调用的方法。

从您的几条评论中,我了解到您需要
get
方法中的嵌套序列化程序。我的建议是,为您的API类使用两个[或更多]序列化程序。
假设您使用的是
ModelViewSet
API类正在使用的,那么您可以覆盖
get\u serializer\u class()
方法,如下所示,

from rest_framework.viewsets import ModelViewSet


class MatchAPI(ModelViewSet):
    queryset = Match.objects.all()

    def get_serializer_class(self):
        if self.action == 'create':
            return MatchCreateSerializer
        return MatchSerializer
您的
MatchCreateSerializer
将如下所示,

class MatchCreateSerializer(serializers.ModelSerializer):
    class Meta:
        fields = '__all__'
        model = Match

因此,在创建
Match
实例时,您只需提供
PKs
analysis
character
等,我知道您需要
GET
方法中的嵌套序列化程序。我的建议是,为您的API类使用两个[或更多]序列化程序。
假设您使用的是
ModelViewSet
API类正在使用的,那么您可以覆盖
get\u serializer\u class()
方法,如下所示,

from rest_framework.viewsets import ModelViewSet


class MatchAPI(ModelViewSet):
    queryset = Match.objects.all()

    def get_serializer_class(self):
        if self.action == 'create':
            return MatchCreateSerializer
        return MatchSerializer
您的
MatchCreateSerializer
将如下所示,

class MatchCreateSerializer(serializers.ModelSerializer):
    class Meta:
        fields = '__all__'
        model = Match

因此,在创建
Match
实例时,您只需要提供
analysis
character
等的
PKs
,这实际上对我不起作用,因为我在使用
GET
时需要嵌套字段。如果您需要反序列化程序与序列化程序的工作方式不同,然后您应该按照Jason Havenaar的建议使用两个序列化程序。我刚刚回答了您关于如何使主键工作的问题。这实际上对我不起作用,因为我在使用
get
时需要嵌套字段。如果您需要反序列化程序与序列化程序的工作方式不同,那么您应该按照Jason Havenaar的建议使用两个序列化程序。我刚才回答了你关于如何使主键工作的问题。你是说对
get
使用序列化程序,对
POST
使用另一个序列化程序?看起来有点奇怪…我同意表面上有点奇怪。这个想法是,您对同一个对象有两种不同的表示——因此有两种不同的序列化器。或者,您可以创建一个自定义字段类型,该字段类型继承
PrimaryKeyRelatedField
,并重写to_表示方法以更改输出。例如,您所说的为
GET
使用序列化程序,为
POST
使用另一个序列化程序?看起来有点奇怪…我同意表面上有点奇怪。这个想法是,您对同一个对象有两种不同的表示——因此有两种不同的序列化器。或者,您可以创建一个自定义字段类型,该字段类型继承
PrimaryKeyRelatedField
,并重写to_表示方法以更改输出。示例位于,谢谢!我制作了两个序列化程序,一个名为
MatchReadSerializer
MatchCreateSerializer
,并在适当的设置中使用它们。现在一切都好了,我可以给他们发帖了!谢谢我制作了两个序列化程序,一个名为
MatchReadSerializer
MatchCreateSerializer
,并在适当的设置中使用它们。现在一切都好了,我可以给他们发帖了!