浅谈django不使用restframework自定义接口与使用的区别
django可以使用restframework快速开发接口,返回前端所需要的json数据,但是有时候利用restframework开发的接口并不能满足所有的需求,这时候就需要自己手动开发接口,也就是将需要用到的某些对象转化为需要使用的json数据,今天记录一下django自己定义接口的一种方法与思路
假设我们定义三张数据表,分别是问卷,问题,选项。一张问卷包含不同的问题,一个问题可以设置不同的选项,自定义的接口可以实现查看所有或单个问卷的标题与id,可以查看所有或单个问题的所属问卷,问题标题,问卷的选项。
1.定义我们需要的模型类,并且在对应的模型类中定义对应的将对象转化为字典的函数
fromdjango.dbimportmodels classQuestionnaire(models.Model): '''问卷''' title=models.CharField('标题',max_length=100) classMeta: verbose_name_plural='所有问卷' defquestionnaire_to_dict(self): '''把questionnaire对象转化为字典''' returndict(questionnaire_id=self.id,title=self.title,questions=[question.question_to_dict()forquestioninself.questions.all()]) def__str__(self): returnself.title classQuestion(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='是否是多选问题') classMeta: verbose_name_plural='问题' defquestion_to_dict(self): '''把question对象转化为字典''' returndict(title=self.title,choice=[choice.choice_to_dict()forchoiceinself.choices.all()], is_checkbox=self.is_checkbox,questionnaire_id=self.questionnaire.id) def__str__(self): returnself.title classChoice(models.Model): '''选项''' #所属的问题 question=models.ForeignKey(Question,verbose_name='所属问题',related_name='choices') content=models.CharField('选项内容',max_length=150) classMeta: verbose_name_plural='问题选项' defchoice_to_dict(self): '''把choice对象转化为字典''' #选项id,选项所属的问题id,选项内容 returndict(id=self.id,question_id=self.question.id,content=self.content) def__str__(self): returnself.content
将你需要转化为字典的字段添加进函数中,当指定外键时,"related_name"为指定关系名,用于反向查找,比如通过问卷查找问题,但是问卷模型类中没有question字段,但是question类中指定questionnaire外键时指定了关系名related_name='questions'所以可以通过self.questions.all()来查看当前问卷的所有问题。
2.定义类视图
(1)定义查看所有问卷与添加问卷的类视图
fromquestion.modelsimportQuestion,Questionnaire,Choice fromdjango.httpimportJsonResponse fromdjango.viewsimportView importjson classQuestionnaires(View): defget(self,request): #获取所有问卷 data=[] questionnaires=Questionnaire.objects.all()#获取所有的问卷类 forquestionnaireinquestionnaires: data.append(questionnaire.questionnaire_to_dict()) returnJsonResponse({'data':data}) defpost(self,request,*args,**kwargs): data=json.loads(request.body.decode()) questionnaire=Questionnaire(title=data.get('title')) questionnaire.save() returnJsonResponse({'msg':'successsave'}) classQuestionnaireDetail(View): '''获取id为questionnaire_id的问卷''' defget(self,request,questionnaire_id): questionnaire=Questionnaire.objects.get(id=questionnaire_id) data=questionnaire.questionnaire_to_dict() returnJsonResponse(data)
这里继承View类自己定义get方法与post方法处理请求,首先获取到所有的问卷对象,在将每一个问卷对象通过自定义的函数转化为字典,最后返回json数据,同样处理post请求添加问卷时,首先获取到问卷的标题,然后实例化一个问卷的对象,再将问卷对象保存。获取单个问卷对象通过传递的id查看到指定的问卷对象,再通过自定义的函数将对象转化为字典数据,最后返回单个问卷对象的json数据。
(2)获取所有问题对象数据,及添加问题对象
classQuestions(View): defget(self,request): #查询所有问题 questions_set=Question.objects.all() #把question_set转化为字典 data=[] forquestioninquestions_set: data.append(question.question_to_dict()) #把字典数据当做json返回 returnJsonResponse({'data':data}) defpost(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') forcinchoices: choice=Choice() choice.content=c choice.question=question choice.save() returnJsonResponse({"msg":"successsave"})
通过get请求来获取所有问题的json数据,通过post方法从前端获取到传递过来的json数据,将其转化为对象并保存。并在保存成功之后返回提示信息。
(3)通过get,put,delete处理单个问题对象
classQuestionDetail(View): defdelete(self,request,question_id): question=Question.objects.get(id=question_id) question.delete() defput(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() returnJsonResponse({'msg':'modifysuccess'}) defget(self,request,question_id): question=Question.objects.get(id=question_id) data=question.question_to_dict() returnJsonResponse(data)
这里难点是使用put方法修改某个对象的数据,使用put请求,将需要修改的数据写成json格式,并把修改后的数据重新赋值给对象,然后保存。
3.配置url,调用接口
fromdjango.conf.urlsimporturl fromquestion.viewsimportQuestions,Questionnaires,QuestionDetail,QuestionnaireDetail urlpatterns=[ url(r'^questions/$',Questions.as_view(),name='questions'), url(r'^questionnaire/(?P\d+)/$',QuestionnaireDetail.as_view(),name='questionnaire'), url(r'^questionnaires/$',Questionnaires.as_view(),name='questionnaires'), url(r'^question/(?P \d+)/$',QuestionDetail.as_view(),name='question'), ]
同样,我们可以使用restframework来快速开发接口,下面是使用restframework来开发接口的代码
1.创建对应的序列化类
fromrest_frameworkimportserializers fromquestion.modelsimportQuestion,Questionnaire,Choice classQuestionnaireSerializer(serializers.ModelSerializer): classMeta: model=Questionnaire fields=('title',) classQuestionSerializer(serializers.ModelSerializer): classMeta: model=Question fields=('title','is_checkbox','questionnaire') classChoiceSerializer(serializers.ModelSerializer): classMeta: model=Choice fields=('content','question')
使用这些序列化类来序列化我们需要的字段
2.定义类视图
classQuestionnaireList(APIView): defget(self,request): questionnaire=Questionnaire.objects.all() serializer=QuestionnaireSerializer(questionnaire,many=True) returnResponse(serializer.data) defpost(self,request): serializer=QuestionnaireSerializer(data=request.data) ifserializer.is_valid(): serializer.save() returnResponse(serializer.data) returnResponse(serializer.errors) classQuestionnaire_Detail(APIView): defget_object(self,pk): try: returnQuestionnaire.objects.get(pk=pk) exceptQuestionnaire.DoesNotExist: raiseHttp404 defget(self,request,pk): questionnaire=self.get_object(pk) serializer=QuestionnaireSerializer(questionnaire) returnResponse(serializer.data) defput(self,request,pk): questionnaire=self.get_object(pk) serializer=QuestionSerializer(questionnaire,data=request.data) ifserializer.is_valid(): serializer.save() returnResponse(serializer.data) returnResponse(serializer.errors) defdelete(self,request,pk): questionnaire=self.get_object(pk) questionnaire.delete() returnResponse(status=status.HTTP_204_NO_CONTENT) classQuestionList(APIView): defget(self,request): question=Question.objects.all() serializer=QuestionSerializer(question,many=True) returnResponse(serializer.data) defpost(self,request): serializer=QuestionSerializer(data=request.data) ifserializer.is_valid(): serializer.save() returnResponse(serializer.data) returnResponse(serializer.errors)
3.配置url
fromdjango.conf.urlsimporturl fromquestion.viewsimportQuestionnaire_Detail,QuestionnaireList,QuestionList urlpatterns=[ url(r'^questions/$',QuestionList.as_view(),name='questions'), url(r'^questionnaire/(?P\d+)/$',Questionnaire_Detail.as_view(),name='questionnaire'), url(r'^questionnaires/$',QuestionnaireList.as_view(),name='questionnaires'), ]
这里我只定义了获取所有问卷,单个问卷及所有问题的类,使用restframework开发接口虽然快速,代码易懂,但是它的缺点在于通过序列化类只能返回这个模型类本身的字段,并不能返回它所关联的外键属性的字段,要想获取其他关联模型类的数据就得定义另外的类视图,那么对应的url也需要配置。但是同样它的好处在于快速,代码简洁易懂,只不过是获取不同模型类的数据需要定义不同的接口,不能像自定义接口那样定义一个接口可以获得其他模型类的数据。
以上这篇浅谈django不使用restframework自定义接口与使用的区别就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。