目的:
- 设计RESTful Web服务以与简单的SQLite数据库进行交互——对实体资源执行CRUD操作。
- 定义Web服务的需求,并了解每种HTTP方法和不同执行范围。
- 在Django中执行迁移以在数据库中创建所需的表来表示和持久化实体资源。
- 学习如何使用Django REST framework实现实体资源的序列化为和反序列化。
1,定义相关需求
假设一个开发团队正在开发适用于 iOS 和 Android 移动应用程序,并且需要RESTful Web服务来对实体执行CRUD操作。
但绝对不想使用模拟Web服务,也不想花时间选择和配置ORM,而是希望快速构建一个RESTful Web服务,并使其尽快准备好开始在移动应用程序中与之交互。尽管不需要将其投入生产环境,但希望实体资源够保存在最简单的关系数据库中。
Django REST framework
配合Django默认的SQLite数据库将使我们能够轻松完成这些任务。
现在开始我们的RESTful Web 服务的第一个版本。
首先,我们必须指定资源实体的要求,用以下属性或字段来描述一个toy实体:
- 一个唯一标识符
- 一个名称
- 一个详情描述
- 一个分类信息
- 一个表示玩具是否在在线商店的商店主页中存在的布尔值
- 一个包含玩具添加的日期和时间时间戳
在RESTful理念中,使用唯一 URI标识每个资源,我们将使用HTTP的统一接口。下面是用到的方法、使用范围和方法语义:
HTTP方法 | 作用范围 | 语义 | 描述 |
---|---|---|---|
GET | 单个实体资源 | 查询单个玩具信息 | 从http://localhost:8000/toys/{id} 查询单个玩具信息 |
GET | 实体资源集合 | 查询所有玩具信息 | 从http://localhost:8000/toys/ 查询所有玩具信息 |
POST | 实体资源集合 | 创建一个玩具信息 | 使用JSON 格式提交请求到http://localhost:8000/toys/ 以创建新toy。服务器将验证它是否为有效的toy,是则将其保留在数据库中,并返回201 Created 状态代码和相关的JSON正文。 |
PUT | 单个实体资源 | 修改一个玩具信息 | 使用JSON 格式提交HTTP请求到http://localhost:8000/toys/{id} 以更改toy信息,成功则返回200 OK 状态代码和JSON正文;如果没有为新toy提供所有必要的数据,则返回400 Bad Reques t状态代码;如果服务器找不到具有指定 ID 的toy,则仅返回404 Not Found 状态码。 |
DELETE | 单个实体资源 | 删除一个玩具信息 | 使用JSON 格式提交HTTP请求到http://localhost:8000/toys/{id} 以删除toy信息,成功则返回204 OK 状态代码;如果服务器找不到具有指定 ID 的toy,则返回404 Not Found t状态代码。 |
2,创建模型
描述一个toy实体:
toys/models.py:
from django.db import models
class Toy(models.Model):
created = models.DateTimeField(auto_now_add=True)
name = models.CharField(max_length=150, blank=False, default='')
description = models.CharField(max_length=250, blank=True, default='')
toy_category = models.CharField(max_length=200, blank=False, default='')
release_date = models.DateTimeField()
was_included_in_home = models.BooleanField(default=False)
class Meta:
ordering = ('name',)
def __str__(self):
return self.name
- 非常重要的是,模型默认会将未定义的
id
映射为pk
。
3,数据迁移
使用settings.py中默认数据库配置:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
准备创建数据库:
python manage.py makemigrations toys
- 将自动生成文件
toys/migrations/0001_initial.py
django ORM将根上一步的toys/migrations/0001_initial.py
来生成数据表。
执行数据迁移:
python manage.py migrate
- 这时才在项目根目录产生一个
db.sqlite3
数据库文件。
可以到http://www.sqlite.org/download.html下载安装sqlite并点sqlite.exe运行起来。执行命令来查看数据表:
sqlite3 db.sqlite3 ".tables"
输出如下:
toys_toy
这张表就用于数据的持久化存储了,它是由django的ORM
框架生成的,使用如下命令查看建表命令:
sqlite3 db.sqlite3 ".schema toys_toy"
输出:
关于其他数据表的说明:
当编写并发送一个CRUD请求到RESTful Web服务后,数据库就会执行类似于下面的操作:
sqlite3 db.sqlite3 "SELECT * FROM toys_toy ORDER BY name;"
4,序列化器
基础工作准备完了,接下来就需要进行Toy实体的序列化
和反序列化
,前提是需要为Toy创建一个序列化器类
具体就是创建rest_framework.serializers.Serializer
类的子类,并通过下面两过程进行序列化与反序列化:
- 序列化器是模型实例和Python原语之间的中介。
- 解析器和渲染器是Python原语与HTTP请求和响应之间的中介。
了解序列化器的工作原理非常重要,因为它是我们将要构建的所有RESTful Web服务的最重要组件之一。
使用上面那个类可能会重复一些在定义模型时使用的内容,但可以进行简化。目前暂时用着再说:
toys/serializers.py:
from rest_framework import serializers
from toys.models import Toy
class ToySerializer(serializers.Serializer):
pk = serializers.IntegerField(read_only=True)
name = serializers.CharField(max_length=150)
description = serializers.CharField(max_length=250)
release_date = serializers.DateTimeField()
toy_category = serializers.CharField(max_length=200)
was_included_in_home = serializers.BooleanField(required=False)
def create(self, validated_data):
return Toy.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.name = validated_data.get('name', instance.name)
instance.description = validated_data.get('description', instance.description)
instance.release_date = validated_data.get('release_date', instance.release_date)
instance.toy_category = validated_data.get('toy_category', instance.toy_category)
instance.was_included_in_home = validated_data.get('was_included_in_home', instance.was_included_in_home)
instance.save()
return instance
- 属性代表要序列化的字段
- 必须重写继承自Serializer的
create()
与update()
来定义如何创建以及更新一个toy实例 create()
通过validated_data
接受已经验证的数据,创建并返回基于它的实例update()
通过instance
接受一个已有的实例,通过validated_data
接受已经验证的数据,用后者内容更新前者内容,保存并返回新的的实例
5,完成序列化和反序列化
可以通过启动python交互式shell来测试已有的序列化功能:
python manage.py shell
先来导入所需要的stuff:
>>> from datetime import datetime
>>> from django.utils import timezone
>>> from django.utils.six import BytesIO
>>> from rest_framework.renderers import JSONRenderer
>>> from rest_framework.parsers import JSONParser
>>> from toys.models import Toy
>>> from toys.serializers import ToySerializer
创建两个toy实例:
>>> toy_release_date = timezone.make_aware(datetime.now(), timezone.get_current_timezone())
>>> toy1 = Toy(name='Snoopy talking action figure', description='Snoopy speaks five languages', release_d
ate=toy_release_date, toy_category='Action figures', was_included_in_home=False)
>>> toy1.save()
>>> toy2 = Toy(name='Hawaiian Barbie', description='Barbie loves Hawaii', release_date=toy_release_date,
toy_category='Dolls', was_included_in_home=True)
>>> toy2.save()
查看toys_toy表,刚刚保存的两个实例已经存入数据表了:
接下来就能查看到每个实例的具体属性了:
>>> print(toy1.created)
2020-09-21 17:59:09.346215+00:00
>>> print(toy1.was_included_in_home)
False
序列化——将模型实例转换为 Python 数据类型,并将序列化的数据呈现为JSON
格式:
>>> serializer_for_toy2 = ToySerializer(toy2) # 首先实例化序列化器
>>> print(serializer_for_toy2.data) #通过data属性获取数据
- 实例化序列化器实现序列化第一步。
json_renderer = JSONRenderer()
toy1_rendered_into_json = json_renderer.render(serializer_for_toy1.data) # 然后将序列化结果渲染为JSON格式完成序列化。
toy2_rendered_into_json = json_renderer.render(serializer_for_toy2.data)
print(toy1_rendered_into_json)
print(toy2_rendered_into_json)
- 将序列化结果渲染为
JSON
格式完成序列化。
输出:
反序列化——将呈现为JSON
格式的序列化数据解析为易于理解的python字典格式,然后转化为一个模型实例。
解析JSON数据:
json_string_for_new_toy = '{"name":"Clash Royale play set","description":"6 figures from Clash Royale", "release_date":"2017-10-09T12:10:00.776594Z","toy_category":"Playset","was_included_in_home":false}'
json_bytes_for_new_toy = bytes(json_string_for_new_toy, encoding="UTF-8")
stream_for_new_toy = BytesIO(json_bytes_for_new_toy)
parser = JSONParser()
parsed_new_toy = parser.parse(stream_for_new_toy) #首先是解析JSON数据
print(parsed_new_toy)
输出:
{
'name': 'Clash Royale play set',
'description': '6 figures from Clash Royale',
'release_date': '2017-10-09T12:10:00.776594Z',
'toy_category': 'Playset',
'was_included_in_home': False
}
将解析结果转为为django支持的模型数据并保存,完成反序列化:
new_toy_serializer = ToySerializer(data=parsed_new_toy) #然后通过序列化类完成序列化
if new_toy_serializer.is_valid():
toy3 = new_toy_serializer.save() #验证无误后存入数据库
print(toy3.name)
这个序列化和反序列化的过程还是优点复杂,同样放到后面来优化。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之家整理,本文链接:https://www.bmabk.com/index.php/post/98129.html