Skip to main content

使您的模型、管理器和查询集可序列化的 Django 类,内置对大约 150 LoC 中的相关对象的支持

项目描述

django-序列化模型

PyPI 版本 发布 提交
分米 dw
构建状态 代码覆盖率
使您的模型、管理器和查询集可序列化的 Django 类,内置对大约 100 LoC 中的相关对象的支持(比这个 README 短!)

目录

一、安装
二、 三、用法 它是如何工作 的 IV。相关图书馆 V.背景故事


安装

pip install django-serializable-model

预计您已经安装了 Django

兼容性

Python 版本 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 不存在,因此某些功能可能在这些版本中受到限制,或者可能只是在导入时出错
  • 尚未确认这是否适用于早期版本的 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.tar.gz (8.1 kB 查看哈希)

已上传 source

内置分布

django_serializable_model-0.0.6-py2.py3-none-any.whl (8.0 kB 查看哈希

已上传 py2 py3