django restful framework 一对多方向更新数据库
django restful framework 序列化
案例: 一个网域domain可以绑定多台服务器主机assets, 但是一台服务器只能绑定一个网域. 数据模型之间关系适用于一对多.
一 . 数据模型: models
定义 assets 模型:
apps/assets/models/asset.py#!/usr/bin/env python
# -*- coding: utf-8 -*- import uuid
from django.db import models class Asset(models.Model): id = models.UUIDField(default=uuid.uuid4, primary_key=True)
ops_id = models.CharField(max_length=30, unique=True, null=True, blank=True, verbose_name=_('ops asset id'))
ip = models.GenericIPAddressField(max_length=32, verbose_name=_('IP'), db_index=True)
hostname = models.CharField(max_length=128, verbose_name=_('Hostname'))
domain = models.ForeignKey("assets.Domain", null=True, blank=True, related_name='assets', verbose_name=_("Domain"), on_delete=models.SET_NULL) # 使用Foreignkey关联外键
created_by = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Created by'))
date_created = models.DateTimeField(auto_now_add=True, null=True, blank=True, verbose_name=_('Date created'))
comment = models.TextField(max_length=128, default='', blank=True, verbose_name=_('Comment')) def __str__(self):
return '{0.hostname}({0.ip})'.format(self) class Meta:
verbose_name = _("Asset")
domain 模型如下:
apps/assets/models/domain.py
# -*- coding: utf-8 -*-
import uuid
from django.db import models
from django.utils.translation import ugettext_lazy as _
class Domain(models.Model):
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
name = models.CharField(max_length=128, unique=True, verbose_name=_('Name'))
comment = models.TextField(blank=True, verbose_name=_('Comment'))
date_created = models.DateTimeField(auto_now_add=True, null=True, verbose_name=_('Date created'))
class Meta:
verbose_name = _("Domain")
def __str__(self):
return self.name
- 模型说明
Assets 模型中有个
domain字段,使用ForeignKey关联Domain模型, 并指定related_name= assets, 表示在domain模型中,会隐藏一个assets字段. 在使用反向查找时(通过domain查assets)使用此字段
二. 序列化: serializers
序列化类用来对request/response参数进行校验. 这里使用
ModelSerializer代码:
apps/assets/serializers/domain.py# -*- coding: utf-8 -*- from rest_framework import serializers
from ..models import Domain class DomainBindAssetSerializer(serializers.ModelSerializer): class Meta:
model = Domain
fields = ['id','name','assets']
read_only_fields = ('id', 'name') def update(self, instance, validated_data):
instance.id = validated_data.get('id',instance.id)
instance.name = validated_data.get('name',instance.name)
instance.save()
instance.assets.set(validated_data.get('assets',instance.assets.all()))
return instance
代码解析
fields = ['id','name','assets']说明此序列化检验字段update方法为了绑定 接口更新字段, 特别注意, assets字段是隐藏字段,不能直接更新domain的assets字段, 需要使用domain.assets.set(object)- 最后返回domain实例
三, 视图: views
视图函数使用标准的 restful接口.
实现反向更新domain下的assets
代码:
apps/assets/api/domain.py# ~*~ coding: utf-8 ~*~ from common.permissions import IsOrgAdminOrAppUser
from common.utils import get_logger
from rest_framework import status
from rest_framework.generics import RetrieveUpdateDestroyAPIView
from rest_framework.views import Response from .. import serializers
from ..models import Domain, Gateway class DomainWithAssetsUpdateApi(RetrieveUpdateDestroyAPIView):
queryset = Domain.objects.all()
serializer_class = serializers.DomainBindAssetSerializer
permission_classes = ()
authentication_classes = () def get_object(self, pk):
try:
return Domain.objects.get(id=pk)
except Domain.DoesNotExist:
logger.error("domain id is not existed.")
False def get(self, request, *args, **kwargs):
"""query domain with assets"""
data = {"msg": '', 'result': None, 'code': None}
domain = self.get_object(kwargs.get('pk'))
try:
if not domain:
raise Exception("Domain not exists! Check url!")
serializer = serializers.DomainBindAssetSerializer(domain)
code = status.HTTP_200_OK
data['result'] = serializer.data
data['code'] = code
logger.info("Domain bind assets:{}".format(domain.assets))
except Exception as e:
code = status.HTTP_422_UNPROCESSABLE_ENTITY
data['msg'] = str(e)
data['code'] = code
logger.error(str(e))
finally:
return Response(data=data, status=code) def put(self, request, *args, **kwargs):
"""bind assets to domain"""
data = {"msg": '', 'result': None, 'code': None} domain = self.get_object(kwargs.get("pk", None))
if not domain:
code = status.HTTP_404_NOT_FOUND
data['msg'] = "Domain not exists, check url!"
data['code'] = code
return Response(data=data, status=code) try:
serializer = serializers.DomainBindAssetSerializer(data=request.data, instance=domain, partial=True)
if serializer.is_valid():
serializer.save()
code = status.HTTP_202_ACCEPTED
data['result'] = serializer.data
data['code'] = code
else:
code = status.HTTP_422_UNPROCESSABLE_ENTITY
data['msg'] = serializer.errors
data['code'] = code
except Exception as e:
code = 500
data['msg'] = str(e)
data['code'] = code
logger.error("Assets bind domain occur error:{}".format(str(e)))
finally:
return Response(data=data, status=code)
代码说明
- 接口只实现: 查询(get), 更新(put)接口
- get接口通过url解析当前查询domain.id, 使用
DomainBindAssetSerializer反序列化查询的结果并返回给接口. - put接口相对复杂一下:
- 首先将使用
DomainBindAssetSerializer将 请求的字段request.data进行序列化,partial=True表示允许只更新要修改的字段. - 将解析的结果进行校验
- 如果正常,使用save(),即调用
DomainBindAssetSerializer.update()的方法对数据进行更新
- 首先将使用
四, 路由: urls
定义访问路由
代码如下:
apps/assets/urls/api_urls.py# coding:utf-8
from django.urls import path
from rest_framework_bulk.routes import BulkRouter
from rest_framework_nested import routers from .. import api app_name = 'assets' router = BulkRouter()
router.register(r'assets', api.AssetViewSet, 'asset')
router.register(r'domain', api.DomainViewSet, 'domain') urlpatterns = [
...
path('domain/<uuid:pk>/assets/',api.DomainWithAssetsUpdateApi.as_view(), name='domain-assets-update'),
...
] urlpatterns += router.urls + cmd_filter_router.urls
五. 测试 : test
测试使用postman
- get 查询接口:
/api/assets/v1/domain/e5d52f79-42fc-4147-8c76-296bb7cae37b/assets/
// 返回格式如下
{
"msg": "",
"result": {
"id": "e5d52f79-42fc-4147-8c76-296bb7cae37b",
"name": "mao",
"assets": [
"323fff34-1baf-46b8-9784-cb2fc6046966",
"5c65c106-1750-47de-a2f3-031c07996eda",
"940cd754-267a-4531-88cd-e4cc248cc936"
]
},
"code": 200
}
- put 更新接口:
/api/assets/v1/domain/e5d52f79-42fc-4147-8c76-296bb7cae37b/assets/
// request data
{
"assets": [
"323fff34-1baf-46b8-9784-cb2fc6046966",
"5c65c106-1750-47de-a2f3-031c07996eda",
]
}
//response data
{
"msg": "",
"result": {
"id": "e5d52f79-42fc-4147-8c76-296bb7cae37b",
"name": "mao",
"assets": [
"323fff34-1baf-46b8-9784-cb2fc6046966",
"5c65c106-1750-47de-a2f3-031c07996eda"
]
},
"code": 202
}
django restful framework 一对多方向更新数据库的更多相关文章
- 3- vue django restful framework 打造生鲜超市 - model设计和资源导入
3- vue django restful framework 打造生鲜超市 - model设计和资源导入 使用Python3.6与Django2.0.2(Django-rest-framework) ...
- 在django restful framework中设置django model的property
众所周知,在django的model中,可以某些字段设置@property和setter deleter getter,这样就可以在存入数据的时候进行一些操作,具体原理请参见廖雪峰大神的博客https ...
- 4- vue django restful framework 打造生鲜超市 -restful api 与前端源码介绍
4- vue django restful framework 打造生鲜超市 -restful api 与前端源码介绍 天涯明月笙 关注 2018.02.20 19:23* 字数 762 阅读 135 ...
- 1- vue django restful framework 打造生鲜超市
Vue+Django REST framework实战 使用Python3.6与Django2.0.2(Django-rest-framework)以及前端vue开发的前后端分离的商城网站 项目支持支 ...
- django restful framework教程大全
一. 什么是RESTful REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移” REST从资源的角 ...
- Django restful Framework 之Requests and Response 方法
前言: 本章主要介绍REST framework 内置的必要的功能. Request objects Response objects Status codes Wrapping API views ...
- 7- vue django restful framework 打造生鲜超市 -商品类别数据展示(上)
Vue+Django REST framework实战 搭建一个前后端分离的生鲜超市网站 Django rtf 完成 商品列表页 并没有将列表页的数据json 与前端的页面展示结合起来 讲解如果将dr ...
- 6- vue django restful framework 打造生鲜超市 -完成商品列表页(下)
Vue+Django REST framework实战 搭建一个前后端分离的生鲜超市网站 Django rtf 完成 商品列表页下 drf中的request和response drf对于django的 ...
- Django restful Framework 之序列化与反序列化
1. 首先在已建好的工程目录下新建app命名为snippets,并将snippets app以及rest_framework app加到工程目录的 INSTALLED_APPS 中去,具体如下: IN ...
随机推荐
- 知否知否,VS Code 不止开源
VS Code, 昨夜始于“开源”,如今“开源”深处渡. 读者看到这句话,也许会有疑惑,为什么两个“开源”都加上了双引号? 其实是笔者有意为之,因为这个两个“开源”的意义有着很大的差别,第一个“开源” ...
- OPTIONS 请求引发的分析
阅读提纲: 为什么会出现 OPTIONS 请求? 什么情况下会出现 OPTIONS 请求? OPTIONS 请求会发送什么内容? 跨域前端访问后端时,所有的 Ajax HTTP 请求都会先发送一个 O ...
- Keepalived+LVS DR模式高可用架构实践
Keepalived最初是为LVS设计,专门监控各服务器节点的状态(LVS不带健康检查功能,所以使用keepalived进行健康检查),后来加入了VRRP(虚拟路由热备协议(Virtual Route ...
- 主席树学习笔记(静态区间第k大)
题目背景 这是个非常经典的主席树入门题——静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个整数构成的序列,将对于指定的闭区间查询其区间内的第K小值. 输入输出 ...
- 数据结构--树链剖分准备之LCA
有关LCA的模板题 传送门 题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和 ...
- Android so 文件
要点 不同的 CPU 架构需要不同的 so 文件 NDK平台不是后向兼容的,而是前向兼容的. ABI 的概念,每一个 Cpu架构对应一个 ABI(Application Binary Interfac ...
- Linux学习(推荐学习资源)——保持更新
1. 介绍 Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和Unix的多用户.多任务.支持多线程和多CPU的操作系统.它能运行主要的Unix工具软件.应用程序和网络协议. ...
- JVM 中你不得不知的一些参数
有的同学虽然写了一段时间 Java 了,但是对于 JVM 却不太关注.有的同学说,参数都是团队规定好的,部署的时候也不用我动手,关注它有什么用,而且,JVM 这东西,听上去就感觉很神秘很高深的样子,还 ...
- R画图——分屏
最近项目需求,用R画了一个九宫格的图,第一次画,将简化后的脚本呈现一下,不是有人说,既然做了,那就摆出来吧. *中文行为说明: args <- commandArgs(T) 调用命令行读取 fi ...
- SqlServer2005 查询 第六讲 null
今天们来讲sql命令中的这个null参数 null null: 可以理解成[没有值,空值]的意思 注意以下几点 --1.零和null是不一样的,null表示空值,而零表示的一个确定的值 --2.nul ...