gpt4 book ai didi

Django模型序列化返回自然主键值示例代码

转载 作者:qq735679552 更新时间:2022-09-28 22:32:09 26 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章Django模型序列化返回自然主键值示例代码由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

场景 。

在设计表结构时,难免需要建立一些外键关联。例如这样两个模型:

?
1
2
3
4
5
6
7
8
9
from django.db import models
 
class person(models.model):
  username = models.charfield(max_length = 100 )
  birthdate = models.datefield()
 
class book(models.model):
  name = models.charfield(max_length = 100 )
  author = models.foreignkey(person, on_delete = models.cascade)

表 book 的字段 author 是表 person 的外键,我们试用 django 原生的 serializer 模块来对 book 实例序列化:

?
1
2
from django.core import serializers
book_json = serializers.serialize( "json" , book.objects.get(pk = 1 ))

json 序列化结果如下:

?
1
2
3
4
5
6
7
8
{
  "pk" : 1 ,
  "model" : "store.book" ,
  "fields" : {
   "name" : "mostly harmless" ,
   "author" : 42
  }
}

这个 "author": 42 对用户来说相当于未知,我们需要的是 person 表中主键为 42 的用户姓名,即 username 的值.

解决方案 。

在 django 官方文档的「序列化」一节中提到了用 models.manager 处理的方案;在搜索解决方案过程中,也接触到 django-rest-framework(drf) ,了解到 drf 中的 serializer 模块也能解决这类问题。那我们不妨对比一下两种解决方案.

方案一:models.manager 。

根据文档,要返回自然主键,我们需要定义一个模型管理器,创建一个 get_by_natural_key 方法,如下: from django.db import models 。

?
1
2
3
4
5
6
7
8
9
10
from django.db import models
 
class personmanager(models.manager):
  def get_by_natural_key( self , username):
   return self .get(username = username)
 
class person(models.model):
  username = models.charfield(max_length = 100 )
  birthdate = models.datefield()
  objects = personmanager()

然后再次序列化 book 实例:

?
1
2
from django.core import serializers
book_json = serializers.serialize( "json" , book.objects.get(pk = 1 ), use_natural_foreign_keys = true)

得到新的结果如下:

{     "pk": 1,     "model": "store.book",     "fields": {         "name": "mostly harmless",         "author": ["douglasadams"]     } } 。

如果需要对其他应用的数据模型做修改,例如使用了 django.auth.user(默认认证后端)作为 book  的外键,要想不修改 user 模型又使用新的模型管理器,可以使用代理模式完成:

?
1
2
3
4
5
6
7
8
9
10
11
from django.db import models
 
class newmanager(models.manager):
  # ...
  pass
 
class myperson(person):
  objects = newmanager()
 
  class meta:
   proxy = true

总的来说,这个方案可以完美解决我所遇到的问题,代码量稍微大一些,但是也更灵活.

方案二:drf 的 serializer 。

下面我们试试用 django-rest-framework 的序列化模块:

?
1
2
3
4
5
6
7
8
9
from rest_framework import serializers
from .models import book
 
class bookserializer(serializers.modelserializer):
  author_name = serializers.charfield(source = 'author.username' )
 
  class meta:
   model = book
   fields = '__all__'

这段代码表示,在序列化 book 实例时,添加一个新的属性 author_name,该值的来源为 source 参数定义的外键 author 实例的自然主键 username.

然后是执行序列化的过程:

?
1
2
queryset = book.objects.get(pk = 1 )
bookserializer(instance = queryset)

序列化结果:

{     "id": 1,     "name": "mostly harmless",     "author": 42,     "author_name": "douglasadams" } 。

当然,序列化一批 book 实例也是可以的:

?
1
2
queryset = book.objects. all ()
bookserializer(instance = queryset, many = true)

序列化结果:

[     {         "id": 1,         "name": "mostly harmless",         "author": 42,         "author_name": "douglasadams"     },     {         "id": 2,         "name": "harry potter",         "author": 2,         "author_name": "jkrowling"     } ] 。

可以看到,使用 drf 的序列化模块返回自然主键,不仅代码清晰改动少,而且效果也很不错,序列化数据少了一个层级,对前端也是十分友好的.

方案三:手动修改序列化后的外键 。

当然,还有一种最傻也是最容易想到的办法,就是在序列化后,手动修改 json 串中对应的外键值为自然主键值.

这种做法可以得到和方案一一样的效果,但是遇到查询结果为列表时我们需要遍历替换。同时试想一下,如果我们在每个视图中都这么处理,那代码会变得十分糟糕。不建议使用该方案.

总结 。

对比两种序列化方案,我个人更偏向于 drf 优雅的处理方式。当然,除了序列化,drf 还有很多功能,例如分页等,强烈建议学习学习.

当然,可能不存在最好的最好的技术方案,遇到这类问题选择最合适自己的就好。也可能还有更多的方法可以解决标题的问题,也欢迎留言探讨! 。

参考 。

  • docs.djangoproject.com/zh-hans/2.2…
  • docs.djangoproject.com/en/2.2/topi…
  • www.django-rest-framework.org/api-guide/f…

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我的支持.

原文链接:https://juejin.im/post/5cfcaac1e51d4510835e0272 。

最后此篇关于Django模型序列化返回自然主键值示例代码的文章就讲到这里了,如果你想了解更多关于Django模型序列化返回自然主键值示例代码的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com