今日的内容:
a. 路由系统
1. 创建app
2. 路由的分组
3. 路由的分发
- 正则表达式匹配
b. django的orm(模型model)
1. 创建模型的步骤
2. orm基本的增删改查
3. 正向查询和反向查询
注意事项:
1. 前台传给后台一个列表时,后端如何接受:
request.POST.getlist(字段名)
2. 前台传给后台一个列表时,需要在ajax请求中增加一个参数:
traditional: true
3. 多选框设置选中状态时,可以使用
$("select的选择器").val(列表)
4. cookie的参数设置
obj = render(request,\'a.html\')
obj.set_cookie(key,values,max_age,expires,path,
domain,secure,httponly)
参数详解
"""
key, 键
value=, 值
max_age=None, 超时时间
expires=None, 指定过期时间IE 专用 date = datetime.datetime() expires=date
path=\'/\', cookie有效路径
domain=None, Cookie生效的域名
secure=False, https传输
httponly=False 只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)
"""
5. 删除Cookie
def logout(request):
rep = redirect("/login/")
rep.delete_cookie("user") # 删除用户浏览器上之前设置的usercookie值
return rep
6. 获取Cookie
username = request.COOKIES.get(\'username\') # 取出登录用户名
7. cookie的加盐
#通过加盐的方式为cookie签名。
obj.set_signed_cookie(\'kkk\',\'vvv\', salt=\'123456\')
#获取经过签名后的cookie值。
request.get_signed_cookie(\'kkk\', salt=\'123456\')
# 目录结构
migrations # 模型操作的迁移文件
init
admin # 管理文件,django admin的时候会用到
apps # 应用信息定义文件,在其中生成了类AppCongfig,该类用于定义应用名等Meta数据
models # 添加模块层数据类的文件,orm框架时使用
tests # 测试代码文件
views # 视图文件
路由分组
对多个视图进行一个分组,比如class为一个组,所有跟class相关的增,删,改,查视图都放在这个app中。各司其职,互不干扰。相比之前把所有的代码写到urls中,功能分划更清晰。
创建app的两种方式:
1. 使用pycharm创建django项目时,可以创建。缺点:只能创建一个
2. 命令行创建python3 manage.py startapp app名称(可创建多个),
- django使用的什么版本的解释器,就需要用对应的解释器创建app
- 需要在对应的目录下创建
分组:
第一种方式
a. 项目下的urls.py中
from *** import views urlpatterns = [ url(r\'^test/\', views.test), ] # 缺点,只能导入一个app,多个app会导致名称空间被污染第二种方式
- django项目下的urls.py文件,注意:需要导入include模块
from django.conf.urls import url,include urlpatterns = [ url(r\'^classes/\',inclued("classes.urls")), url(r\'^student/\',inclued("student.urls")), url(r\'^teacher/\',inclued("teacher.urls")) ]
在对应的app下,创建一个urls.py文件
对应app的urls.py
form django.conf.urls import url from classes import views urlpatterns = [ url(r\'^get_classes/\',views.get_classes), ]
- 对应app下的views.py文件内容为:
from django.shortcuts import render,HttpResponse # Create your views here. def get_classes(request): return HttpResponse("get_classes")第二种方式的总结:
- 客户端访问127.0.0.1:8000/classes/get_classes时,先进入到项目下的urls.py文件进行匹配
- 根据项目下urls.py中的对应关系,进入到各个app项目下的urls.py文件中进行匹配
- 根据各个app下的urls.py中的对应关系,匹配成功请求路径后,执行对应app项目下views.py文件下的函数。
路由分发
from app01 import views urlpatterns = [ url(r\'^test/(?P<id>\w+)/(?P<name>\w+)\', views.test), ] # app01项目下views.py文件: def test(request,name,id): print(name) print(id) return HttpResponse("test") # 浏览器访问 http://127.0.0.1:8000/test/0123/plf # -------------------------views.py中打印结果--------------------- plf 0123当浏览器中输入一个不存在的地址时,我们可以在浏览器中匹配对应的路径,然后为不存在的url,专门设置一个页面
from app01 import views urlpatterns = [ url(r\'^\', views.notfound), ]反向路由
当一个路径很长的时候,我们可以在路由系统中,设置一个变量a,用来代替这个路径,之后我们在form表单中action中写入{% url "a" %}即可.
# 路由系统中的写法 urlpatterns = [ url(r\'^logindbsjhalbdhaskbhdkjsabhdkbashkdbhsabdhsja/$\', views.login, name=\'test\'), ] # 对应的html的页面中写法: <form action="/test/" method="post"> <input type="text"> </form>
django中请求处理方式有2种:FBV 和 CBV
第一种:FBV(function base views)
就是在视图里使用函数处理请求
urls.py
from django.conf.urls import url, include # from django.contrib import admin from mytest import views urlpatterns = [ # url(r\'^admin/\', admin.site.urls), url(r\'^index/\', views.index),views.py
from django.shortcuts import render def index(req): if req.method == \'POST\': print(\'method is :\' + req.method) elif req.method == \'GET\': print(\'method is :\' + req.method) return render(req, \'index.html\')第二种:CBV(class base views)
就是在视图里使用类处理请求。
urls.py
from mytest import views urlpatterns = [ # url(r‘^index/‘, views.index), url(r‘^index/‘, views.Index.as_view()), ] # 注:url(r‘^index/‘, views.Index.as_view()), 是固定用法。views.py
from django.views import View class Index(View): def get(self, req): print(\'method is :\' + req.method) return render(req, \'index.html\') def post(self, req): print(\'method is :\' + req.method) return render(req, \'index.html\') # 注:类要继承 View ,类中函数名必须小写。 \'\'\' \'get\', \'post\', \'put\', \'patch\', \'delete\', \'head\', \'options\', \'trace\' form 只支持 post和 get ajax 支持 所有的方法 \'\'\'
ORM框架
1. 先配置mysql的连接地址
# 在settings.py文件中,写入自己需要连接的数据库 DATABASES = { # \'default\': { # \'ENGINE\': \'django.db.backends.sqlite3\', # \'NAME\': os.path.join(BASE_DIR, \'db.sqlite3\'), # } \'default\': { \'ENGINE\': \'django.db.backends.mysql\', \'NAME\':\'orm\', \'USER\': \'root\', \'PASSWORD\': \'123456\', \'HOST\': \'192.168.81.161\', \'PORT\': \'3306\', } }2. 在app中的
__init__.py文件中导入pymysql模块import pymysql pymysql.install_as_MySQLdb()3. 在app项目下models.py文件中创建表.一个类一个表
# 类需要继承models.Model from django.db import models # Create your models here. class UserInfo(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=32) age = models.CharField(max_length=32) ut = models.ForeignKey("UserType",null=True)4. 修改配置文件
把我们的应用添加到对应的settings.py的INSTALLED_APPS 中:
INSTALLED_APPS = [ \'django.contrib.admin\', \'django.contrib.auth\', \'django.contrib.contenttypes\', \'django.contrib.sessions\', \'django.contrib.messages\', \'django.contrib.staticfiles\', \'****\', #我们创建的应用 ]4. 创建表
python manage.py makemigrations ## 生成迁移文件 python manage.py migrate ## 生成实际的表 ps: 如果修改了models.py中的代码,需要重新执行上面的两行代码5. 基本操作
增
第一种方式 models.users.objects.create(username=\'xsmile\',password=12345) 第二种方式 a = {\'username\':"plf",\'passsword\':\'123456\'} models.users.objects.create(**a) 第三种方式:插入多条数据 info = [ models.UserInfo(name="root1",age=34,ut_id=1), models.UserInfo(name="root2",age=34,ut_id=2), models.UserInfo(name="root3",age=34,ut_id=3), models.UserInfo(name="root4",age=34,ut_id=4), models.UserInfo(name="root5",age=34,ut_id=5), models.UserInfo(name="root6",age=34,ut_id=6), models.UserInfo(name="root7",age=34,ut_id=7), ] models.UserInfo.objects.bulk_create(info)删除
Test.objects.filter(name__contains=\'jack\').delete()改
Test.objects.filter(name__contains=\'apollo1\').update(name=\'Jack\')查
单表查询
models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值 models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据 models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in models.Tb1.objects.filter(name__contains="ven") # 获取name字段包含"ven"的 models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感 models.Tb1.objects.filter(id__range=[1, 3]) # id范围是1到3的,等价于SQL的bettwen and 类似的还有:startswith,istartswith, endswith, iendswith date字段还可以: models.Class.objects.filter(first_day__year=2017)多表查询(外键查询)
1. 正向查询(通过关联的字段ut,直接使用点语法获取另外一张表的字段数据) objs = models.UserInfo.objects.filter(ut_id__gt=2,ut__title="正常员工") print(objs) for i in objs: print(f"id:{i.id} {i.name} {i.age} {i.ut.title}")
正向查询
第一种:按对象查找
语法
对象.关联字段.字段
book_obj = models.Book.objects.first() # 第一本书对象 print(book_obj.publisher) # 得到这本书关联的出版社对象 print(book_obj.publisher.name) # 得到出版社对象的名称第二种:按照字段查找
语法
关联字段__字段
print(models.Book.objects.values_list("publisher__name"))
反向查询
第一种:按照对象查找
语法
对象.表名_set
publisher_obj = models.Publisher.objects.first() # 找到第一个出版社对象 books = publisher_obj.book_set.all() # 找到第一个出版社出版的所有书 titles = books.values_list("title") # 找到第一个出版社出版的所有书的书名第二种:按照字段查找
语法
表名__字段
titles = models.Publisher.objects.values_list("book__title")