django类,使您的模型、管理器和查询集可序列化,内置对~100 loc中相关对象的支持
django-serializable-model的Python项目详细描述
django可序列化模型
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)。
我鼓励您阅读源代码,因为它比本自述文件短:)
相关库
- django-api-decorators
Tiny decorator functions to make it easier to build an API using Django in ~100 LoC
背景
这个库是在我处理Yorango的即席api时构建的。编写用于序列化各种模型的代码是复杂而乏味的,这导致我们的许多api方法的代码混乱不堪。我在网上能找到的唯一解决方案是来自wadofstuff的Django 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做了,最后得到了机会!