浅谈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 文件和输入输出小结
Oct 09 Python
Python中SOAP项目的介绍及其在web开发中的应用
Apr 14 Python
python实现的简单FTP上传下载文件实例
Jun 30 Python
Python的Tornado框架的异步任务与AsyncHTTPClient
Jun 27 Python
如何利用Fabric自动化你的任务
Oct 20 Python
python算法题 链表反转详解
Jul 02 Python
Python用字典构建多级菜单功能
Jul 11 Python
python中列表的切片与修改知识点总结
Jul 23 Python
django创建简单的页面响应实例教程
Sep 06 Python
Keras:Unet网络实现多类语义分割方式
Jun 11 Python
重构Python代码的六个实例
Nov 25 Python
pd.DataFrame中的几种索引变换的实现
Jun 16 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
推荐10个提供免费PHP脚本下载的网站
2014/12/31 PHP
php注册审核重点解析(数据访问)
2017/05/23 PHP
thinkphp5 加载静态资源路径与常量的方法
2017/12/24 PHP
laravel withCount 统计关联数量的方法
2019/10/10 PHP
Add a Picture to a Microsoft Word Document
2007/06/15 Javascript
jQuery实现自动调整字体大小的方法
2015/06/15 Javascript
js代码验证手机号码和电话号码是否合法
2015/07/30 Javascript
纯CSS3代码实现滑动开关效果
2015/08/19 Javascript
使用JQuery中的trim()方法去掉前后空格
2016/09/16 Javascript
Vue框架中正确引入JS库的方法介绍
2017/07/30 Javascript
JavaScript数据结构与算法之队列原理与用法实例详解
2017/11/22 Javascript
vue中mint-ui的使用方法
2018/04/04 Javascript
微信小程序中换行空格(多个空格)写法详解
2018/07/10 Javascript
JS/CSS实现字符串单词首字母大写功能
2019/09/03 Javascript
Node.js开发之套接字(socket)编程入门示例
2019/11/05 Javascript
用map函数来完成Python并行任务的简单示例
2015/04/02 Python
Python随机生成信用卡卡号的实现方法
2015/05/14 Python
python中的全局变量用法分析
2015/06/09 Python
python轻松查到删除自己的微信好友
2016/01/10 Python
python3安装pip3(install pip3 for python 3.x)
2018/04/03 Python
python使用插值法画出平滑曲线
2018/12/15 Python
django ModelForm修改显示缩略图 imagefield类型的实例
2019/07/28 Python
flask开启多线程的具体方法
2020/08/02 Python
美国办公用品折扣网站:Shoplet.com
2019/11/24 全球购物
主要的Ajax框架都有什么
2013/11/14 面试题
社区端午节活动方案
2014/01/28 职场文书
干部现实表现材料
2014/02/13 职场文书
婚礼主持结束词
2014/03/13 职场文书
影视广告专业求职信
2014/09/02 职场文书
纪检干部个人对照检查材料
2014/09/23 职场文书
2015年春节标语口号
2014/12/09 职场文书
项目投资意向书范本
2015/05/09 职场文书
公司周年庆典致辞
2015/07/30 职场文书
读《解忧杂货店》有感:请相信一切都是最好的安排
2019/11/07 职场文书
Win11安全功能升级:内置防网络钓鱼功能
2022/04/08 数码科技
Python first-order-model实现让照片动起来
2022/06/25 Python