Django2.0版本ORM实操都在这里??????????Django请求生命周期是什么?进来看了就明白Django2.0版本路由和有名无名分组到底和Django1.0版本有什么区别?如何实现反向解析?我已经总结好了~ 
ORM:对象映射关系程序
通过orm将编程语言的对象模型和数据库的关系模型建立映射关系,这样我们在使用编程语言对数据库进行操作的时候可以直接使用编程语言的对象模型进行操作就可以了,而不用直接使用sql语言;
python与MySQL映射关系
| Python | 映射 | MySQL |
|---|---|---|
| 类 | -------> | 表 |
| 对象 | -------> | 表里面的数据 |
| 对象点属性 | -------> | 字段对应的值 |
?我们的模型类需要写在应用下的models.py文件中
# SQL原生语句和ROM创建的区别class User(models.Model): # id int primary key auto_increment id = models.AutoField(primary_key=True) # name varchar(32) name = models.CharField(max_length=32) # CharField必须要加max_length参数 # age int age = models.IntegerField()???数据库迁移命令(重点)
models.py文件执行了和数据库相关的命令,就重新执行下面这两条命令:python3 manage.py makemigrations、python3 manage.py migrateRUN manage.py Task,输入makemigrations 1.将数据库修改操作先记录到"本本"(对应应用下的migrations文件夹) python3 manage.py makemigrations# 执行完,产生一个文件,用来记录 2.真正的执行数据库迁移操作,同步到数据库 python3 manage.py migrate# 执行完会在数据库中产生Django所需的依赖表,自动创建的 # 自己创建的表user以'应用名_表名'的形式创建,app01_user??不指定id字段和主键等,ORM会自动创建id
# 如果你不指定主键 那么orm会自动帮你创建一个名为id的主键字段class user(models.Model): username = models.CharField(max_length=32) # 就不用写id了···,需要定制id,就写上~# 原来的表class user(models.Model): username = models.CharField(max_length=32) # 增加字段(两种方法) password = models.IntegerField('密码',null=True) # 该字段可以为空 is_delete = models.IntegerField(default=0) # 默认值 # 修改字段直接改代码,然后执行makemigrations,数据库迁移# 删除直接删除或者注释掉代码,然后执行makemigrations,数据库迁移查询操作
username = request.POST.get('username')# 获取用户post从页面提交的数据,username是获取到用户提交的数据# 1.查询数据# select * from user where name=username;user_obj_list = models.User.objects.filter(name=username) # 获取到的是列表,看成列表套数据对象 obj_info = user_obj_list[0]# 获取id、name、ageprint(obj_info.id, obj_info.name, obj_info.age) # 1 hammer 18# 或这下面这样提取列表数据也可以user_obj = models.User.objects.filter(name=username).first()'''如果用户提交的信息不存在返回None'''# 登录功能示例user_check = models.User.objects.filter(name=username,password=password).first() # 等价于select * from user where name=username and pwd = passwordif user_check: return HttpResponse('登录成功')# 2.添加数据# insert into user(name,pwd) values(username,password);models.User.objects.create(name=username,pwd=password)# 3.查询所有的数据,展示所有数据到前端页面,通过for循环在html页面获取表数据# select * from user;models.User.objects.all() # 返回列表[obj1,obj2,obj3,obj4]# 4.修改数据models.User.objects.filter(id=edit_id).update(name=username,pwd=password)# 或者edit_obj.name = usernameedit_obj.pwd = passwordedit_obj.save()# 5.删除数据models.User.objects.filter(id=delete_id).delete()数据库迁移命令,链接
python manage.py makemigrations
inspectdb 表名语句反向操作数据库,反向输出sql语句对应的类
ps:如果inspectdb后不跟表名,那么就会将该数据库内的所有表反向解析成类(python语句)
# 数据库里面已经有一些表,我们如何通过django orm操作?1.照着数据库表字段自己在models.py2.django提供的反向同步操作:1.先执行数据库迁移命令 完成链接 python manage.py makemigrations2.查看代码 python manage.py inspectdb class Userinfo(models.Model): id = models.IntegerField(blank=True, null=True) name = models.CharField(max_length=32, blank=True, null=True) pwd = models.IntegerField(blank=True, null=True) class Meta: managed = False db_table = 'userinfo'表与表之间的关系有一下三种:
一对多、多对多、一对一,没关系暂且排外,下面演示如何通过ORM来创建外键确立表关系~
ORM创建外键字段的位置:
# 创建书籍表 出版者表 作者表# 先写表的基本结构,在考虑表关系如何写外键# 书籍表class Book(models.Model): name = models.CharField(max_length=32) price = models.DecimalField(max_digits=8, decimal_places=2) # 总共8位 小数占2位 # 作者外键 Author = models.ManyToManyField(to='Author') # 出版社外键 Publish = models.ForeignKey(to='Publish',on_delete=models.CASCADE) # 作者表class Author(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() Atuhor_Detail = models.OneToOneField(to='Atuhor_Detail',on_delete=models.CASCADE)# 作者详情表class Atuhor_Detail(models.Model): phone = models.BigIntegerField() Email = models.EmailField()# 出版社表class Publish(models.Model): name = models.CharField(max_length=32) address = models.CharField(max_length=32)注意:


