浅谈django不使用restframework自定义接口与使用的区别
作者:学习真的很有用 发布时间:2023-11-24 09:44:02
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也需要配置。但是同样它的好处在于快速,代码简洁易懂,只不过是获取不同模型类的数据需要定义不同的接口,不能像自定义接口那样定义一个接口可以获得其他模型类的数据。
来源:https://blog.csdn.net/WanYu_Lss/article/details/81748398
猜你喜欢
- “用户体验”作为舶来品在国内风靡已经有几个年头了,而且从目前情况来看仍旧会继续风靡一段时间。当某产品发布会上,发言人张口闭口就
- /** * 截取字符串 len为字节长度 * @param str * @param len * @return * @throws Uns
- 本文实例讲述了Python使用内置json模块解析json格式数据的方法。分享给大家供大家参考,具体如下:Python中解析json字符串非
- python清空命令行 !有时我们在命令行上运行一些代码时,觉得有些冗余了,可以通过以下代码进行清除命令行上的代码。import osdef
- 今天突然想起做一个当鼠标经过<a/>时,会发出声音Js代码如下: <script type="text
- 在工作之余抽了点时间写了一下这个,在ie6-ie7-ff下显示位置基本都一致了。(发现demo页面用栅格线做背景,调试还真的容易得多 。热力
- 发现错误利用Python库xlrd中的xlrd.open_workbook()函数读取自定义xlsx表格文件时出错如下:Traceback
- Python是一个脚本语言,被解释器解释执行。它的发布方式:.py文件:对于开源项目或者源码没那么重要的,直接提供源码,需要使用者自行安装P
- 区块链中的共识算法在比特币公链架构解析中,就曾提到过为了实现去中介化的设计,比特币设计了一套共识协议,并通过此协议来保证系统的稳定性和防攻击
- 本文实例讲述了python安装cx_Oracle模块常见问题与解决方法。分享给大家供大家参考,具体如下:安装或使用cx_Oracle时,需要
- python2.7中 集成了json的处理(simplejson),但在实际应用中,从mysql查询出来的数据,通常有日期格式,这时候,会报
- Python IDLE Subprocess Connection Error的解决方法今天准备运行一个Python 文件时,IDLE突然报
- 1、把这段拷到DW里,存成HTML文件。<HTML><HEAD><TITLE>move backgrou
- 本文实例讲述了Python使用add_subplot与subplot画子图操作。分享给大家供大家参考,具体如下:子图:就是在一张figure
- 目录一,python介绍二.python的安装程序三、变量python基础部分学习一,python介绍python的创始人为吉多·范罗苏姆(
- 动态变量名赋值在使用 tkinter 时需要动态生成变量,如动态生成 var1...var10 变量。使用 exec 动态赋值exec 在
- 注:IE8以前的版本均不支持该特性为了向文档中插入生成内容,可以使用:before与:after伪元素。如,我想在所有链接的后面加上&quo
- 前言Python 相对导入与绝对导入,这两个概念是相对于包内导入而言的。包内导入即是包内的模块导入包内部的模块。Python import
- Semantics可翻译为语义的(学),它是Html/Xhtml是否真正符合标准的重要一环。Jorux在这和大家讨论一些自己的观点,如有不妥
- 这篇文章主要介绍了python标识符命名规范原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友