在设计表结构时,难免需要建立一些外键关联,例如这样两个模型:
django。数据库导入模型 类人(models.Model): 用户名=models.CharField (max_length=100) 生日=models.DateField () 类的书(models.Model): name=models.CharField (max_length=100) 作者=models.ForeignKey(人,> django。核心进口序列化器 book_json=序列化器。序列化(json, Book.objects.get (pk=1)
JSON序列化结果如下:
{ “pk”: 1、 “模型”:“store.book”, “字段”:{ “名称”:“主要是无害的”, “作者”:42 } }
这个“作者”:42对用户来说相当于未知,我们需要的是人表中主键为42的用户姓名,即用户名的值。
在Django官方文档的“序列化”一节中提到了用模型。经理处理的方案,在搜索解决方案过程中,也接触到Django-REST-Framework肾盂输尿管)了解到DRF中的序列化器模块也能解决这类问题。那我们不妨对比一下两种解决方案。
<强>方案一:模型。经理强>
根据文档,要返回自然主键,我们需要定义一个模型管理器,创建一个get_by_natural_key方法,如下:
django。
django。数据库导入模型 类PersonManager (models.Manager): def get_by_natural_key(自我、用户名): 返回self.get(用户名=用户名) 类人(models.Model): 用户名=models.CharField (max_length=100) 生日=models.DateField () 对象=PersonManager ()
然后再次序列化书实例:
django。核心进口序列化器 book_json=序列化器。序列化(json, Book.objects.get (pk=1), use_natural_foreign_keys=True)
得到新的结果如下:
{
引用>
,,“pk”: 1,
,,“模型”:“商店。书”,
,,“字段”:{
,,,,,,“名称”:“主要是无害的”,
,,,,,,“作者”(“DouglasAdams”):
,,}
}
如果需要对其他应用的数据模型做修改,例如使用了django.auth.User(默认认证后端)作为Book 用户的外键,要想不修改模型又使用新的模型管理器,可以使用代理模式完成:
django。数据库导入模型 类新任(models.Manager): #…… 通过 类MyPerson(人): 对象=新任() 类元: 代理=True总的来说,这个方案可以完美解决我所遇到的问题,代码量稍微大一些,但是也更灵活。
<强>方案二:DRF的序列化器强>
下面我们试试用Django-REST-Framework的序列化模块:
从rest_framework进口序列化器 从进口得书 类BookSerializer (serializers.ModelSerializer): author_name=serializers.CharField(源=癮uthor.username”) 类元: 模型=书 字段=' __all__ '这段代码表示,在序列化书实例时,添加一个新的属性author_name,该值的来源为源参数定义的外键作者实例的自然主键用户名。
然后是执行序列化的过程:
queryset=Book.objects.get (pk=1) BookSerializer(实例=queryset)序列化结果:
{
引用>
,,“id”: 1、
,,“名称”:“主要是无害的”,
,,“作者”:42岁,
,,:“author_name DouglasAdams”
}
当然,序列化一批书实例也是可以的:
queryset=Book.objects.all () BookSerializer (=queryset实例,许多=True)序列化结果:
(
,,{
,,,,,,“id”: 1、
,,,,,,“名称”:“主要是无害的”,
,,,,,,“作者”:42岁,
,,,,,,:“author_name DouglasAdams”
,,},
,,{
,,,,,,“id”: 2,
,,,,,,“名称”:“哈利波特”,Django模型序列化返回自然主键值示例代码