淺談django不使用restframework自定義接口與使用的區(qū)別
django可以使用restframework快速開(kāi)發(fā)接口,返回前端所需要的json數(shù)據(jù),但是有時(shí)候利用restframework開(kāi)發(fā)的接口并不能滿(mǎn)足所有的需求,這時(shí)候就需要自己手動(dòng)開(kāi)發(fā)接口,也就是將需要用到的某些對(duì)象轉(zhuǎn)化為需要使用的json數(shù)據(jù),今天記錄一下django自己定義接口的一種方法與思路
假設(shè)我們定義三張數(shù)據(jù)表,分別是問(wèn)卷,問(wèn)題,選項(xiàng)。一張問(wèn)卷包含不同的問(wèn)題,一個(gè)問(wèn)題可以設(shè)置不同的選項(xiàng),自定義的接口可以實(shí)現(xiàn)查看所有或單個(gè)問(wèn)卷的標(biāo)題與id,可以查看所有或單個(gè)問(wèn)題的所屬問(wèn)卷,問(wèn)題標(biāo)題,問(wèn)卷的選項(xiàng)。
1.定義我們需要的模型類(lèi),并且在對(duì)應(yīng)的模型類(lèi)中定義對(duì)應(yīng)的將對(duì)象轉(zhuǎn)化為字典的函數(shù)
from django.db import models
class Questionnaire(models.Model):
'''問(wèn)卷'''
title = models.CharField('標(biāo)題',max_length=100)
class Meta:
verbose_name_plural = '所有問(wèn)卷'
def questionnaire_to_dict(self):
'''把questionnaire對(duì)象轉(zhuǎn)化為字典'''
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):
'''問(wèn)題'''
#所屬問(wèn)卷
questionnaire = models.ForeignKey(Questionnaire,verbose_name='所屬問(wèn)卷',related_name='questions')
#問(wèn)題標(biāo)題
title = models.CharField('問(wèn)題',max_length=150)
#是否是多選
is_checkbox = models.BooleanField('是否多選',default=False,help_text='是否是多選問(wèn)題')
class Meta:
verbose_name_plural = '問(wèn)題'
def question_to_dict(self):
'''把question對(duì)象轉(zhuǎn)化為字典'''
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):
'''選項(xiàng)'''
#所屬的問(wèn)題
question = models.ForeignKey(Question,verbose_name='所屬問(wèn)題',related_name='choices')
content = models.CharField('選項(xiàng)內(nèi)容',max_length=150)
class Meta:
verbose_name_plural = '問(wèn)題選項(xiàng)'
def choice_to_dict(self):
'''把choice對(duì)象轉(zhuǎn)化為字典'''
#選項(xiàng)id,選項(xiàng)所屬的問(wèn)題id,選項(xiàng)內(nèi)容
return dict(id=self.id,question_id=self.question.id,content=self.content)
def __str__(self):
return self.content
將你需要轉(zhuǎn)化為字典的字段添加進(jìn)函數(shù)中,當(dāng)指定外鍵時(shí),"related_name"為指定關(guān)系名,用于反向查找,比如通過(guò)問(wèn)卷查找問(wèn)題,但是問(wèn)卷模型類(lèi)中沒(méi)有question字段,但是question類(lèi)中指定questionnaire外鍵時(shí)指定了關(guān)系名related_name='questions'所以可以通過(guò)self.questions.all()來(lái)查看當(dāng)前問(wèn)卷的所有問(wèn)題。
2.定義類(lèi)視圖
(1)定義查看所有問(wèn)卷與添加問(wèn)卷的類(lèi)視圖
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):
#獲取所有問(wèn)卷
data = []
questionnaires = Questionnaire.objects.all() #獲取所有的問(wèn)卷類(lèi)
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的問(wèn)卷'''
def get(self,request,questionnaire_id):
questionnaire = Questionnaire.objects.get(id=questionnaire_id)
data = questionnaire.questionnaire_to_dict()
return JsonResponse(data)
這里繼承View類(lèi)自己定義get方法與post方法處理請(qǐng)求,首先獲取到所有的問(wèn)卷對(duì)象,在將每一個(gè)問(wèn)卷對(duì)象通過(guò)自定義的函數(shù)轉(zhuǎn)化為字典,最后返回json數(shù)據(jù),同樣處理post請(qǐng)求添加問(wèn)卷時(shí),首先獲取到問(wèn)卷的標(biāo)題,然后實(shí)例化一個(gè)問(wèn)卷的對(duì)象,再將問(wèn)卷對(duì)象保存。獲取單個(gè)問(wèn)卷對(duì)象通過(guò)傳遞的id查看到指定的問(wèn)卷對(duì)象,再通過(guò)自定義的函數(shù)將對(duì)象轉(zhuǎn)化為字典數(shù)據(jù),最后返回單個(gè)問(wèn)卷對(duì)象的json數(shù)據(jù)。
(2)獲取所有問(wèn)題對(duì)象數(shù)據(jù),及添加問(wèn)題對(duì)象
class Questions(View):
def get(self,request):
#查詢(xún)所有問(wèn)題
questions_set = Question.objects.all()
#把question_set轉(zhuǎn)化為字典
data = []
for question in questions_set:
data.append(question.question_to_dict())
#把字典數(shù)據(jù)當(dāng)做json返回
return JsonResponse({'data':data})
def post(self,request,*args,**kwargs):
'''假設(shè)前端通過(guò)post傳過(guò)來(lái)一個(gè)json數(shù)據(jù)'''
#把request中的json轉(zhuǎn)化為python對(duì)象
data = json.loads(request.body.decode())
#抽取數(shù)據(jù)
questionnaire_id = data.get('questionnaire_id')
title = data.get('title')
is_checkbox = data.get('is_checkbox')
# 獲取questionnaire_id對(duì)應(yīng)的對(duì)象
questionnaire = Questionnaire.objects.get(id=questionnaire_id)
#創(chuàng)建Question實(shí)例
question = Question(title=title,is_checkbox=is_checkbox,questionnaire=questionnaire)
question.save()
#創(chuàng)建choice對(duì)象
choices = data.get('choice')
for c in choices:
choice = Choice()
choice.content = c
choice.question = question
choice.save()
return JsonResponse({"msg":"success save"})
通過(guò)get請(qǐng)求來(lái)獲取所有問(wèn)題的json數(shù)據(jù),通過(guò)post方法從前端獲取到傳遞過(guò)來(lái)的json數(shù)據(jù),將其轉(zhuǎn)化為對(duì)象并保存。并在保存成功之后返回提示信息。
(3)通過(guò)get,put,delete處理單個(gè)問(wèn)題對(duì)象
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的數(shù)據(jù)
data = json.loads(request.body.decode())
title = data.get('title')
#獲取question對(duì)象
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)
這里難點(diǎn)是使用put方法修改某個(gè)對(duì)象的數(shù)據(jù),使用put請(qǐng)求,將需要修改的數(shù)據(jù)寫(xiě)成json格式,并把修改后的數(shù)據(jù)重新賦值給對(duì)象,然后保存。
3.配置url,調(diào)用接口
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來(lái)快速開(kāi)發(fā)接口,下面是使用restframework來(lái)開(kāi)發(fā)接口的代碼
1.創(chuàng)建對(duì)應(yīng)的序列化類(lèi)
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')
使用這些序列化類(lèi)來(lái)序列化我們需要的字段
2.定義類(lèi)視圖
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'), ]
這里我只定義了獲取所有問(wèn)卷,單個(gè)問(wèn)卷及所有問(wèn)題的類(lèi),使用restframework開(kāi)發(fā)接口雖然快速,代碼易懂,但是它的缺點(diǎn)在于通過(guò)序列化類(lèi)只能返回這個(gè)模型類(lèi)本身的字段,并不能返回它所關(guān)聯(lián)的外鍵屬性的字段,要想獲取其他關(guān)聯(lián)模型類(lèi)的數(shù)據(jù)就得定義另外的類(lèi)視圖,那么對(duì)應(yīng)的url也需要配置。但是同樣它的好處在于快速,代碼簡(jiǎn)潔易懂,只不過(guò)是獲取不同模型類(lèi)的數(shù)據(jù)需要定義不同的接口,不能像自定義接口那樣定義一個(gè)接口可以獲得其他模型類(lèi)的數(shù)據(jù)。
以上這篇淺談django不使用restframework自定義接口與使用的區(qū)別就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
PyQt5的相對(duì)布局管理的實(shí)現(xiàn)
這篇文章主要介紹了PyQt5的相對(duì)布局管理的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08
python實(shí)現(xiàn)多線(xiàn)程行情抓取工具的方法
當(dāng)我們實(shí)現(xiàn)了單線(xiàn)程,接下來(lái)就是實(shí)現(xiàn)多線(xiàn)程了,下面這篇文章主要給大家介紹了關(guān)于python實(shí)現(xiàn)多線(xiàn)程行情抓取工具的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2018-02-02
Python warning警告出現(xiàn)的原因及忽略方法
在本篇文章里小編給大家分享的是關(guān)于Python warning警告出現(xiàn)的原因及忽略方法,有需要的朋友們可以學(xué)習(xí)參考下。2020-01-01
基于Python3讀寫(xiě)INI配置文件過(guò)程解析
這篇文章主要介紹了基于Python3讀寫(xiě)INI配置文件過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07
簡(jiǎn)單示例入門(mén)了解Python TkInter框架
這篇文章主要為大家通過(guò)簡(jiǎn)單示的示例帶大家入門(mén)了解Python TkInter框架,讓大家對(duì)Python TkInter有一個(gè)簡(jiǎn)單的認(rèn)知,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2023-11-11
如何基于python實(shí)現(xiàn)畫(huà)不同品種的櫻花樹(shù)
這篇文章主要介紹了如何基于python實(shí)現(xiàn)畫(huà)不同品種的櫻花樹(shù),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-01-01
Python中cv2.Canny() 函數(shù)使用方法
cv2.Canny() 函數(shù)是 OpenCV 中的邊緣檢測(cè)函數(shù)之一,用于檢測(cè)圖像的邊緣,它的基本原理是通過(guò)計(jì)算圖像中每個(gè)像素點(diǎn)的梯度值來(lái)檢測(cè)邊緣,本文通過(guò)示例代碼介紹Python中cv2.Canny() 函數(shù)用法,需要的朋友參考下吧2023-07-07

