django类,使您的模型、管理器和查询集可序列化,内置对~100 loc中相关对象的支持

django-serializable-model的Python项目详细描述


django可序列化模型

PyPI versionreleasescommits
dmdw

Django类使您的模型、管理器和QuerySets可序列化,内置对~100 loc中相关对象的支持(比本自述文件短!)

目录

i.Installation
二。Usage
三、How it Works
四、Related Libraries
Backstory

安装

pip install django-serializable-model

预计您已经安装了django

兼容性

这最初用于Python2.7的旧Django1.5代码库。

应该与Django 1.4-1.9和Python 2.7-3.x一起使用。

  • 可能适用于django 1.10-2.x,但不能百分之百确定^{} usage works the same way in these
  • 2to3表明没有什么可更改的,因此应该与python 3.x兼容
  • 可能也适用于django 0.95-1.3
    • 0.95前,管理器API不存在,所以有些功能可能在这些版本中受到限制,或者在导入
    • 时可能发生错误。
  • 尚未确认这是否适用于早期版本的python。

如果您有兼容性问题或已确认版本的兼容性,请提交PR或提交问题。


用法

最简单的用例,只需在模型上实现.serialize()函数:

fromdjango.dbimportmodelsfromdjango_serializable_modelimportSerializableModelclassUser(SerializableModel):email=models.CharField(max_length=765,blank=True)name=models.CharField(max_length=100)new_user=User.objects.create(name='John Doe',email='john@doe.com',)printnew_user.serialize()# {'id': 1, 'email': 'john@doe.com', 'name': 'John Doe'}

通过重写默认的.serialize()函数,只在序列化字典中包含白名单字段:

fromdjango.dbimportmodelsfromdjango_serializable_modelimportSerializableModelclassUser(SerializableModel):email=models.CharField(max_length=765,blank=True)name=models.CharField(max_length=100)# whitelisted fields that are allowed to be seenWHITELISTED_FIELDS=set(['name',])defserialize(self,*args,**kwargs):"""Override serialize method to only serialize whitelisted fields"""fields=kwargs.pop('fields',self.WHITELISTED_FIELDS)returnsuper(User,self).serialize(*args,fields=fields)new_user=User.objects.create(name='John Doe',email='john@doe.com',)printnew_user.serialize()# {'name': 'John Doe'}

使用简单的一对一关系:

fromdjango.dbimportmodelsfromdjango_serializable_modelimportSerializableModelclassUser(SerializableModel):email=models.CharField(max_length=765,blank=True)name=models.CharField(max_length=100)classSettings(SerializableModel):user=models.OneToOneField(User,primary_key=True)email_notifications=models.BooleanField(default=False)defserialize(self,*args):"""Override serialize method to not serialize the user field"""returnsuper(Settings,self).serialize(*args,exclude=['user'])new_user=User.objects.create(name='John Doe',email='john@doe.com',)Settings.objects.create(user=new_user)new_user_refreshed=User.objects.select_related('settings').get(pk=new_user.pk)printnew_user_refreshed.serialize()# {'id': 1, 'email': 'john@doe.com', 'name': 'John Doe'}# recursively serialize Settings object by passing the join inprintnew_user_refreshed.serialize('settings')# {'id': 1, 'email': 'john@doe.com', 'settings': {'email_notifications': False}, 'name': 'John Doe'}

具有外键关系:

fromdjango.dbimportmodelsfromdjango_serializable_modelimportSerializableModelclassUser(SerializableModel):email=models.CharField(max_length=765,blank=True)name=models.CharField(max_length=100)classPost(SerializableModel):user=models.ForeignKey(User)text=models.TextField()new_user=User.objects.create(name='John Doe',email='john@doe.com',)Post.objects.create(user=new_user,text='wat a nice post')Post.objects.create(user=new_user,text='another nice post')# called on QuerySetprintPost.objects.all().serialize()# [{'id': 1, 'text': 'wat a nice post', 'user_id': 1}, {'id': 2, 'text': 'another nice post', 'user_id': 1}]# adds an _id to the foreign key name, just like when using `.values()`# called on Manageruser1=User.objects.get(pk=new_user.pk)printuser1.post_set.serialize()# [{'id': 1, 'text': 'wat a nice post', 'user_id': 1}, {'id': 2, 'text': 'another nice post', 'user_id': 1}]# recursively serialize Post objects by passing the join inprintUser.objects.prefetch_related('post_set').get(pk=new_user.pk).serialize('post_set')"""{    'id': 1,    'email': 'john@doe.com',    'name': 'John Doe',    'post_set': [{'id': 1, 'text': 'wat a nice post', 'user_id': 1}, {'id': 2, 'text': 'another nice post', 'user_id': 1}]}"""

