一、模型层及ORM
1.模型层定义
负责跟数据库之间进行通信
2.Django配置mysql
安装mysqlclient,mysqlclient版本最好在13.13以上
pip3 install mysqlclient
DATABASES = {'default': {'ENGINE': 'django.db.backends.mysql','NAME': "mysite1",'USER':'root','PASSWORD':'123456','HOST':'127.0.0.1','PORT':'3306',}
}
3.什么是模型
4.ORM框架
映射图
5.数据库迁移
6.模型类创建
示例
from django.db import modelsclass Book(models.Model):title = models.CharField(verbose_name='书名',max_length=50,default='')price = models.DecimalField(verbose_name='价格',max_digits=7,decimal_places=2)
小结:
任何关于表结构的修改,都要在模型类上进行修改
解决方案
- 模型类中添加 对应 类属性
- 执行数据库迁移
二、基础字段及选项1
1.字段类型
auto_now() - 用作更新时间字段
aotu_now_add - 用作创建时间 字段
用于价格、钱相关的字段
EmailField - 用于邮箱字段
ImageField() - 图片
三、基础字段及选项2
1.字段选择项
指定创建的列的额外信息
允许出现多个字段选项,多个选项之间使用逗号隔开
null和blank区别:
null是针对数据库而言
blank是针对表单的
示例
2.Meta类
使用内部Meta类来给模型赋予属性
示例
from django.db import models# Create your models here.
from django.db import modelsclass Book(models.Model):title = models.CharField('书名',max_length=5,unique=True,default='')pub = models.CharField('出版社',max_length=100,default='')price = models.DecimalField('价格',max_digits=7,decimal_places=2)market_price = models.DecimalField('零售价',max_digits=7,decimal_places=2,default=0.0)info = models.CharField('描述',max_length=100,default='')class Meta:db_table = 'book'class Author(models.Model):name = models.CharField('姓名',max_length=11,null=False)age = models.IntegerField('年龄',default=1)email = models.EmailField('邮箱',null=True)class Meta:db_table = 'author'
小结:
常见问题1:
常见问题2:
四、ORM基本操作
1.ORM创建数据
ORM基本操作包括增删改查,即CRUD
核心
模型类.管理器对象
2.管理器对象
示例
3.创建数据
方案一、
Model.objects.create(属性1=值1,。。。。)
成功:返回创建好的实体对象
失败:抛出异常
方案二、
创建Molde实例化对象,并调用save()保存
obj = Model(属性=值,。。。)
obj.属性 = 值
obj.save()
4.Django Shell
利用django shell可以代替编写view的代码来进行直接操作
启动方式:python manage.py shell
from bookstore.models import Book
b1 = Book.objects.create(title='Java',pub='清华大学出版社',price=20,market_price=68,info='java入门到入土')
b2 = Book(title='VUE',pub='清华大学出版社',price=30,market_price=108,info='VUE入门')
b2.save()
五、ORM查询操作1
1.查询简介
通过管理器方法调用查询方法
2.查询方法
bb1 = Book.objects.all()
for book in bb1:
... print(book.title)
...
可以在模型类中定义__str__方法,自定义QuerySet的输出格式
def __str__(self):
return '%s%s%s%s%s'%(self.title,self.pub,self.price,self.market_price,self.info)
在Django Shell 中输出如下
<QuerySet [<Book: Java清华大学出版社20.0068.00java入门到入土>, <Book: VUE清华大学出版社30.00108.00VUE入门>, <Book: Dj清华大学出版社70.00178.00Django入门>,
<Book: JS机械出版社90.00198.00JS入门>, <Book: Linux机械出版社80.00188.00Linux入门>, <Book: HTML清华大学出版社90.00198.00HTML入门>]>
>>>
示例
>>> b2 = Book.objects.values('title','pub')
>>> b2
输出
<QuerySet [{'title': 'Java', 'pub': '清华大学出版社'}, {'title': 'VUE', 'pub': '清华大学出版社'}, {'title': 'Dj', 'pub': '清华大学出版社'}, {'title': 'JS', 'pub': '机械出版社'}, {'title': 'Linux', 'pub': '机械出版社'}, {'title': 'HTML', 'pub': '清华大学出版社'}]>
>>>
示例
>>> b3 = Book.objects.order_by('-price')
>>> for book in b3:
... print(book.price)
...
输出
90.00
90.00
80.00
70.00
30.00
20.00
查询案例:
总路由:
path('bookstore/',include('bookstore.urls')),
子路由:
from django.urls import path,re_path,include
from . import views
urlpatterns = [path('all_book',views.all_book),
]
视图:
from django.shortcuts import render
from bookstore.models import Book
# Create your views here.
def all_book(request):book = Book.objects.all().order_by('-id')return render(request,'bookstore/test_book.html',locals())
模板:
<body><table border="1"><thead><tr><th>id</th><th>标题</th><th>出版社</th><th>价格</th><th>零售价</th><th>操作</th></tr></thead><tbody>{% for book in book %}<tr><td>{{book.id}}</td><td>{{book.title}}</td><td>{{book.pub}}</td><td>{{book.price}}</td><td>{{book.market_price}}</td><td><a href="#">更新</a><a href="#">删除</a></td></tr>{% endfor %}</tbody></table>
</body>
六、ORM查询操作2
1.条件查询
样例
示例
2.查询谓词
__exact:等值匹配
模糊查询
__contains:包含指定的值
__startswith:以xxx开始
__endswith:以xxx结束
__gt:大于指定值
__gte:大于等于指定值
__lt:小于指定值
__lte:小于等于指定值
__in:查找数据是否在指定范围内
__range:查找数据是否在指定的区间范围内
七、ORM更新数据
1.更新单个数据
b1 = Book.objects.get(id=1)
>>> b1
<Book: Java清华大学出版社20.0068.00java入门到入土>
>>> b1.price = 22
>>> b1.save()
2.批量更新数据
直接调用QuerySet的update(属性=值)实现批量修改
url
path('update_book/<int:book_id>',views.update_book),
view
def update_book(request,book_id):try:book = Book.objects.get(id=book_id)except Exception as e:return HttpResponse('书不存在')print(book)if request.method == 'GET':return render(request,'bookstore/update_book.html',locals())elif request.method == 'POST':price = request.POST['price']market_price = request.POST['market_price']#改book.price = pricebook.market_price = market_price#保存book.save()# book = Book.objects.all().order_by('-id')# return render(request,'bookstore/test_book.html',{"book":book})return HttpResponseRedirect('/bookstore/all_book')
template
<form action="/bookstore/update_book/{{book.id}}" method="post"><p>title<input type="text" value="{{book.title}}" disabled="disabled"></p><p>pub<input type="text" value="{{book.pub}}" disabled="disabled"></p><p>price<input type="text" value="{{book.price}}" name="price"></p><p>market_price<input type="text" value="{{book.market_price}}" name="market_price"></p><p>info<input type="text" value="{{book.info}}" name="info"></p><p><input type="submit" value="更新"></p></form>
八、ORM删除
1.单个数据删除
2.批量删除
3.伪删除
url
path('delete_book',views.delete_book),
view
def delete_book(request):book_id = request.GET.get('book_id')if not book_id:return HttpResponse('请求异常')try:book = Book.objects.get(id=book_id,is_activ=True)except Exception as e:return HttpResponse('id错误')book.is_activ = Falsebook.save()return HttpResponseRedirect('/bookstore/all_book')
九、F对象和Q对象
1.F对象
可以应用于点赞
2.Q对象
小结:
F对象:标记字段
Q对象:或与非
十、聚合查询和原生数据库
1.聚合查询
如:查询BOOK数据表中的全部书的平均价格,查询所有书的总个数等,都要用到聚合查询
聚合查询分为:
- 整表聚合
- 分组聚合
2.整表聚合
聚合函数【需要导入】
>>> from django.db.models import *
>>> Book.objects.aggregate(res=Count('id'))
{'res': 6}
3.分组聚合
>>> bs = Book.objects.values('pub')
>>> bs.annotate(res=Count('id'))
<QuerySet [{'pub': '清华大学出版社', 'res': 4}, {'pub': '机械出版社', 'res': 2}]>
>>>
>>> bs.annotate(res=Count('id')).filter(res__gt=2)
<QuerySet [{'pub': '清华大学出版社', 'res': 4}]>
>>> ss = bs.annotate(res=Count('id')).filter(res__gt=2)
>>> print(ss.query)
SELECT `book`.`pub`, COUNT(`book`.`id`) AS `res` FROM `book` GROUP BY `book`.`pub` HAVING COUNT(`book`.`id`) > 2 ORDER BY NULL
4.原生数据库
查询:
语法:
返回值:
使用原生数据库操作时,小心SQL注入
完全跨过模型类操作数据库 -查询/更新/删除
十一、admin后台管理1
admin配置步骤
创建后台管理帐号-该账号是管理后台最高权限帐号
python manage.py createsuperuser
Username (leave blank to use 'administrator'): admin
Email address: 1353973780@qq.com
Password:
Password (again):
Superuser created successfully.
127.0.0.1:8000/admin
十二、admin后台管理2
1.注册自定义模型类
若自己定义的模型类也能在admin后台管理中显示和管理,需要将自己的类注册到后台管理界面
注册步骤:
admin.py中
from .models import Bookadmin.site.register(Book)
2.修改自定义模型类的数据样式
在用户自定义的模型类中可以重写 def__str__(self)方法
models.py
class Book(models.Model):title = models.CharField('书名',max_length=5,unique=True,default='')pub = models.CharField('出版社',max_length=100,default='')price = models.DecimalField('价格',max_digits=7,decimal_places=2)market_price = models.DecimalField('零售价',max_digits=7,decimal_places=2,default=0.0)info = models.CharField('描述',max_length=100,default='')is_activ = models.BooleanField('是否活跃',default=True)class Meta:db_table = 'book'def __str__(self):return '%s%s%s%s%s'%(self.title,self.pub,self.price,self.market_price,self.info)
3.模型管理器类
作用:为后台管理界面添加便于操作的新功能
说明:后台管理器类须继承自dajngo.contrib.admin里面的ModelAdmin
使用方法
案例
class BookManage(admin.ModelAdmin):#列表页显示哪些字段的列list_display = ['id','title','price','market_price']#控制list_play中的字段 哪些可以链接到修改页list_display_links = ['title']#添加过滤器list_filter = ['pub']#添加搜索查询(模糊)search_fields = ['title']#添加可在列表页编辑的字段list_editable=['price']
admin.site.register(Book,BookManage)
4.再谈Meta
models.py
class Book(models.Model):title = models.CharField('书名',max_length=5,unique=True,default='')pub = models.CharField('出版社',max_length=100,default='')price = models.DecimalField('价格',max_digits=7,decimal_places=2)market_price = models.DecimalField('零售价',max_digits=7,decimal_places=2,default=0.0)info = models.CharField('描述',max_length=100,default='')is_activ = models.BooleanField('是否活跃',default=True)class Meta:db_table = 'book'verbose_name = '图书'verbose_name_plural = verbose_name
十三、关系映射1
1.什么是关系映射
通常不会将数据放到同一张表中,常见的关系映射
一对一
一对多
多对多
2.一对一映射
语法:OneToOneField(类名,on_delete=xxx)
class A(models.Model):
....
class B(models.Model):
属性=models.OneToOneField(A,on_delete=xxxx)
特殊字段选项【必须】
on_delete - 级联删除
models.CASCADE 级联删除
models.PROTECT 抛出ProtectedError以阻止被引用对象的删除
SET_NULL 设置ForeignKey null;需要指定null=true
SET_DEFAULT 将 ForeignKey设置为其默认值;必须设置ForeignKey的默认值
from django.db import models# Create your models here.
class Author(models.Model):name = models.CharField('姓名',max_length=11)class Wife(models.Model):name = models.CharField('姓名',max_length=11)author = models.OneToOneField(Author,on_delete=models.CASCADE)
一对一【创建数据】
- 无外键的模型类[Author]
author1 = Author.objects.create(name = 'xxx')
- 有外键的模型类[Wife]
#关联xxx老师obj
1.wife1 = Wife.objects.create(name='x1x',author=author1)
#关联xxx老师对应主键值
1.wife1 = Wife.objects.create(name='x1x',author_id=1) #author_id后写外键所对应的id
一对一【查询数据】
正向查询:直接通过外键属性查询,则称为正向查询
#通过wife找author
from .models import author
wife = wife.objects.get(name='赵夫人')
print(wife.name,'的老公是',wife.author.name)
反向查询:没有外键属性的乙方,可以调用反向属性()查找到关联的另一方
反向属性:models中创建类是django自带的
当反向引用不存在时,会触发异常
author1= Author.objects.get(name=’赵老师‘)
author1.wife.name
十四、关系映射2
1.一对多-定义
明确具体角色,在多表上设置外键
如一个学校多个班级,一个班级多个学生
2.一对多-创建
语法:
当一个A类可以关联多个B类对象时
class A(models.Model):
...
class B(models.Model):
属性 = models.ForeignKey(A,on_delete = models.CASCADE3)
ForeignKey必须指定on_delete模式
3.一对多-数据创建
先创建一,在创建多
>>> from otm.models import *
>>> pub1 = Publisher.objects.create(name='清华大学出版社')
>>> BOok.objects.create(title='C++',publisher=pub1)
>>> BOok.objects.create(title='Java',publisher_id=1)
4.一对多-查询数据
正向查询 通过publisher属性查询即可
通过书查询出版社
>>> b1 = BOok.objects.get(id=1)
>>> b1.publisher.name
'清华大学出版社'
反向查询 通过Publisher查询 对应的所有的BOok
通过出版社查询书
>>> pub = Publisher.objects.get(id=1)
>>> books = BOok.objects.filter(publisher=pub)
### >>>books = pub.book_set.all() 类名小写_set
>>> for item in books:
... print(item.title)
...
C++
Java
C
5.多对多-定义
如每个人都有不同的学校,每个学校都有不同的学生
- mysql中创建多对多需要依赖第三章表来实现
- Django中无需手动创建第三张表,Django自动完成
语法:
属性 = models.ManyToManyField(MyModel)
6.多对多-创建
#作者
class Author(models.Model):name = models.CharField('姓名',max_length=11)
#书籍
class Book(models.Model):title = models.CharField('书名',max_length=11)authors = models.ManyToManyField(Author)
7.多对多-数据的创建
方案一、先创建author在关联book
两个作家同时写了一本书
>>> from mtm.models import *
>>> author1 = Author.objects.create(name='赵老师')
>>> author3 = Author.objects.create(name='张老师')
>>> book1 = author1.book_set.create(title='Python')
>>> author3.book_set.add(book1)
一个作家写两本书
>>> 一个作家写两本书
>>> author1 = Author.objects.create(name='赵老师')
>>> book1 = author1.book_set.create(title='Python')
>>> book2 = author1.book_set.create(title='Java')
方案二、先创建Book在关联author
>>> book4 = Book.objects.create(title='JS')
>>> author2 = book.authors.create(name='xxxx')
>>> book.authors.add(author3)
8.多对多-查询
正向查询 有多对多属性的对象 查 另一个,即谁有桥 用有桥的对象 查另一个
通过book查对应的所有Author
book.authors.all() 获取book对应的所有的author信息
book.authors.filter(age__gt=80) 获取book对应的作者中年龄大于80的作者信息
反向查询
通过author查询对应的所有的book
利用反向属性book_set
author.book_set.all()
author.book_set.filter()
十五、cookies和sessions
1.会话定义
从打开浏览器访问一个网站,到关闭浏览器结束此次访问,称之为一次绘画,
HTTP协议是无状态的,导致绘画状态难以保持
Cookies和Session就是为了保持会话状态而诞生的两个存储技术
2.Cookies定义
是保存在客户端浏览器上的存储空间
Chrome浏览器可以通过打开开发者工具的Application-》Storage-》Cookies查看和操作浏览器端所有的Cookies值
3.Cooies特点
cookies在浏览器上是以键-值对的形式进行存储的,键值不能是中文
存储的数据带有声明周期
cookies中的数据是按域存储隔离的,不同的域之间无法访问
cookies的内部数据会在每次访问网址时都会携带到服务器端,如果cookies过大会降低响应速度
4.Cookies的使用-存储
例如:
urls
path('set_cookies',view.set_cookies),
view
def set_cookies(request):resp = HttpResponse('set cookies is ok')resp.set_cookie('uuname','zpw',500)return resp
只要调用set_cookie这个方法,响应中就会有暗号
修改cookie 就是用set_cookie重新赋值
5.Cooies的使用-删除&获取
获取
通过request.COOKIE 获取客户端的COOKIES数据
value = request.COOKIES.get('cookies名','默认值')
例如
urls
path('get_cookies',view.get_cookies),
view
def get_cookies(request):value = request.COOKIES.get('uuname')return HttpResponse('value is %s'%(value))
删除
删除指定的key的Cookie。如果key不存在则什么也不发生
HttpResponse.delete_cookie(key)
responds = HttpResponse("已删除 xxxx")
responds.delete_cookie('xxxx')
return responds
十六、cookies和session-2
cookie实则是将数据存在浏览器上,session是将数据存在服务器上
1.session定义
session是在服务器上开辟一段空间用于保留浏览器和服务器交互时的重要数据
实现方式
-使用session需要在浏览器客户端启动cookie,且在cookie中存储sessionid
每个客户端都可以在服务器端有一个独立的Session
-与请求者一一对应,不会共享数据
2.session初始配置
settings.py中配置session
启用session的应用
INSTALLED_APPS = [
'django.contrib.sessions',
]
启用session中间件
MIDDLEWARE = [
'django.contrib.sessions.middleware.SessionMiddleware',,
]
3.session的使用
1.保存session的值到服务器
request.session['KEY' ]=Value
2.获取session的值
value = request.session['KEY'] #强取
value = request.session.get('KEY',None)
3.删除session
del request.session['KEY']
4.在settings中相关的配置
SESSION_COOKIE_AGE
作用:指定sessionID在cookies中的保存时长(默认是2周),如下
SESSION_COOKIE_AGE=60*60*24*7*2
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
设置只要浏览器关闭时,session就失效(默认False)
5.Django session的问题
django_session表是单表设计;且该表数据量持续增大
可以写一个定时器每天执行 python3 manage.py clearsessions 【该命令可删除已经过期的session数据】
cookie和session对比