浅谈django不使用restframework自定义接口与使用的区别


Posted in Python onJuly 15, 2020

django可以使用restframework快速开发接口,返回前端所需要的json数据,但是有时候利用restframework开发的接口并不能满足所有的需求,这时候就需要自己手动开发接口,也就是将需要用到的某些对象转化为需要使用的json数据,今天记录一下django自己定义接口的一种方法与思路

假设我们定义三张数据表,分别是问卷,问题,选项。一张问卷包含不同的问题,一个问题可以设置不同的选项,自定义的接口可以实现查看所有或单个问卷的标题与id,可以查看所有或单个问题的所属问卷,问题标题,问卷的选项。

1.定义我们需要的模型类,并且在对应的模型类中定义对应的将对象转化为字典的函数

from django.db import models
 
class Questionnaire(models.Model):
 '''问卷'''
 title = models.CharField('标题',max_length=100)
 class Meta:
 verbose_name_plural = '所有问卷'
 def questionnaire_to_dict(self):
 '''把questionnaire对象转化为字典'''
 return dict(questionnaire_id=self.id,title=self.title,questions=[question.question_to_dict() for question in self.questions.all()])
 def __str__(self):
 return self.title
 
class Question(models.Model):
 '''问题'''
 #所属问卷
 questionnaire = models.ForeignKey(Questionnaire,verbose_name='所属问卷',related_name='questions')
 #问题标题
 title = models.CharField('问题',max_length=150)
 #是否是多选
 is_checkbox = models.BooleanField('是否多选',default=False,help_text='是否是多选问题')
 class Meta:
 verbose_name_plural = '问题'
 
 def question_to_dict(self):
 '''把question对象转化为字典'''
 return dict(title=self.title,choice=[choice.choice_to_dict() for choice in self.choices.all()],
   is_checkbox=self.is_checkbox,questionnaire_id=self.questionnaire.id)
 
 def __str__(self):
 return self.title
 
class Choice(models.Model):
 '''选项'''
 #所属的问题
 question = models.ForeignKey(Question,verbose_name='所属问题',related_name='choices')
 content = models.CharField('选项内容',max_length=150)
 
 class Meta:
 verbose_name_plural = '问题选项'
 
 def choice_to_dict(self):
 '''把choice对象转化为字典'''
 #选项id,选项所属的问题id,选项内容
 return dict(id=self.id,question_id=self.question.id,content=self.content)
 
 def __str__(self):
 return self.content

将你需要转化为字典的字段添加进函数中,当指定外键时,"related_name"为指定关系名,用于反向查找,比如通过问卷查找问题,但是问卷模型类中没有question字段,但是question类中指定questionnaire外键时指定了关系名related_name='questions'所以可以通过self.questions.all()来查看当前问卷的所有问题。

2.定义类视图

(1)定义查看所有问卷与添加问卷的类视图

from question.models import Question,Questionnaire,Choice
from django.http import JsonResponse
from django.views import View
import json
class Questionnaires(View):
 def get(self,request):
 #获取所有问卷
 data = []
 questionnaires = Questionnaire.objects.all() #获取所有的问卷类
 for questionnaire in questionnaires:
  data.append(questionnaire.questionnaire_to_dict())
 return JsonResponse({'data':data})
 
 def post(self,request,*args,**kwargs):
 data = json.loads(request.body.decode())
 questionnaire = Questionnaire(title=data.get('title'))
 questionnaire.save()
 return JsonResponse({'msg':'success save'})
 
class QuestionnaireDetail(View):
 '''获取id为questionnaire_id的问卷'''
 def get(self,request,questionnaire_id):
 questionnaire = Questionnaire.objects.get(id=questionnaire_id)
 data = questionnaire.questionnaire_to_dict()
 return JsonResponse(data)

这里继承View类自己定义get方法与post方法处理请求,首先获取到所有的问卷对象,在将每一个问卷对象通过自定义的函数转化为字典,最后返回json数据,同样处理post请求添加问卷时,首先获取到问卷的标题,然后实例化一个问卷的对象,再将问卷对象保存。获取单个问卷对象通过传递的id查看到指定的问卷对象,再通过自定义的函数将对象转化为字典数据,最后返回单个问卷对象的json数据。

(2)获取所有问题对象数据,及添加问题对象

