在教程中,序列化器字段和模型字段之间存在这种松散的一对一映射。我可以预期,如果序列化程序字段和模型字段都是CharFields,它将在反序列化到模型实例时保存一串字符:
models.py:
class Deck(models.Model):
created = models.DateTimeField(auto_now_add=True)
name = models.CharField(max_length=100, unique=True, blank=False, null=False)
serializers.py:
class DeckSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Deck
fields = ('url', 'id', 'created', 'name')
extra_kwargs = {
'url': {
'view_name': 'goals:deck-detail',
}
}
但是当我尝试一个关系时,序列化器字段是一个ReadOnlyField,根据我的理解,它本质上是一个Charfield,但是模型字段是一个ForeignKeyField,并且为了增加混乱,我似乎在节省一个当我覆盖perform_create:
时视图中的对象models.py:
class Deck(models.Model):
created = models.DateTimeField(auto_now_add=True)
name = models.CharField(max_length=100, unique=True, blank=False, null=False)
user = models.ForeignKey('users.User', related_name='decks', on_delete=models.CASCADE, null=False)
serializers.py:
class DeckSerializer(serializers.HyperlinkedModelSerializer):
user = serializers.ReadOnlyField(source='user.username')
class Meta:
model = Deck
fields = ('url', 'id', 'created', 'name', 'user')
extra_kwargs = {
'url': {
'view_name': 'goals:deck-detail',
}
}
views.py:
class DeckList(generics.ListCreateAPIView):
serializer_class = DeckSerializer
def get_queryset(self):
return Deck.objects.all().filter(user__username=self.request.user)
def perform_create(self, serializer):
serializer.save(user=self.request.user)
这里发生了什么?在处理关系时,为什么我通过覆盖视图中的perform_create来保存对象,在序列化器中声明CharField,并在模型中声明一个关系字段?
我的理解中缺少什么,或者幕后真正发生了什么,以至于用户字段(ForeignKey)可以表示为字符串但是保存为对象?
修改
如果我在视图中覆盖serializer.save(user = user),并且serializers.py的用户字段为
user = serializers.CharField(read_only=True)
我想在serializers.py中覆盖save方法,如何传递正确的数据以便知道如何序列化?我只是抓住整个User对象,保存它,它还会完成剩下的工作吗? serializers.save()在视图中是否与serializers.py中的serializers.save()相同?
答案 0 :(得分:2)
不是100%确定我已经理解了你的要求,但如果问题是:
在Django ORM中保存ForeignKey字段时,幕后发生了什么?
然后答案是:
该关系作为(例如)int字段保存在DB中,该字段存储相关对象的主键。
Django文档中的ForeignKey field reference部分解释了ORM的这一部分是如何工作的,"Database Representation"子部分可能涉及您感兴趣的特定位。
例如,对于User
作为Deck
模型中相关字段的情况,基础表可能看起来像这样(假设是postgresql):
myapp_deck
id int
created timestamp
name varChar
user_id int
Deck -> User
关系由存储pk的数据库映射,用于user_id
表中myapp_deck
字段中的相关用户对象。
因此,所有Django(以及因此,DRF)需要做的是更改User
模型中的Deck
,将user_id
表中的myapp_deck
更改为另一个User
对象的PK。
希望这会有所帮助,如果我错过了你的问题,请告诉我。
已编辑添加自定义.create()方法的示例
如果要覆盖序列化程序中的自定义“保存”方法,则要覆盖的方法相应地为create()
和update()
(请参阅DRF文档中的Serializer "Saving instances"部分)。< / p>
这方面的一个例子可能是:
class DeckSerializer(serializers.HyperlinkedModelSerializer):
user = serializers.ReadOnlyField(source='user.username')
... Rest of your serializer code ...
def create(self, validated_data, **kwargs):
user_obj = User.objects.get(pk=validated_data["user"])
deck = Deck.objects.create(
name=validated_data["name"],
user=user_obj,
)
return deck
注意:这假设相关pk
对象的User
通过序列化程序传递,验证正常,并且在validated_data
字典中可用