Django基础012--接口开发
全局参数(get,post,put,delete)
接口:/api/parameter
GET:获取全局参数的所有数据
POST:创建全局参数
PUT:更新全局参数
DELETE:删除全局参数
1.创建app
python manage.py startapp example
2.models.py
1 from django.db import models 2 3 4 # Create your models here. 5 class BaseModel(models.Model): 6 '''公共字段''' 7 is_delete_choice = ( 8 (1, '删除'), 9 (0, '正常') 10 ) 11 is_delete = models.SmallIntegerField(choices=is_delete_choice, default=0, verbose_name='是否被删除') 12 create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True) # auto_now_add的意思,插入数据的时候,自动取当前时间 13 update_time = models.DateTimeField(verbose_name='修改时间', auto_now=True) # 修改数据的时候,时间会自动变 14 15 class Meta: 16 abstract = True # 只是用来继承的,不会创建这个表 17 18 19 #全局参数model 20 class Parameter(BaseModel): 21 name = models.CharField(verbose_name='参数名',max_length=200,unique=True) 22 desc = models.CharField(verbose_name='描述', max_length=200) 23 value = models.CharField(verbose_name='参数值', max_length=200) 24 25 def __str__(self): 26 return self.name 27 28 class Meta: 29 db_table = 'parameter' 30 verbose_name = '全局参数信息表' 31 verbose_name_plural = verbose_name 32 #最后创建的在最上面 33 ordering = ['-id']#根据id降序排序
创建表,执行以下命令
python manage.py makemigrations example --指定app生成表的初始化文件
python manage.py migrate example --指定app创建表
3.example/urls.py
1 from django.urls import path 2 from .views import f_parameter,Parameter,SParameter 3 4 urlpatterns = [ 5 # FBV 6 path('parameter',f_parameter), 7 #CBV 8 path('c_parameter',Parameter.as_view()), 9 #简化代码 10 path('s_parameter',SParameter.as_view()),
4.项目的urls.py
1 from django.contrib import admin 2 from django.urls import path,include 3 #引入example中的urls 4 from example import urls 5 6 urlpatterns = [ 7 path('admin/', admin.site.urls), 8 #include是引入其他app的urls,每个请求都要加上api/ 9 path('api/',include(urls)), 10 ]
5.views.py
5.1 FBV模式 func base view
1 # FBV func base view 2 #用函数实现的view 3 def f_parameter(request): 4 data = {'name':'zzl','age':18} 5 if request.method == 'GET': 6 page = request.GET.get('page')#获取前台返回的第几页数据 7 qs = models.Parameter.objects.filter(is_delete=0)#查询出未删除的参数 8 page_obj = Paginator(qs,5) 9 page_data = page_obj.get_page(page)#获取分页的数据 10 data_list = [] 11 for data in page_data: 12 #model_to_dict(data,exclude=['is_delete']) 13 # fields:包含哪些字段, 14 # exclude:排除哪些字段 15 # django自带model_to_dict 不处理时间,用自己重写的model_to_dict 16 data_list.append(model_to_dict(data,exclude=['is_delete']))#将qs转成dict并放入list中 17 return JsonResponse({'msg':0,'data':data_list}) 18 elif request.method == 'POST': 19 form_obj = forms.ParameterForm(request.POST) 20 f = form_obj.is_valid() 21 if f: 22 models.Parameter.objects.create(**form_obj.cleaned_data)#插入数据 23 return JsonResponse({'code':200,'msg':'成功'}) 24 else: 25 return JsonResponse({'code':500,'msg':form_obj.errors.get_json_data()}) 26 elif request.method == 'PUT': 27 #django并没有处理PUT的数据 request.PUT 28 #实际put传过来的数据在request.body里 29 #request.body的数据不可用,要导入from django.http import QueryDict,来处理数据 30 #更新数据,需要告知,要更新哪条数据 31 put_data = QueryDict(request.body) 32 print('put_data',put_data) 33 34 p_id = put_data.get('id')#获取前端传过来的数据的id 35 print('p_id',p_id) 36 p_data = models.Parameter.objects.get(id=p_id) 37 38 #参数1是前端传过来的,参数2是数据库中获取的 39 form_obj = forms.ParameterForm(put_data,instance=p_data) 40 41 if form_obj.is_valid(): 42 form_obj.save()#如果数据校验通过,就通过form_obj.save方法来更新数据 43 return JsonResponse({'code': 200, 'msg': '成功'}) 44 else: 45 return JsonResponse({'code': 500, 'msg': form_obj.errors.get_json_data()}) 46 elif request.method == 'DELETE': 47 #删除要先确定是删除哪条数据,需要获取id 48 #删除有1,逻辑删除 2,物理删除 49 #1,逻辑删除:只是通过改变某个字段的状态,重要的数据,有可能在未来通过状态再改回来 50 #2,物理删除,数据不重要,直接delete掉 51 p_id = request.GET.get('id') 52 print(p_id) 53 #逻辑删除 54 #models.Parameter.objects.filter(id=p_id).update(is_delete = 1) #这种更新方式不会触发update_time更新 55 # p_obj = models.Parameter.objects.filter(id=p_id).first() 56 # print(p_obj) 57 # p_obj.is_delete = 1 58 # p_obj.save()#这种方式可以触发update_time更新 59 60 #物理删除 61 models.Parameter.objects.filter(id=p_id).delete()#删除数据 62 63 return JsonResponse({'msg':'delete'}) 64 else: 65 return JsonResponse({'msg':'error'})
5.2 CBV模式 class base view
1 #CBV class base view 2 #面向对象的语言,通过class,可以用到继承 多继承 面向对象 3 class Parameter(View): 4 def get(self,request): 5 page = request.GET.get('page') # 获取前台返回的第几页数据 6 qs = models.Parameter.objects.filter(is_delete=0) # 查询出未删除的参数 7 page_obj = Paginator(qs, 5) 8 page_data = page_obj.get_page(page) # 获取分页的数据 9 data_list = [] 10 for data in page_data: 11 # model_to_dict(data,exclude=['is_delete']) 12 # fields:包含哪些字段, 13 # exclude:排除哪些字段 14 # django自带model_to_dict 不处理时间,用自己重写的model_to_dict 15 data_list.append(model_to_dict(data, exclude=['is_delete'])) # 将qs转成dict并放入list中 16 return JsonResponse({'msg': 0, 'data': data_list}) 17 18 def post(self,request): 19 form_obj = forms.ParameterForm(request.POST) 20 f = form_obj.is_valid() 21 if f: 22 models.Parameter.objects.create(**form_obj.cleaned_data) # 插入数据 23 return JsonResponse({'code': 200, 'msg': '成功'}) 24 else: 25 return JsonResponse({'code': 500, 'msg': form_obj.errors.get_json_data()}) 26 27 def put(self,request): 28 # django并没有处理PUT的数据 request.PUT 29 # 实际put传过来的数据在request.body里 30 # request.body的数据不可用,要导入from django.http import QueryDict,来处理数据 31 # 更新数据,需要告知,要更新哪条数据 32 put_data = QueryDict(request.body) 33 print('put_data', put_data) 34 35 p_id = put_data.get('id') # 获取前端传过来的数据的id 36 print('p_id', p_id) 37 p_data = models.Parameter.objects.get(id=p_id) 38 39 # 参数1是前端传过来的,参数2是数据库中获取的 40 form_obj = forms.ParameterForm(put_data, instance=p_data) 41 42 if form_obj.is_valid(): 43 form_obj.save() # 如果数据校验通过,就通过form_obj.save方法来更新数据 44 return JsonResponse({'code': 200, 'msg': '成功'}) 45 else: 46 return JsonResponse({'code': 500, 'msg': form_obj.errors.get_json_data()}) 47 48 def delete(self,request): 49 # 删除要先确定是删除哪条数据,需要获取id 50 # 删除有1,逻辑删除 2,物理删除 51 # 1,逻辑删除:只是通过改变某个字段的状态,重要的数据,有可能在未来通过状态再改回来 52 # 2,物理删除,数据不重要,直接delete掉 53 p_id = request.GET.get('id') 54 print(p_id) 55 # 逻辑删除 56 # models.Parameter.objects.filter(id=p_id).update(is_delete = 1) #这种更新方式不会触发update_time更新 57 # p_obj = models.Parameter.objects.filter(id=p_id).first() 58 # print(p_obj) 59 # p_obj.is_delete = 1 60 # p_obj.save()#这种方式可以触发update_time更新 61 62 # 物理删除 63 models.Parameter.objects.filter(id=p_id).delete() # 删除数据 64 65 return JsonResponse({'msg': 'delete'})
5.3 CBV模式 代码优化
5.3.1 custom_view.py
1 #重写model_to_dict 2 import datetime 3 from itertools import chain 4 5 from django.core.paginator import Paginator 6 from django.db.models import Model, Q 7 from django.forms import BaseForm 8 from django.http import JsonResponse, QueryDict 9 from django.views import View 10 from .custom_response import NbResponse 11 12 from example import models 13 14 15 def model_to_dict(instance, fields=None, exclude=None): 16 opts = instance._meta 17 data = {} 18 for f in chain(opts.concrete_fields, opts.private_fields, opts.many_to_many): 19 if fields and f.name not in fields: 20 continue 21 if exclude and f.name in exclude: 22 continue 23 value = f.value_from_object(instance) 24 if isinstance(value, datetime.datetime): 25 value = value.strftime('%Y-%m-%d %H:%M:%S') 26 if isinstance(value, datetime.date): 27 value = value.strftime('%Y-%m-%d') 28 data[f.name] = value 29 return data 30 31 class BaseView(View): 32 search_fields = []#定义需要模糊搜素的字段 33 filter_fields = []#定义需要搜索的字段 34 model_class = None 35 fields = [] #指定返回的字段 36 exclude_fields = [] #指定返回时过滤的字段 37 form_class = None 38 39 @property#修饰方法,使方法可以像属性一样访问 40 def model(self): 41 #issubclass 参数1是否为参数2的子类 42 if self.model_class and issubclass(self.model_class,Model): 43 return self.model_class 44 raise Exception('未定义model_class') 45 46 @property # 修饰方法,使方法可以像属性一样访问 47 def form(self): 48 # issubclass 参数1是否为参数2的子类 49 if self.form_class and issubclass(self.form_class, BaseForm): 50 return self.form_class 51 raise Exception('未定义form_class') 52 53 def get_filter_dict(self): 54 filter_dict = {} 55 for field in self.filter_fields: 56 filter_value = self.request.GET.get(field)#获取前端传过来的值 57 if filter_value: 58 filter_dict[field] = filter_value 59 return filter_dict 60 61 #只支持一个字段的模糊查询 62 def get_search_dict(self): 63 search_dict = {} 64 value = self.request.GET.get('search')#获取前台传过来的字段 65 if value: 66 search_dict = {'%s__contains'%self.search_fields[0] : value} 67 print(search_dict) 68 return search_dict 69 70 #支持多个字段的模糊查询 71 def get_search_dict_or(self): 72 value = self.request.GET.get('search') 73 q = Q() 74 if value: 75 for field in self.search_fields: 76 d = {'%s__contains'%field : value} 77 q = Q(**d) | q 78 return q 79 80 81 class GetView(BaseView): 82 def get(self,request): 83 page = request.GET.get('page') # 获取前台返回的第几页数据 84 filter_dict = self.get_filter_dict()#获取需要搜索的字典 85 # search_dict = self.get_search_dict()#获取需要模糊查询的字典 86 # qs = self.model.objects.filter(is_delete=0).filter(**filter_dict).filter(**search_dict) # 查询出未删除的参数 87 search_q = self.get_search_dict_or()#获取需要模糊查询的q 88 qs = self.model.objects.filter(is_delete=0).filter(**filter_dict).filter(search_q) # 查询出未删除的参数 89 page_obj = Paginator(qs, 5) 90 page_data = page_obj.get_page(page) # 获取分页的数据 91 data_list = [] 92 for data in page_data: 93 # model_to_dict(data,exclude=['is_delete']) 94 # fields:包含哪些字段, 95 # exclude:排除哪些字段 96 # django自带model_to_dict 不处理时间,用自己重写的model_to_dict 97 data_list.append(model_to_dict(data, fields=self.fields,exclude=self.exclude_fields)) # 将qs转成dict并放入list中 98 return NbResponse(data=data_list) 99 100 101 class PostView(BaseView): 102 def post(self,request): 103 form_obj = self.form(request.POST) 104 f = form_obj.is_valid() 105 if f: 106 self.model.objects.create(**form_obj.cleaned_data) # 插入数据 107 return NbResponse() 108 else: 109 # return JsonResponse({'code': 500, 'msg': form_obj.errors.get_json_data()}) 110 return NbResponse(code=500,msg=form_obj.errors.get_json_data()) 111 112 113 class PutView(BaseView): 114 def put(self,request): 115 # django并没有处理PUT的数据 request.PUT 116 # 实际put传过来的数据在request.body里 117 # request.body的数据不可用,要导入from django.http import QueryDict,来处理数据 118 # 更新数据,需要告知,要更新哪条数据 119 120 p_id = request.PUT.get('id') # 获取前端传过来的数据的id 121 print('p_id', p_id) 122 p_data = models.Parameter.objects.get(id=p_id) 123 124 # 参数1是前端传过来的,参数2是数据库中获取的 125 form_obj = self.form(request.PUT, instance=p_data) 126 127 if form_obj.is_valid(): 128 form_obj.save() # 如果数据校验通过,就通过form_obj.save方法来更新数据 129 return JsonResponse({'code': 200, 'msg': '成功'}) 130 else: 131 return JsonResponse({'code': 500, 'msg': form_obj.errors.get_json_data()}) 132 133 134 class DeleteView(BaseView): 135 def delete(self,request): 136 # 删除要先确定是删除哪条数据,需要获取id 137 # 删除有1,逻辑删除 2,物理删除 138 # 1,逻辑删除:只是通过改变某个字段的状态,重要的数据,有可能在未来通过状态再改回来 139 # 2,物理删除,数据不重要,直接delete掉 140 p_id = request.GET.get('id') 141 print(p_id) 142 # 逻辑删除 143 # models.Parameter.objects.filter(id=p_id).update(is_delete = 1) #这种更新方式不会触发update_time更新 144 # p_obj = models.Parameter.objects.filter(id=p_id).first() 145 # print(p_obj) 146 # p_obj.is_delete = 1 147 # p_obj.save()#这种方式可以触发update_time更新 148 149 # 物理删除 150 self.model.objects.filter(id=p_id).delete() # 删除数据 151 152 return JsonResponse({'msg': 'delete'}) 153 154 155 class NbView(GetView,PostView,PutView,DeleteView): 156 pass
5.3.2 views.py
1 #简化代码--全局参数 2 class SParameter(NbView): 3 # 抽象出不同的地方,让相同的地方复用 4 model_class = models.Parameter#重写了父类的变量 5 #fields = ['name'] 6 exclude_fields = ['is_delete'] 7 filter_fields = ['value'] #搜索字段 8 search_fields = ['name','desc'] #模糊查询字段 9 form_class = forms.ParameterForm
6.myMiddleWires.py
当请求方式为PUT时,参数是在request.body中获取,且是经过编码后的,获取参数不方便
可以在中间件请求拦截器中,识别请求方式为PUT时,将参数转为request.put
1 from django.middleware.common import MiddlewareMixin 2 from django.http import HttpResponse,QueryDict 3 from sky.settings import DEBUG 4 from example.custom_response import NbResponse 5 6 class PutMethodMiddlerware(MiddlewareMixin): 7 def process_request(self,request): 8 if request.method == 'PUT': 9 request.PUT = QueryDict(request.body) 10 11 12 #出现异常时抛出异常 13 class ExceptionMiddleware(MiddlewareMixin): 14 def process_exception(self,request,exception): 15 if not DEBUG:#上线之后,直接将错误返回,未上线不做拦截,控制台可看 16 #拦截异常的 17 return NbResponse(code=500,msg='系统开小差了,请联系管理员...%s'%exception)
7.custom_response.py
JsonResponse返回json字符串时,如果每次需要返回固定的字段,可以重写JsonResponse里的方法
1 from django.http import JsonResponse 2 3 4 class NbResponse(JsonResponse): 5 def __init__(self,code=200,msg='操作成功',**kwargs): 6 data = {'code':code,'msg':msg} 7 data.update(kwargs) 8 super().__init__(data=data,json_dumps_params={"ensure_ascii": False})