class Questions(View):
 def get(self,request):
 #查询所有问题
 questions_set = Question.objects.all()
 #把question_set转化为字典
 data = []
 for question in questions_set:
  data.append(question.question_to_dict())
 #把字典数据当做json返回
 return JsonResponse({'data':data})
 def post(self,request,*args,**kwargs):
 '''假设前端通过post传过来一个json数据'''
 #把request中的json转化为python对象
 data = json.loads(request.body.decode())
 #抽取数据
 questionnaire_id = data.get('questionnaire_id')
 title = data.get('title')
 is_checkbox = data.get('is_checkbox')
 # 获取questionnaire_id对应的对象
 questionnaire = Questionnaire.objects.get(id=questionnaire_id)
 #创建Question实例
 question = Question(title=title,is_checkbox=is_checkbox,questionnaire=questionnaire)
 question.save()
 #创建choice对象
 choices = data.get('choice')
 for c in choices:
  choice = Choice()
  choice.content = c
  choice.question = question
  choice.save()
 return JsonResponse({"msg":"success save"})

通过get请求来获取所有问题的json数据,通过post方法从前端获取到传递过来的json数据,将其转化为对象并保存。并在保存成功之后返回提示信息。

(3)通过get,put,delete处理单个问题对象

class QuestionDetail(View):
 def delete(self,request,question_id):
 question = Question.objects.get(id=question_id)
 question.delete()
 
 def put(self,request,question_id):
 #获取前端put的数据
 data = json.loads(request.body.decode())
 title = data.get('title')
 #获取question对象
 question = Question.objects.get(id=question_id)
 question.title = title
 question.save()
 return JsonResponse({'msg':'modify success'})
 
 def get(self,request,question_id):
 question = Question.objects.get(id=question_id)
 data = question.question_to_dict()
 return JsonResponse(data)

这里难点是使用put方法修改某个对象的数据,使用put请求,将需要修改的数据写成json格式,并把修改后的数据重新赋值给对象,然后保存。

3.配置url,调用接口

from django.conf.urls import url
from question.views import Questions,Questionnaires,QuestionDetail,QuestionnaireDetail
urlpatterns = [
 url(r'^questions/$',Questions.as_view(),name='questions'),
 url(r'^questionnaire/(?P<questionnaire_id>\d+)/$',QuestionnaireDetail.as_view(),name='questionnaire'),
 url(r'^questionnaires/$',Questionnaires.as_view(),name='questionnaires'),
 
 url(r'^question/(?P<question_id>\d+)/$',QuestionDetail.as_view(),name='question'),
]

同样,我们可以使用restframework来快速开发接口,下面是使用restframework来开发接口的代码

1.创建对应的序列化类

from rest_framework import serializers
from question.models import Question,Questionnaire,Choice
 
class QuestionnaireSerializer(serializers.ModelSerializer):
 class Meta:
 model = Questionnaire
 fields = ('title',)
 
class QuestionSerializer(serializers.ModelSerializer):
 class Meta:
 model = Question
 fields = ('title','is_checkbox','questionnaire')
 
class ChoiceSerializer(serializers.ModelSerializer):
 class Meta:
 model = Choice
 fields = ('content','question')

使用这些序列化类来序列化我们需要的字段

2.定义类视图

class QuestionnaireList(APIView):
 def get(self,request):
 questionnaire = Questionnaire.objects.all()
 serializer = QuestionnaireSerializer(questionnaire,many=True)
 return Response(serializer.data)
 
 def post(self,request):
 serializer = QuestionnaireSerializer(data=request.data)
 if serializer.is_valid():
  serializer.save()
  return Response(serializer.data)
 return Response(serializer.errors)
 
class Questionnaire_Detail(APIView):
 def get_object(self,pk):
 try:
  return Questionnaire.objects.get(pk=pk)
 except Questionnaire.DoesNotExist:
  raise Http404
 def get(self,request,pk):
 questionnaire = self.get_object(pk)
 serializer = QuestionnaireSerializer(questionnaire)
 return Response(serializer.data)
 
 def put(self,request,pk):
 questionnaire = self.get_object(pk)
 serializer = QuestionSerializer(questionnaire,data=request.data)
 if serializer.is_valid():
  serializer.save()
  return Response(serializer.data)
 return Response(serializer.errors)
 
 def delete(self,request,pk):
 questionnaire = self.get_object(pk)
 questionnaire.delete()
 return Response(status=status.HTTP_204_NO_CONTENT)
 
class QuestionList(APIView):
 def get(self,request):
 question = Question.objects.all()
 serializer = QuestionSerializer(question,many=True)
 return Response(serializer.data)
 
 def post(self,request):
 serializer = QuestionSerializer(data=request.data)
 if serializer.is_valid():
  serializer.save()
  return Response(serializer.data)
 return Response(serializer.errors)

3.配置url

from django.conf.urls import url
from question.views import Questionnaire_Detail,QuestionnaireList,QuestionList
urlpatterns = [
 url(r'^questions/$',QuestionList.as_view(),name='questions'),
 url(r'^questionnaire/(?P<pk>\d+)/$',Questionnaire_Detail.as_view(),name='questionnaire'),
 url(r'^questionnaires/$',QuestionnaireList.as_view(),name='questionnaires'),
]

