使您的模型、管理器和查询集可序列化的 Django 类,内置对大约 150 LoC 中的相关对象的支持
项目描述
django-序列化模型
使您的模型、管理器和查询集可序列化的 Django 类,内置对大约 100 LoC 中的相关对象的支持(比这个 README 短!)
目录
一、安装
二、
三、用法 它是如何工作
的 IV。相关图书馆
V.背景故事
安装
pip install django-serializable-model
预计您已经安装了 Django
兼容性
在 Django 2.2、1.11、1.9和 1.5 以及 Python 3.5、3.4 和 2.7 上测试
- 应该适用于 Django 1.4-2.x 和 Python 2.7-3.x
- 内置了几个 Django 向后和向前兼容性修复程序
- 可能也适用于 Django 0.95-1.3
- Pre 1.3 不支持关于关系的
on_delete论点。这只影响下面的用法和示例;内部不受影响。 - 在 0.95 之前,Manager API 不存在,因此某些功能可能在这些版本中受到限制,或者可能只是在导入时出错
- Pre 1.3 不支持关于关系的
- 尚未确认这是否适用于早期版本的 Python。
如果您遇到兼容性问题或已确认版本兼容性,请提交 PR 或提交问题。
用法
最简单的用例,只是.serialize()在模型上实现功能:
from django.db import models
from django_serializable_model import SerializableModel
class User(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',
)
print new_user.serialize()
# {'id': 1, 'email': 'john@doe.com', 'name': 'John Doe'}
覆盖默认.serialize()函数以仅在序列化字典中包含列入白名单的字段:
from django.db import models
from django_serializable_model import SerializableModel
class User(SerializableModel):
email = models.CharField(max_length=765, blank=True)
name = models.CharField(max_length=100)
# whitelisted fields that are allowed to be seen
WHITELISTED_FIELDS = set([
'name',
])
def serialize(self, *args, **kwargs):
"""Override serialize method to only serialize whitelisted fields"""
fields = kwargs.pop('fields', self.WHITELISTED_FIELDS)
return super(User, self).serialize(*args, fields=fields)
new_user = User.objects.create(
name='John Doe',
email='john@doe.com',
)
print new_user.serialize()
# {'name': 'John Doe'}
使用简单的一对一关系:
from django.db import models
from django_serializable_model import SerializableModel
class User(SerializableModel):
email = models.CharField(max_length=765, blank=True)
name = models.CharField(max_length=100)
class Settings(SerializableModel):
user = models.OneToOneField(User, primary_key=True,
on_delete=models.CASCADE)
email_notifications = models.BooleanField(default=False)
def serialize(self, *args):
"""Override serialize method to not serialize the user field"""
return super(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)
print new_user_refreshed.serialize()
# {'id': 1, 'email': 'john@doe.com', 'name': 'John Doe'}
# recursively serialize Settings object by passing the join in
print new_user_refreshed.serialize('settings')
# {'id': 1, 'email': 'john@doe.com', 'settings': {'email_notifications': False}, 'name': 'John Doe'}
具有外键关系:
from django.db import models
from django_serializable_model import SerializableModel
class User(SerializableModel):
email = models.CharField(max_length=765, blank=True)
name = models.CharField(max_length=100)
class Post(SerializableModel):
user = models.ForeignKey(User, on_delete=models.CASCADE)
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 QuerySet
print Post.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 Manager
user1 = User.objects.get(pk=new_user.pk)
print user1.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 in
print User.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,它们可以是任意深度,使用与 . 相同的__语法prefetch_related。这意味着如果您的Post对象也有Comment对象,您可以编写:
User.objects.prefetch_related('post_set__comment_set').serialize('post_set__comment_set')
Comment并在每个字典中获取字典数组Post。如果您的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在 Models、Managers 和 QuerySets 上实现一个方法允许在每个模型的基础上轻松定制白名单和黑名单(除其他外)。这种行为不可能是 的简单递归版本model_to_dict,但对于各种安全措施和覆盖通常是必需的。为了递归关系/连接,它接受与熟悉的参数相同的参数prefetch_related,在我的用例中,它通常紧接在.serialize调用之前。
.serialize还使用了一个自定义model_to_dict函数,该函数的行为与内置函数略有不同,在构建 API 时更符合预期(请参阅文档字符串)。
我鼓励你阅读源代码,因为它比这个 README 短:)
相关图书馆
- django-api-装饰器
Tiny decorator functions to make it easier to build an API using Django in ~100 LoC
背景故事
这个库是在我处理Yorango的 ad-hoc API 时构建的。编写代码来序列化各种模型是复杂而乏味的,导致我们的许多 API 方法的代码混乱。我能在网上找到的唯一解决方案是 wadofstuff 的Django Full Serializers以及一些在线递归片段——它们都没有提供基于每个模型的可定制白名单和黑名单的选项。后来,我发现Django REST 框架的 ModelSerializer确实提供了与我正在寻找的功能相似的功能(并且不需要购买框架的其余部分),尽管增加了一些复杂性和健壮性。model_to_dict
我最终在 ~100 LoC 中编写了自己的解决方案,它基本上可以满足我的所有需求,并替换了代码库中大量杂乱的序列化代码。它在生产中使用并获得了惊人的结果,包括非常复杂和深度的查询,例如:
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 制作的其他各种有用的实用程序库,终于有机会了!
项目详情
django_serializable_model- 0.0.6 -py2.py3-none-any.whl 的哈希值
| 算法 | 哈希摘要 | |
|---|---|---|
| SHA256 | 66bf5a4cbd321e0c374052293079059cff1f829848500d749cb9e356390513b6 |
|
| MD5 | 287c9a1b39c8ab279fdf929069fc8deb |
|
| 布莱克2-256 | a5145904525262dbcfc36ee8cbe9ba9cbcfc4b3e7ee81cafca500c50cfd22667 |