外键被当作虚拟字段,创建表完成后,不会实例化出来,而是告诉了ORM创建第三张表的关系
Django2.0版本以上,在创建外键和一对一关系的时候,需要添加级联更新参数on_delete=models.CASCADE,不然会报错,只有OneToOneField和ForeignKey需要写,ManyToManyField不需要
# django 升级到2.0之后,表与表之间关联的时候,必须要写on_delete参数,否则会报异常:# TypeError: init() missing 1 required positional argument: ‘on_delete’Atuhor_Detail = models.OneToOneField(to='Atuhor_Detail',on_delete=models.CASCADE)Publish = models.ForeignKey(to='Publish',on_delete=models.CASCADE)
??path官网文档
??URL调度
??“江狗”
在新版本Django2.x中,
url的路由表示用path和re_path代替;模块的导入由django1.x版本的
from django.conf.urls import url,include变成现在的Django2.x中的from django.urls import path, re_path, include
Django提供了两种设计URL的方法: path和re_path,它们均支持向视图函数或类传递参数。path是正常参数传递,re_path是采用正则表达式regex匹配;
path方法:采用双尖括号<变量类型:变量名>或<变量名>传递,例如<int:id>, <slug:slug>或<username>。re_path方法: 采用命名组(?P<变量名>表达式)的方式传递参数。path支持匹配的数据类型只有str,int, slug, uuid四种。一般来说re_path更强大,但写起来更复杂一些简单示例
'''urls.py'''from django.contrib import adminfrom django.urls import path,re_path,includefrom app01 import viewsurlpatterns = [ # 路由匹配 re_path(r'test',views.test), re_path(r'testadd',views.testadd)]'''views.py'''from django.shortcuts import render,HttpResponse,redirect# Create your views here.def test(request): return HttpResponse('from test')def testadd(request): return HttpResponse('from testadd')'''这样匹配的话,相当于使用正则表达式,如果url后面写test返回fromtest,那么再写testadd呢?也会返回from test,这是一种包含关系,需要更明确的去区别,比如写test/,或者testadd/,建议在末尾加上/'''urlpatterns = [ path('admin/', admin.site.urls), # 限制开头 re_path(r'^test/',views.test), # 限制开头和结尾 re_path(r'^testadd/$',views.testadd)]/,那么会自动补充/,相当于跳转页面,如果不想使用该特性,可以在setting.py文件中取消:APPEND_SLASH = False
下例中,我们分别以path和re_path 定以了两个urls,它们是等效的,把文章的id(整数类型)传递给了视图。re_path里引号前面的小写r表示引号里为正则表达式, ^代表开头,$代表以结尾,\d+代表正整数
# blog/urls.pyfrom django.urls import path, re_pathfrom . import views urlpatterns = [ path('blog/articles/<int:id>/', views.article_detail, name = 'article_detail'), re_path(r'^blog/articles/(?P<id>\d+)/$', views.article_detail, name='article_detail'),] # blog/views.pydef article_detail(request, id): # 展示某篇文章在使用path和re_path方法设计urls需注意:
/,但建议以斜杠结尾;re_path时不一定总是以$结尾,有时不能加。比如下例中把blog.urls通过re_path加入到项目urls中时就不能以$结尾,因为这里的blog/并不是完整的url,只是一个开头而已。from django.urls import include, re_pathurlpatterns = [ re_path(r'^blog/', include('blog.urls')), ...]涉及到urls.py写对应关系,无名分组后如果不给视图函数传参,那么就会报错
通俗理解:路由使用正则,正则匹配加括号分组,当作了视图函数的第二个位置参数
'''urls.py'''from django.contrib import adminfrom django.urls import path,re_path,includefrom app01 import viewsurlpatterns = [ path('admin/', admin.site.urls), # 匹配数字 # re_path(r'^test/[0-9]{4}/$',views.test), # 无名分组,匹配1个到多个正整数 re_path(r'^test/(\d+)/$',views.test),]'''views.py'''def test(request,num): print(num) # 1234 return HttpResponse('from test')'''路由使用正则,正则匹配加括号分组,当作了视图函数的第二个位置参数'''在使用路由的时候,正则表达式可以起别名,别名当作关键字参数传给视图函数;
没有按关键字参数写报错

按别名,传参
'''urls.py'''urlpatterns = [re_path(r'^test/(?P<id>\d+)/$',views.test),]'''views.py'''def test(request,id): print(id) return HttpResponse('from test')# 有名分组,将匹配到的数字命名成id,当成关键字参数传给视图函数注意:
无名分组和有名分组不能混合使用
re_path(r'^test/(\d+)/(?P<id>\d+)/$',views.test)def test(request,a,id): print(a,id) return HttpResponse('from test')# 这样不可以相同分组可以混合使用
re_path(r'^testadd/(\d+)/(\d+)/$',views.testadd)def testadd(request,*args,**kwargs): return HttpResponse('from testadd')# 这样使用相同分组是可以的反向解析解决了当路由频繁变化的时候,html界面上的连接地址实现动态解析;
'''urls.py'''# 1、给路由与视图函数对应关系添加一个别名from django.contrib import adminfrom django.urls import path,re_path,includefrom app01 import viewsurlpatterns = [ path('admin/', admin.site.urls), # 反向解析 path('index/',views.index,name='index_name'), path('home/',views.home)]'''views.py'''from django.shortcuts import HttpResponse,render,reversedef index(request): return HttpResponse('from index')def home(request): print(reverse('index_name')) # 或者 # return redirect('index_name') return render(request,'home.html')'''home.html'''<a href="{% url 'index_name' %}">111</a><a href="{% url 'index_name' %}">111</a><a href="{% url 'index_name' %}">111</a>总结:
当路由频繁变化的时候,html界面上的连接地址如何做到动态解析# 1.给路由与视图函数对应关系添加一个别名(名字自己指定 只要不冲突即可) url(r'^index/',views.index,name='index_name')# 2.根据该别名动态解析出一个结果,该结果可以直接访问到对应的路由 前端 <a href="{% url 'index_name' %}">111</a> 后端 from django.shortcuts import reverse reverse('index_name') ps:redirect括号内也可以直接写别名如果有分组的情况,不写数字参数会报错
'''路由'''urlpatterns = [ path('admin/', admin.site.urls), # 反向解析 re_path(r'index/(\d+)/',views.index,name='index_name'), path('home/',views.home)]'''后端'''def index(request): return HttpResponse('from index')def home(request): print(reverse('index_name')) return render(request,'home.html')'''前端'''<a href="{% url 'index_name' %}">111</a>
无名分组反向解析
# 无名分组1、起别名url(r'^index/(\d+)/',views.index,name='index_name')2、前端<a href="{% url 'index_name' 1 %}"></a> # 只要给个数字即可3、后端reverse('index_name',args=(1,)) # 只要给个数字即可有名分组反向解析
# 无名分组1、起别名url(r'^index/(?P<id>\d+)/',views.index,name='index_name')2、前端<a href="{% url 'index_name' id=1 %}"></a> # 只要给个数字即可3、后端reverse('index_name',kwargs={'id':1}) # 只要给个数字即可总结:
url和Django1.0一样,一定要区别开来def index(request,id): return render(request,'home.html')# id一般是获取到的主键值??参考文献:大江狗