这里我只定义了获取所有问卷,单个问卷及所有问题的类,使用restframework开发接口虽然快速,代码易懂,但是它的缺点在于通过序列化类只能返回这个模型类本身的字段,并不能返回它所关联的外键属性的字段,要想获取其他关联模型类的数据就得定义另外的类视图,那么对应的url也需要配置。但是同样它的好处在于快速,代码简洁易懂,只不过是获取不同模型类的数据需要定义不同的接口,不能像自定义接口那样定义一个接口可以获得其他模型类的数据。

以上这篇浅谈django不使用restframework自定义接口与使用的区别就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python中的赋值、浅拷贝、深拷贝介绍
Mar 09 Python
利用一个简单的例子窥探CPython内核的运行机制
Mar 30 Python
Python生成8位随机字符串的方法分析
Dec 05 Python
Python自动化运维之IP地址处理模块详解
Dec 10 Python
python实现Windows电脑定时关机
Jun 20 Python
Python docx库用法示例分析
Feb 16 Python
图文详解python安装Scrapy框架步骤
May 20 Python
django如何通过类视图使用装饰器
Jul 24 Python
Python+opencv+pyaudio实现带声音屏幕录制
Dec 23 Python
Tensorflow 多线程与多进程数据加载实例
Feb 05 Python
Python OpenCV中的numpy与图像类型转换操作
Dec 11 Python
如何使用python-opencv批量生成带噪点噪线的数字验证码
Dec 21 Python
浅析Python 条件控制语句
Jul 15 #Python
python中如何设置代码自动提示
Jul 15 #Python
PyTorch实现重写/改写Dataset并载入Dataloader
Jul 14 #Python
python实现将中文日期转换为数字日期
Jul 14 #Python
Python实时监控网站浏览记录实现过程详解
Jul 14 #Python
python3 中时间戳、时间、日期的转换和加减操作
Jul 14 #Python
python转化excel数字日期为标准日期操作
Jul 14 #Python
You might like
PHP5中的this,self和parent关键字详解教程
2007/03/19 PHP
PHP实现发送邮件的方法(基于简单邮件发送类)
2015/12/17 PHP
Yii使用smsto短信接口的函数demo示例
2016/07/13 PHP
监控 url fragment变化的js代码
2010/04/19 Javascript
jQuery学习笔记 操作jQuery对象 CSS处理
2012/09/19 Javascript
JS随即打乱数组实现代码
2012/12/03 Javascript
JS图片无缝、平滑滚动代码
2014/03/11 Javascript
使用JavaScript判断图片是否加载完成的三种实现方式
2014/05/04 Javascript
Node.js中使用mongoskin操作mongoDB实例
2014/09/28 Javascript
jQuery插件windowScroll实现单屏滚动特效
2015/07/14 Javascript
JS实现的竖向折叠菜单代码
2015/10/21 Javascript
Sort()函数的多种用法
2016/03/20 Javascript
使用jquery获取url以及jquery获取url参数的实现方法
2016/05/25 Javascript
js控制按钮,防止频繁点击响应的实例
2017/02/15 Javascript
Javascript中click与blur事件的顺序详析
2017/04/25 Javascript
Bootstrap Tree View简单而优雅的树结构组件实例解析
2017/06/15 Javascript
详解Vue用自定义指令完成一个下拉菜单(select组件)
2017/10/31 Javascript
[47:43]Alliance vs KG 2019国际邀请赛小组赛 BO2 第一场 8.16
2019/08/18 DOTA
python 文件和路径操作函数小结
2009/11/23 Python
Django中处理出错页面的方法
2015/07/15 Python
python基于phantomjs实现导入图片
2016/05/13 Python
python中安装模块包版本冲突问题的解决
2017/05/02 Python
Python实现自动为照片添加日期并分类的方法
2017/09/30 Python
利用信号如何监控Django模型对象字段值的变化详解
2017/11/27 Python
修复CentOS7升级Python到3.6版本后yum不能正确使用的解决方法
2018/01/26 Python
Ubuntu下使用python读取doc和docx文档的内容方法
2018/05/08 Python
python实现两张图片拼接为一张图片并保存
2019/07/16 Python
CSS3实现精美横向滚动菜单按钮
2017/04/14 HTML / CSS
美国男士和女士奢侈品折扣手表购物网站:Certified Watch Store
2018/06/13 全球购物
运动会广播稿50字-100字
2014/10/11 职场文书
档案接收函格式
2015/01/30 职场文书
辩护词范文大全
2015/05/21 职场文书
2015年学生资助工作总结
2015/05/25 职场文书
车位出租协议书范本
2016/03/19 职场文书
如何使用Python对NetCDF数据做空间相关分析
2021/04/21 Python
Windows安装Anaconda3的方法及使用过程详解
2021/06/11 Python