day13-3django后端开发
一、配置
1.修改文件目录后,需要修改的位置
2.修改运行目录
3.复制db路径,重新连接数据库
2.删除数据的操作步骤
https://blog.csdn.net/doulihang/article/details/102973565
3.数据库多对多的生成方式
django里面的多对多关系,它是通过建立第三张表来存储对应的关系。
在models模块
class Teacher(models.Model): name = models.CharField(max_length=50) def __str__(self): return self.name class Meta: db_table = 'teacher' class Student(models.Model): name = models.CharField(max_length=50,verbose_name='学生姓名') teacher = models.ManyToManyField(Teacher,verbose_name='老师') def __str__(self): return self.name class Meta: db_table = 'student'
2.添加到admin中后,通过页面创建数据。查看数据库中的显示
#新增数据,新增多对多关系 #正向查询(在models里面有多对多的查询) stu = models.Student.objects.create(name="fangdan") stu.teacher.add(1) stu.teacher.add(2) # get_or_create如果存在就get,如果不存在就创建 stu,status = models.Student.objects.get_or_create(name="李想") print(stu) stu.teacher.remove(1)#从关系里面删除一个老师 print(stu.teacher.all())#查看所有老师 print(stu.teacher.get(id=2)) #反向查询,model里面没有多对多的这个字段 teacher,status = models.Teacher.objects.get_or_create(name= '大老师') print(teacher.student_set.all()) # print(teacher.student_set.remove()) # print(teacher.student_set.add()) print(teacher.student_set.filter()) print(teacher.student_set.count()) # print(teacher.student_set.clear()) # print(teacher.student_set.create())
4.自关联
class Case(models.Model): name = models.CharField(max_length=50) url = models.CharField(max_length=10) method = models.CharField(max_length=20) param = models.CharField(max_length=30) #自关联,null=True数据不能为空,blank=True admin中不能为空 require_case = models.ForeignKey('self',on_delete=models.PROTECT,verbose_name='依赖用例',null=True,blank=True) def __str__(self): return self.name class Meta: db_table = 'case' ordering = ['-id']
5.一对一的关系
class Account(models.Model): balance = models.IntegerField(verbose_name='余额',default=0) class Meta: db_table = 'account' class User(models.Model): name = models.CharField(max_length=50) account = models.OneToOneField(Account,on_delete=models.CASCADE,verbose_name='账户')#级联 def __str__(self): return self.name class Meta: db_table = 'user'
6.数据库路由:不同的app访问不同的数据库
user访问sqllite,order访问的是mysql数据库
数据库配置:sqllite是文件数据库
pip install django_redis==4.10
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), }, 'mysql':{ 'ENGINE': 'django.db.backends.mysql', 'NAME': 'jxz', 'HOST': '118.24.3.40', 'PASSWORD': '123456', 'USER': 'jxz', 'PORT': 3306, } }#数据库配置 CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://118.24.3.40:6379/0", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", "CONNECTION_POOL_KWARGS": {"max_connections": 100}, "PASSWORD": "HK139bc&*", # 密码 } }, "redis2": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://118.24.3.40:6379/1", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", "CONNECTION_POOL_KWARGS": {"max_connections": 100, 'decode_responses': True}, "PASSWORD": "HK139bc&*", # 密码 } } } # redis配置 DATABASE_ROUTERS = ['sky.database_router.DatabaseAppsRouter'] #与下面的类的路径
写一个数据库路由的类
db_mapper = { 'sqlite':'default', 'order':'mysql' } class DatabaseAppsRouter(object): def db_for_read(self, model, **hints): print('走了读',model) app_label = model._meta.app_label if app_label in db_mapper: return db_mapper[app_label] return 'default' def db_for_write(self, model, **hints): print('走了写',model) app_label = model._meta.app_label if app_label in db_mapper: return db_mapper[app_label] return 'default'
运行后django会报错,解决方法,是在sky的下面创建一个__init__.py,再启动就不会报错了
import pymysql pymysql.install_as_MySQLdb()
在order中的models中写入
from django.db import models # Create your models here. class FDD(models.Model): name = models.CharField(max_length=50) def __str__(self): return self.name class Meta: db_table = 'Fdd' # app_label = 'new_user'因为是在order应用中写的,所以不用写这个 #makemigrations order #migrate # migrate order --database mysql
在mysql中插入数据报错,解决方法
def allow_relation(self, obj1, obj2, **hints): '''允许两个表有关系''' return True # ValueError: Cannot # assign # "<ContentType: ContentType object (1)>": the # current # database # router # prevents # this # relation.
redis需要安装它 django_redis==4.10
import django_redis r = django_redis.get_redis_connectiong('redis2') print(r.keys())
7.fvb,cvb(function(def) view,class view)
===参照user中的views 和order中的views的区别
8.urls拆分
order和user中的有views,在sky的urls中如果添加
方法一:使用别名as
from user import views # from order import views as o_view urlpatterns = [ path('admin/', admin.site.urls), path('',include('user.urls')), # path('user', o_view.UserView.as_view()), ]
方法二:拆分
分别在order和user中创建urls.py文件
from . import views from django.urls import path urlpatterns = [ path('user',views.UserView.as_view(),), ]
from . import views from django.urls import path from .import views,new_views urlpatterns = [ path('index', views.index), # path('', views.get_sign), # path('category', views.category_view), path('category/<int:id>', views.category), path('detail/<int:id>', views.article), path('test', views.test), path('', views.index), path('add', views.add_article), path('interface', new_views.InterfaceView.as_view()), ]
from django.contrib import admin from django.urls import path,include from user import views # from order import views as o_view urlpatterns = [ path('admin/', admin.site.urls), path('',include('user.urls')), path('order/',include('order.urls')), ]
9.中间件:类似上下文管理器
使用场景:总计应用中那个功能用的比较多,统计abc功能被用户用了多少次
配置中间件:特别像抓包工具
代码
from django.middleware.common import MiddlewareMixin from django.shortcuts import HttpResponse import django_redis from user.models import Interface class TestMiddleWare(MiddlewareMixin): def process_request(self,request):请求到这里 print('process_request') # token = request.Get.get('token') # if token: # r = django_redis.get_redis_connection() # if r.get(token): # pass # else: # return HttpResponse('请登录') path = request.path_info.replace('/','',1) interface = Interface.objects.filter(url=path) if interface: interface = interface.first() return HttpResponse(interface.response) def process_response(self,request,response):在views里处理完了请求,到这里 print('process_response') return response def process_exception(self,request,exception):请求出错了,到这里 return HttpResponse("系统开小差了~")
from django.shortcuts import render,HttpResponse # Create your views here. from django.views import View class UserView(View): def get(self,request): print('走到了order的views') return HttpResponse('POST请求') def get(self,request): return HttpResponse('GET请求')
urls
from . import views from django.urls import path urlpatterns = [ path('user',views.UserView.as_view(),), ]
请求http://127.0.0.1:8000/order/user
中间的请求顺序
实践,在models中创建表,在admin中添加,然后添加内容
class Interface(models.Model): name = models.CharField(max_length=50) url = models.CharField(max_length=50,unique=True) response = models.TextField(default='{}',null=True,blank=True,verbose_name='返回报文') def __str__(self): return self.name class Meta: db_table = 'interface'
在浏览器中输入:http://127.0.0.1:8000/pay
注意:如果在数据库中已经创建好了,只是使用,但是在models里面又没有,解决方法:
inspectdb 数据库名 --database mysql
导入到自己py文件中
python manage.py makemigrations app python manage.py migrate app --database db python manage.py inspectdb table1 table2 table3 > models.py --database db
10.接口查询
(1)基本接口
在new_views中
from django.core.paginator import Paginator from django.forms import model_to_dict from django.views import View from django.shortcuts import HttpResponse from django.http.response import JsonResponse from .import models import json from common.response import SkyResponse from common.const import page_limit from django.db.models import Q class InterfaceView(View): def get(self,request): return HttpResponse( json.dumps({"code":0,"msg":"操作成功"},ensure_ascii=False) )
在urls中
from .import views,new_views urlpatterns = [ path('index', views.index), path('interface', new_views.InterfaceView.as_view()), ]
结果:
(2)增删改查
一个url,和多个url
字典:from django.forms import model_to_dict在sky中创建common文件,然后创建一个response.py
(3)查询所有
from django.http.response import JsonResponse def SkyResponse(code=0,msg='操作成功',**kwargs): data = {'code':code,'msg':msg} data.update(**kwargs) return JsonResponse(data,json_dumps_params={'ensure_ascii':False} )
#查询所有的
from common.response import SkyResponse
def get(self,request): l = [] interface_query_set = models.Interface.objects.all() for d in interface_query_set: dic = model_to_dict(d) l.append(dic) return SkyResponse(data=l)
(3)按照id来筛选或者查询所有
filter_field = ['id','name'] @property def get_filter_dict(self): filter_dict = {} # {id:1,name:lhy} for field in self.filter_field: value = self.request.GET.get(field) if value: filter_dict[field] = value return filter_dict def get(self, request): # get 一条?id=1 筛选 l = [] interface_query_set = models.Interface.objects.filter(**self.get_filter_dict) for d in interface_query_set: dic = model_to_dict(d) l.append(dic) return SkyResponse(data=l)
(4)模糊查询:contains和Q
from django.db.models import Q search_field = ['name','url','request'] @property def get_search_obj(self): q_obj = Q() search = self.request.GET.get('search') if search: for field in self.search_field: d = {'%s__contains' % field: search} q_obj = q_obj | Q(**d) return q_obj # models.Interface.objects.filter(Q(url__contains=seacher)|Q(name__contains=seacher)|Q(request__contains=seacher)) # 'select * from interface where url like 'aa' or name like 'aa' or response like 'aa'; def get(self, request): # get 模糊查询 name=登 l = []
#先精确后模糊 interface_query_set = models.Interface.objects.filter(**self.get_filter_dict).filter(self.get_search_obj) for d in interface_query_set: dic = model_to_dict(d) l.append(dic) return SkyResponse(data=l)
(5)分页
在sky的common中创建const.py
page_limit = 2 #默认分页数量
在new_views中
from common.const import page_limit from django.core.paginator import Paginator分页 def get_page_data(self,obj_list): try: limit = int(self.request.GET.get('limit',page_limit)) #limit = s page = int(self.request.GET.get('page',1))#默认获取第一页 except: limit = page_limit page = 1 page_obj = Paginator(obj_list,limit) result = page_obj.get_page(page)#分好页的数据 return page_obj,result #page=1,limit=10 def get(self, request): # 分页 l = [] page_obj, page_data = self.get_page_data(interface_query_set)
interface_query_set = models.Interface.objects.filter(**self.get_filter_dict).filter(self.get_search_obj)
for d in page_data: dic = model_to_dict(d) l.append(dic) return SkyResponse(data=l, count=page_obj.count)
在网页中输入:http://127.0.0.1/interface?page=1&limit=2
11.接口删除
#删除 def delete(self, request): id = request.GET.get('id') if id: query_set = self.model_class.objects.filter(id=id) if query_set: query_set.delete() return SkyResponse() else: return SkyResponse(code=404, msg='id不存在') else: return SkyResponse(code=-1, msg='请传入id')
问题解决:
在执行模糊搜索的时候,提示系统开小差了
然后去中间件中打印
在postman中执行http://127.0.0.1:8000/interface?search=a的时候,提示错误信息
在pycharm中查看
发现原来是自己的内容写错了,修改后好了