浅谈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标准日志模块logging的使用方法
Nov 01 Python
python实现的简单RPG游戏流程实例
Jun 28 Python
Python基于动态规划算法计算单词距离
Jul 25 Python
python调用OpenCV实现人脸识别功能
May 25 Python
Python实现的统计文章单词次数功能示例
Jul 08 Python
django之状态保持-使用redis存储session的例子
Jul 28 Python
Python进程,多进程,获取进程id,给子进程传递参数操作示例
Oct 11 Python
Python全局锁中如何合理运用多线程(多进程)
Nov 06 Python
python 实现目录复制的三种小结
Dec 04 Python
Python-opencv 双线性插值实例
Jan 17 Python
python 调整图片亮度的示例
Dec 03 Python
Django+Django-Celery+Celery的整合实战
Jan 20 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
求帮忙修改个php curl模拟post请求内容后并下载文件的解决思路
2015/09/20 PHP
理解PHP中的Session及对Session有效期的控制
2016/01/08 PHP
php获取开始与结束日期之间所有日期的方法
2016/11/29 PHP
javascript HTMLEncode HTMLDecode的完整实例(兼容ie和火狐)
2009/06/02 Javascript
JS等比例缩小图片尺寸的实例
2013/02/27 Javascript
jquery 定位input元素的几种方法小结
2013/07/28 Javascript
JQuery显示隐藏页面元素的方法总结
2015/04/16 Javascript
在其他地方你学不到的jQuery小贴士和技巧(欢迎收藏)
2016/01/20 Javascript
jquery trigger函数执行两次的解决方法
2016/02/29 Javascript
微信小程序 配置文件详细介绍
2016/12/14 Javascript
利用VUE框架,实现列表分页功能示例代码
2017/01/12 Javascript
基于jQuery中ajax的相关方法汇总(必看篇)
2017/11/08 jQuery
浅谈vue父子组件怎么传值
2018/07/21 Javascript
jquery 通过ajax请求获取后台数据显示在表格上的方法
2018/08/08 jQuery
使用D3.js构建实时图形的示例代码
2018/08/28 Javascript
小程序实现列表点赞功能
2018/11/02 Javascript
JavaScript ES6中的简写语法总结与使用技巧
2018/12/30 Javascript
Vue实现星级评价效果实例详解
2019/12/30 Javascript
JS判断数组四种实现方法详解
2020/06/29 Javascript
uniapp微信小程序实现一个页面多个倒计时
2020/11/01 Javascript
python实现多线程暴力破解登陆路由器功能代码分享
2015/01/04 Python
python使用selenium实现批量文件下载
2019/03/11 Python
PyQt 实现使窗口中的元素跟随窗口大小的变化而变化
2019/06/18 Python
Django如何自定义model创建数据库索引的顺序
2019/06/20 Python
pycharm重命名文件的方法步骤
2019/07/29 Python
Python 可变类型和不可变类型及引用过程解析
2019/09/27 Python
css3制作彩色边线3d立体按钮的示例(css3按钮)
2014/05/06 HTML / CSS
Ray-Ban雷朋美国官网:全球领先的太阳眼镜品牌
2016/07/20 全球购物
Cotton On南非:澳洲时尚平价品牌
2018/06/28 全球购物
可口可乐唇膏:Lip Smackers
2019/08/27 全球购物
个人求职简历的自我评价
2013/10/19 职场文书
计算机专业自荐信范文
2014/05/28 职场文书
学校安全教育月活动总结
2014/07/07 职场文书
2014年社区重阳节活动策划方案
2014/09/16 职场文书
司法局群众路线教育实践活动整改措施思想汇报
2014/10/13 职场文书
华为HarmonyOS3.0强在哪? 看看鸿蒙3.0这7个小功能
2023/01/09 数码科技