django 前后端分离,后端接口实现
博客篇我们使用的是前后端不分离的方式进行实现,前后端不分离实现方式,主要用于小型的项目,且一个人就可以搞定所有,但是中大型的应用还是用的前后端分离的方式进行的
前后端分离方式后台主要给前端提供接口,前端JS调用后台的接口,根据接口定义的传参进行传参,得到返回值,然后展现在页面上,或者对数据进行了操作,把操作后的数据传给后端,后端进行数据的更新等
下面的例子我们主要从基本的增删改查进行设计后台接口部分
一、准备工作
1、modles.py文件中,创建student表,用于进行增删改查
class Student(models.Model):
name = models.CharField(verbose_name='名称',max_length=10)
phone = models.CharField(max_length=11,unique=True,verbose_name='手机号')
money = models.FloatField(verbose_name='金额',default=0,null=True)
addr = models.CharField(verbose_name='地址', default='北京', max_length=20)
work_addr = models.CharField(verbose_name='地址', default='北京', max_length=20)
create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True) # auto_now_add的意思,插入数据的时候,自动取当前时间
update_time = models.DateTimeField(verbose_name='修改时间', auto_now=True)
class Meta:
verbose_name = '学生表'
verbose_name_plural = verbose_name
db_table = 'student'
def __str__(self):
return self.name
python manage.py makemigrations 创建表结构
python manage.py migrate 创建数据库表
2、view.py文件中引用form表单进行验证
from .models import Student
from django.forms import ModelForm #引用表单模块
class StudentForm(ModelForm):
class Meta:
model = Student
fields = '__all__' #代表所有的字段
3、定义接口类,主要用于写增删改查接口对应的方法
class StudentView(View):
4、urls.py文件,增加接口请求名称
备注:as_view方法里面实现了,根据请求方式去找类里面对应的方法名,如果是get请求,它就去找get这个函数,找不到就是不支持get请求
urlpatterns = [
#这种方式,需要在连接后面加?,比如url?id=1
path('stu3', views2.StudentView.as_view() ),
#这种方式,无需在连接后面加?,比如 url/3
#path('stu3/<int:id>',views2.StudentView.as_view()),
]
二、查询,get请求
其中支持模糊查询及过滤查询,方法如下:
search_field=['name','phone','addr','work_addr'] #存储搜索的字段,全局变量
filter_field=['name','phone','id'] #存储过滤字段,全局变量
def get(self,request):
limit = request.GET.get('limit',20) #每页个数,无传值默认每页20
page = request.GET.get('page',1) #页码,无传值,默认1
search=request.GET.get('search') #获取请求中的查询条件
filter_dict={} #定义空字典,存储过滤字段及值
#过滤
for field in self.filter_field: #遍历过滤list
value=request.GET.get(field)
if value: #当请求中有该字段且该字段不为空
filter_dict[field]=value #把该字段及值写入过滤字典中
#查询
q_result=Q()
for field in self.search_field: #变量搜索list
if search: #如果查询值不为空
d={'%s__contains'%field:search} #每个字段与该值均放入d字典
q_result=Q(**d)|q_result #取几个字段是该值的并集
all_students = Student.objects.filter(**filter_dict).filter(q_result).values() #这种方式优先过滤,all_students为搜索结果
#all_students = Student.objects.filter(q_result).values().filter(**filter_dict) #这种方式优先模糊查询,all_students为搜索结果
page_obj = Paginator(all_students,limit) #搜索结果分页
stus = list(page_obj.get_page(page)) #获取第几页数据
data = {"error_code":0,"msg":"操作成功","data":stus,"count":page_obj.count} #结果写成json格式
return JsonResponse(data,json_dumps_params={"ensure_ascii":False},encoder=NbJSONEncoder) #返回结果,其中得到时间格式带T字样,为解决这个问题,可以通过encoder=NbJSONEncoder 解决
encoder=NbJSONEncoder中,其NbJSONEncoder对应的代码如下:
import json
import datetime
class NbJSONEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime.datetime):
return obj.strftime('%Y-%m-%d %H:%M:%S')
elif isinstance(obj, datetime.date):
return obj.strftime('%Y-%m-%d')
else:
return json.JSONEncoder.default(self, obj)
三、添加,post请求
思路:从post请求的body中获取到数据,通过表单自带的验证,验证数据格式的正确性,验证通过的返回正确的结果,验证失败的返回失败的结果
def post(self,request):
stu_form = StudentForm(request.POST) #获取post请求中的数据
if stu_form.is_valid(): #表单自带验证,验证是否符合规则
Student.objects.create(**stu_form.cleaned_data) #数据同步到数据库中
data = {"error_code":0,'msg':'添加成功'} #返回结果
else:
data = {"error_code":-1,'msg':stu_form.errors.get_json_data()} #失败返回结果
return JsonResponse(data,json_dumps_params={"ensure_ascii":False}) #返回结果
四、修改,put请求
思路:如果不是POST请求的话,request.POST里面没数据 所以获取数据通过request.META来获取原始请求的数据,parse_file_upload是django用例解析body里面的数据和文件的,获取数据后进行部分及全部数据修改和数据校验,数据校验主要是通过表单内部的校验方法,部分修改是通过判断请求中的数据与表单校验失败的有交集进行程序实现的
put_data,files =request.parse_file_upload(request.META,request)#获取请求中的修改的数据字段及值
stu_form=StudentForm(put_data) #放入表单
id=request.GET.get('id',0) #获取请求中的ID值,无,默认为0
clean_data={} #
if stu_form.is_valid(): #from中的值如果均有效
Student.objects.filter(id=id).update(**stu_form.cleaned_data) #根据字段ID,更新值
data = {"error_code": 0, 'msg': '操作成功'} #返回值
else: #FROM中的值如果有无效的
error_keys=set(stu_form.errors.get_json_data().keys()) #获取错误的keys并转换为集合
put_keys=set(put_data.keys()) #获取所有的keys并转换为集合
if error_keys & put_keys:#如果2者有交集
data = {"error_code": -1, 'msg': stu_form.errors.get_json_data()}
return JsonResponse(data, json_dumps_params={"ensure_ascii": False}) #返回错误结果
else: #如果无交集
for key in put_data:
clean_data[key]=put_data.get(key) #把变量这个放入字典
Student.objects.filter(id=id).update(**clean_data) #更新数据库
data = {"error_code": 0, 'msg': '操作成功'}#返回结果
return JsonResponse(data, json_dumps_params={"ensure_ascii": False}) #返回正确的结果
五、删除,delete请求
思路:获取请求中的ID值,然后删除对应ID的记录
def delete(self,request):
id=request.GET.get('id',0) #获取请求删除的ID,如果没有传默认是0
Student.objects.filter(id=id).delete() #删除数据
data = {"error_code": 0, 'msg': '操作成功'} #返回结果
print('delete')
return JsonResponse(data, json_dumps_params={"ensure_ascii": False}) #返回