.serialize接受任意数量的连接作为其*args,它们可以是任意深度的,使用与^{}相同的__语法。这意味着如果你的Post对象也有Comment对象,你可以写:

User.objects.prefetch_related('post_set__comment_set').serialize('post_set__comment_set')

并在每个Post字典中获取一个Comment字典数组。如果您的Post对象也有Like对象:

joins=['post_set__comment_set','post_set__like_set']User.objects.prefetch_related(*joins).serialize(*joins)

json和api

由于.serialize输出字典,因此只需在字典上使用json.dumps就可以将其转换为json。

如果您正在构建一个api,那么也可以在字典上使用JSONResponse


工作原理

在模型、管理器和查询集上实现一个.serialize方法允许在每个模型的基础上轻松地定制白名单和黑名单(以及其他内容)。 这种类型的行为不可能是简单的model_to_dict递归版本,但通常是各种安全措施和重写所必需的。 为了在关系/连接上递归,它接受与熟悉的prefetch_related相同的参数,在我的用例中,这些参数通常紧跟在.serialize调用之前。 .serialize还使用了一个自定义的model_to_dict函数,该函数的行为与内置函数的行为稍有不同,其方式在构建api时更为常见(请参阅docstring)。

我鼓励您阅读源代码,因为它比本自述文件短:)

相关库


背景

这个库是在我处理Yorango的即席api时构建的。编写用于序列化各种模型的代码是复杂而乏味的,这导致我们的许多api方法的代码混乱不堪。我在网上能找到的唯一解决方案是来自wadofstuffDjango Full Serializers以及一些递归的model_to_dict在线代码片段——这些代码片段都没有提供按模型定制白名单和黑名单的选项。 后来,我发现Django REST Framework's ModelSerializers确实提供了与我正在寻找的功能类似的函数(和{eM1} $,而没有需要购买到框架的其余部分),尽管增加了一些复杂性和健壮性。

最后,我在~100 loc中编写了自己的解决方案,基本上满足了我的所有需求,并替换了来自代码库周围的大量混乱的序列化代码。它在生产中得到了很好的结果,包括quit查询E的复杂性和深度,如:

joins=['unit_set','unit_set__listing_set','unit_set__listing_set__tenants','unit_set__listing_set__bill_set','unit_set__listing_set__payment_set__payer','unit_set__listing_set__contract']s_props=(user.property_set.all().prefetch_related(*joins).serialize(*joins))

我一直想提取并开源这个以及其他各种有用的实用程序库,我在yorango做了,最后得到了机会!

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java有没有工具可以将zephyr转换为velocity模板?   java在安卓 studio中从JSON响应中获取值   jvm如何在Java中设计一个好的permgen空间字符串?   java如何防止Rest webservice使用被盗令牌进行身份验证   java无法遍历列表JSTL   找不到用于ResourceServerTokenServices的java Bean SpringSecurityOauth2   java子字符串替换问题   爪哇玻璃鱼3。十、 以编程方式处理任意HTTPSession的终止   java如何检查输入是否为整数,并在最后添加一个命令来重新启动while循环?   引发java ical4j 1.0.6不可解析日期异常   Java等价于Delphi的DBCtrlGrid?   如果发生错误,java将查找下一个预期标记ANTLR 3   java自打开应用程序(创建锁屏)   java为什么netty有自己的ConcurrentHashMap?   Gradle任务中的java拉取和运行依赖项   继承与Java继承的混淆   java使用shell脚本中的版本执行jar   java我无法让Sqlite数据库与带有Maven的JavaFX应用程序IDE Eclipse包正确通信   java控制台日志未通过org打印。阿帕奇。hadoop。mapreduce。作业的waitForCompletion(true)方法   JAVAlang.NoSuchMethodError:apachestorm螺栓中的spring getrequest