Django REST framework的各种技巧集合。
项目描述
收集了Django REST framework的各种技巧。
先决条件
Django 2.2, 3.0, 3.1, 3.2, 4.0和4.1。
Python 3.7, 3.8, 3.9, 3.10和3.11。
依赖项
djangorestframework: 初始版本为3.6.3编写,但如今使用>=3.10,<3.14进行测试。可能在早期或更高版本上(甚至)支持,但无法保证。
安装
从PyPI安装最新稳定版本
pip install django-rest-framework-tricks
或从GitHub安装最新开发版本
pip install https://github.com/barseghyanartur/django-rest-framework-tricks/archive/master.tar.gz
将rest_framework和rest_framework_tricks添加到INSTALLED_APPS
INSTALLED_APPS = ( # ... # REST framework 'rest_framework', # REST framework tricks (this package) 'rest_framework_tricks', # ... )
文档
文档可在Read the Docs上找到。
主要功能和亮点
使用示例
嵌套序列化器
非关系型字段的嵌套序列化器。
我们的虚构 Book 模型包含以下(非关系型)Django 模型字段
title: CharField
description: TextField
summary: TextField
publication_date: DateTimeField
state: CharField(带选项)
isbn: CharField
price: DecimalField
pages: IntegerField
stock_count: IntegerField
在我们的 REST API 中,我们想使用嵌套序列化器将 Book 序列化器拆分为部分,以获得以下结构
{
"id": "",
"title": "",
"description": "",
"summary": "",
"publishing_information": {
"publication_date": "",
"isbn": "",
"pages": ""
},
"stock_information": {
"stock_count": "",
"price": "",
"state": ""
}
}
示例模型
此处与标准实现的不同之处在于,我们在 Book 模型级别声明了两个 NestedProxyField 字段,用于在 BookSerializer 序列化器中声明。
注意,这种更改不会导致模型更改(无需迁移等)。
必需导入
from django.db import models
from rest_framework_tricks.models.fields import NestedProxyField
模型定义
BOOK_PUBLISHING_STATUS_PUBLISHED = 'published'
BOOK_PUBLISHING_STATUS_NOT_PUBLISHED = 'not_published'
BOOK_PUBLISHING_STATUS_IN_PROGRESS = 'in_progress'
BOOK_PUBLISHING_STATUS_CHOICES = (
(BOOK_PUBLISHING_STATUS_PUBLISHED, "Published"),
(BOOK_PUBLISHING_STATUS_NOT_PUBLISHED, "Not published"),
(BOOK_PUBLISHING_STATUS_IN_PROGRESS, "In progress"),
)
BOOK_PUBLISHING_STATUS_DEFAULT = BOOK_PUBLISHING_STATUS_PUBLISHED
class Book(models.Model):
"""Book."""
title = models.CharField(max_length=100)
description = models.TextField(null=True, blank=True)
summary = models.TextField(null=True, blank=True)
publication_date = models.DateField()
state = models.CharField(max_length=100,
choices=BOOK_PUBLISHING_STATUS_CHOICES,
default=BOOK_PUBLISHING_STATUS_DEFAULT)
isbn = models.CharField(max_length=100, unique=True)
price = models.DecimalField(max_digits=10, decimal_places=2)
pages = models.PositiveIntegerField(default=200)
stock_count = models.PositiveIntegerField(default=30)
# List the fields for `PublishingInformationSerializer` nested
# serializer. This does not cause a model change.
publishing_information = NestedProxyField(
'publication_date',
'isbn',
'pages',
)
# List the fields for `StockInformationSerializer` nested serializer.
# This does not cause a model change.
stock_information = NestedProxyField(
'stock_count',
'price',
'state',
)
class Meta:
"""Meta options."""
ordering = ["isbn"]
def __str__(self):
return self.title
示例序列化器
首先,我们将 nested_proxy_field 属性添加到嵌套序列化器 PublishingInformationSerializer 和 StockInformationSerializer 的 Meta 类定义中。
然后我们定义我们的(主要)BookSerializer 类,它将被用作 BookViewSet 的 serializer_class。我们从 rest_framework_tricks.serializers.HyperlinkedModelSerializer 继承 BookSerializer,而不是从 Django REST framework 继承。还有一个可用的 rest_framework_tricks.serializers.ModelSerializer。
必需导入
from rest_framework import serializers
from rest_framework_tricks.serializers import (
HyperlinkedModelSerializer,
)
from .models import Book
定义序列化器
嵌套序列化器
class PublishingInformationSerializer(serializers.ModelSerializer):
"""Publishing information serializer."""
publication_date = serializers.DateField(required=False)
isbn = serializers.CharField(required=False)
pages = serializers.IntegerField(required=False)
class Meta:
"""Meta options."""
model = Book
fields = (
'publication_date',
'isbn',
'pages',
)
# Note, that this should be set to True to identify that
# this serializer is going to be used as `NestedProxyField`.
nested_proxy_field = True
嵌套序列化器
class StockInformationSerializer(serializers.ModelSerializer):
"""Stock information serializer."""
class Meta:
"""Meta options."""
model = Book
fields = (
'stock_count',
'price',
'state',
)
# Note, that this should be set to True to identify that
# this serializer is going to be used as `NestedProxyField`.
nested_proxy_field = True
用于 ViewSet 的主要序列化器
# Note, that we are importing the ``HyperlinkedModelSerializer`` from
# the `rest_framework_tricks.serializers`. Names of the serializers
# should match the names of model properties set with ``NestedProxyField``
# fields.
class BookSerializer(HyperlinkedModelSerializer):
"""Book serializer."""
publishing_information = PublishingInformationSerializer(required=False)
stock_information = StockInformationSerializer(required=False)
class Meta:
"""Meta options."""
model = Book
fields = (
'url',
'id',
'title',
'description',
'summary',
'publishing_information',
'stock_information',
)
示例 ViewSet
此处没有任何与标准实现的不同之处。
必需导入
from rest_framework.viewsets import ModelViewSet
from rest_framework.permissions import AllowAny
from .models import Book
from .serializers import BookSerializer
ViewSet 定义
class BookViewSet(ModelViewSet):
"""Book ViewSet."""
queryset = Book.objects.all()
serializer_class = BookSerializer
permission_classes = [AllowAny]
示例 OPTIONS 调用
OPTIONS /books/api/books/
HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
{
"name": "Book List",
"description": "Book ViewSet.",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
],
"actions": {
"POST": {
"id": {
"type": "integer",
"required": false,
"read_only": true,
"label": "ID"
},
"title": {
"type": "string",
"required": true,
"read_only": false,
"label": "Title",
"max_length": 100
},
"description": {
"type": "string",
"required": false,
"read_only": false,
"label": "Description"
},
"summary": {
"type": "string",
"required": false,
"read_only": false,
"label": "Summary"
},
"publishing_information": {
"type": "nested object",
"required": false,
"read_only": false,
"label": "Publishing information",
"children": {
"publication_date": {
"type": "date",
"required": false,
"read_only": false,
"label": "Publication date"
},
"isbn": {
"type": "string",
"required": false,
"read_only": false,
"label": "Isbn"
},
"pages": {
"type": "integer",
"required": false,
"read_only": false,
"label": "Pages"
}
}
},
"stock_information": {
"type": "nested object",
"required": false,
"read_only": false,
"label": "Stock information",
"children": {
"stock_count": {
"type": "integer",
"required": false,
"read_only": false,
"label": "Stock count"
},
"price": {
"type": "decimal",
"required": true,
"read_only": false,
"label": "Price"
},
"state": {
"type": "choice",
"required": false,
"read_only": false,
"label": "State",
"choices": [
{
"value": "published",
"display_name": "Published"
},
{
"value": "not_published",
"display_name": "Not published"
},
{
"value": "in_progress",
"display_name": "In progress"
}
]
}
}
}
}
}
}
无限嵌套深度
支持无限嵌套深度。
我们的虚构 Author 模型可以包含以下(非关系型)Django 模型字段
salutation: CharField
name: CharField
email: EmailField
birth_date: DateField
biography: TextField
phone_number: CharField
website: URLField
company: CharField
company_phone_number: CharField
company_email: EmailField
company_website: URLField
在我们的 REST API 中,我们可以使用嵌套序列化器将 Author 序列化器拆分为部分,以获得以下结构
{
"id": "",
"salutation": "",
"name": "",
"birth_date": "",
"biography": "",
"contact_information": {
"personal_contact_information": {
"email": "",
"phone_number": "",
"website": ""
},
"business_contact_information": {
"company": "",
"company_email": "",
"company_phone_number": "",
"company_website": ""
}
}
}
我们的模型定义如下(完整模型定义请参阅 高级用法示例)
class Author(models.Model):
"""Author."""
# ...
# List the fields for `PersonalContactInformationSerializer` nested
# serializer. This does not cause a model change.
personal_contact_information = NestedProxyField(
'email',
'phone_number',
'website',
)
# List the fields for `BusinessContactInformationSerializer` nested
# serializer. This does not cause a model change.
business_contact_information = NestedProxyField(
'company',
'company_email',
'company_phone_number',
'company_website',
)
# List the fields for `ContactInformationSerializer` nested
# serializer. This does not cause a model change.
contact_information = NestedProxyField(
'personal_contact_information',
'business_contact_information',
)
# ...
查看完整示例,请参阅 高级用法示例。
排序过滤器
为排序选项提供开发者友好的名称(例如,对于相关字段名称),以创建更好的API。
示例模型
此处没有任何与标准实现的不同之处。
必需导入
from django.db import models
模型定义
class Profile(models.Model):
"""Profile."""
user = models.ForeignKey('auth.User')
biography = models.TextField()
hobbies = models.TextField()
示例序列化器
此处没有任何与标准实现的不同之处。
必需导入
from rest_framework import serializers
from .models import Profile
定义序列化器
class ProfileSerializer(serializers.ModelSerializer):
"""Profile serializer."""
username = serializers.CharField(source='user.username', read_only=True)
full_name = serializers.SerializerMethodField()
email = serializers.CharField(source='user.email', read_only=True)
class Meta(object):
model = Profile
fields = (
'id',
'username',
'full_name',
'email',
'biography',
'hobbies',
)
def get_full_name(self, obj):
return obj.user.get_full_name()
示例 ViewSet
这里与标准实现唯一的区别是我们使用 rest_frameworks_tricks.filters.OrderingFilter 而不是 rest_framework.filters.OrderingFilter。
必需导入
from rest_framework.viewsets import ModelViewSet
from rest_framework.permissions import AllowAny
from rest_framework_tricks.filters import OrderingFilter
from .models import Profile
from .serializers import ProfileSerializer
ViewSet 定义
class ProfileViewSet(ModelViewSet):
"""Profile ViewSet."""
queryset = Profile.objects.all()
serializer_class = ProfileSerializer
permission_classes = [AllowAny]
filter_backends = (OrderingFilter,)
ordering_fields = {
'id': 'id',
'username': 'user__username',
'email': 'user__email',
'full_name': ['user__first_name', 'user__last_name']
}
ordering = ('id',)
示例 GET 调用
注意,我们的排序选项现在与序列化器(JSON响应)中的字段名称相等。这样,API 就更容易使用和理解。
GET /api/profile/?ordering=email
GET /api/profile/?ordering=-username
GET /api/profile/?ordering=full_name
GET /api/profile/?ordering=-full_name
受限的文件字段
示例模型
此处没有任何与标准实现的不同之处。
必需导入
from django.db import models
模型定义
class Profile(models.Model):
"""Upload."""
username = models.CharField(max_length=255)
resume = models.FileField()
示例序列化器
必需导入
from rest_framework import serializers
from rest_framework_tricks.fields import ConstrainedFileField
from .models import Upload
定义序列化器
class ProfileSerializer(serializers.ModelSerializer):
"""Profile serializer."""
username = serializers.CharField()
# Restrict resume to 5Mb
resume = ConstrainedFileField(max_upload_size=5_242_880)
class Meta(object):
model = Profile
fields = (
'id',
'username',
'resume',
)
演示
在本地运行演示
为了能够快速评估 django-rest-framework-tricks,已创建一个演示应用程序(带有快速安装程序)(在 Ubuntu/Debian 上运行,也可能在其他 Linux 系统上运行,但不保证)。按照以下说明在不到一分钟的时间内运行演示。
获取并运行最新的 rest_framework_tricks_demo_installer.sh 演示安装程序
wget -O - https://raw.github.com/barseghyanartur/django-rest-framework-tricks/master/examples/rest_framework_tricks_demo_installer.sh | bash
打开您的浏览器并测试应用程序。
http://127.0.0.1:8001/books/api/
测试
项目已涵盖测试。
要测试所有支持的 Python/Django 版本,请输入
tox
要针对特定环境进行测试,请输入
tox -e py39-django32
要仅测试您的工作环境,请输入
pytest -vvv
要在工作环境中运行单个测试,请输入
pytest -vvv src/rest_framework_tricks/tests/test_nested_proxy_field.py
pip install -r examples/requirements/test.txt
编写文档
请保持以下层次结构。
=====
title
=====
header
======
sub-header
----------
sub-sub-header
~~~~~~~~~~~~~~
sub-sub-sub-header
^^^^^^^^^^^^^^^^^^
sub-sub-sub-sub-header
++++++++++++++++++++++
sub-sub-sub-sub-sub-header
**************************
许可证
GPL-2.0-only OR LGPL-2.1-or-later
支持
有关任何问题,请联系作者部分提供的电子邮件。
项目详情
下载文件
下载您平台上的文件。如果您不确定选择哪个,请了解更多关于 安装软件包 的信息。
源分发
构建分发
django_rest_framework_tricks-0.2.14-py2.py3-none-any.whl 的哈希值
算法 | 散列摘要 | |
---|---|---|
SHA256 | 9eccf2a81487c22d368a8ffd06ba88dd928071cb8ae5145f9bdeb98e80f985de |
|
MD5 | 120ae09337514d8df2d98c2f2b20a870 |
|
BLAKE2b-256 | a259f5f02c7c15c62907f021184e2cc9865a511f06104fd9b7c061d59fba3d3f |