1. ORM常用字段和属性
1. AutoField(primary_key=True)
2. CharField(max_length=32)
3. IntgerField()
4. DateField()
5. DateTimeField()
1. auto_now_add --> 创建的时候自动填充当前时间
2. auto_now --> 每次修改的时候自动把当前时间更新
2. 关系字段
1. ForeignKey(to="类名",related_name=“xx”) --> 1对多 ,外键通常设置在多的那一边,related_name是反向查询使用
2. ManyToMany(to="类名",related_name="xx") --> 多对多,通常设置在正向查询多的那一边
3. ORM一般操作
1. 必知必会13条
1. 返回QuerySet对象的
1. all()
2. filter()
3. values()
4. values_list()
5. exclude()
6. order_by()
7. reverse()
8. distinct()
2. 返回具体对象的
1. get()
2. first()
3. last()
3. 返回布尔值的
1. exists()
4. 返回具体数值的
1. count()
2. 单表查询的双下划线
1. models.Book.objects.filter(id__gt=1) #查询id大于1的book对象
2. models.Book.objects.filter(id__in=[1,2,3]) #查询id在1,2,3中的的所有对象
3. models.Book.objects.filter(id__range=[1,5]) #查询id在1到5的范围的对象
4. models.Book.objects.filter(title__contains="沙河") #查询书名中包含沙河的所有对象
5. models.Book.objects.filter(title__icontains="沙河") #查询书名中包含沙河的所有对象,忽略大小写
6. models.Book.objects.filter(title__startswith="沙河") #查询书名是以沙河开头的所有对象
7. models.Book.objects.filter(title__endswith="沙河") #查询书名是以沙河结尾的所有对象
8. models.Book.objects.filter(publish_date__year=2017) #查询出版社出版年份是2017年的所有书的对象
9. models.Book.objects.filter(publish_date__month=2) #查询出版社月份是2月的所有书的对象
3. 外键的跨表查询
a.正向查找
1. 基于对象
book_obj = models.Book.object.get(id=1)
book_obj.publisher.name
2. 基于双下划线的
models.Book.objects.filter(id=1).values("publisher__name") # 先获取id为1的书的对象,然后到publisher的出版社对象中找name属性,values中一定要加引号和双下划线
如:
ret = models.Book.objects.filter(id=1).values('publisher__name')
print(ret)
<QuerySet [{'publisher__name': '清华大学出版社'}]>
b.反向查找(由出版社查书)
1. 基于对象
publisher_obj = models.Publisher.objects.get(id=1)
默认反向查找的时候是表名加_set
publisher_obj.book_set.all()
如果在外键中设置了related_name="books"
publisher_obj.books.all()
2. 基于双下划线
models.Publisher.objects.filter(id=1).values("book__title") #这里也是用的book
如果配置了related_query_name="books"
models.Publisher.objects.filter(id=1).values("books__title")
这里有个很大的疑惑,为什么反向查找时,表名Book不可以,要用小写的book呢,这个没有定义的:
class publisher(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(null=False, max_length=20)
class Book(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=64, null=False, unique=True)
price = models.DecimalField(max_digits=5, decimal_places=2, default=99.99)
publisher = models.ForeignKey(to='publisher')
publisher_obj = models.publisher.objects.get(id=9)
ret = publisher_obj.book_set.all() #如果用了Book会报错,没有这个属性
print(ret)
返回的对象??
<QuerySet [<Book: Book object>, <Book: Book object>]>
4. 分组和聚合
1. 聚合
from django.db.models import Avg, Sum, Max, Min, Count
models.Book.objects.all().aggregate(Avg("price"))
2. 分组
book_list = models.Book.objects.all().annotate(author_num=Count("author")) #先拿出所有的Book对象,然后按id分组,接着拿id去统计作者数量
#分组详解
ret = models.Book.objects.all().annotate(author_num=Count('authors')) #这里的authors是写了related_query_name='authors'
for i in ret:
print(i.author_num)
#返回的对象和sql语句
(0.000) SELECT @@SQL_AUTO_IS_NULL; args=None
(0.069) SELECT `app_publisher_book`.`id`, `app_publisher_book`.`title`, `app_publisher_book`.`price`, `app_publisher_book`.`publisher_id`, `app_publisher_book`.`author_id`, COUNT(`app_publisher_author_book`.`author_id`) AS `author_num` FROM `app_publisher_book` LEFT OUTER JOIN `app_publisher_author_book` ON (`app_publisher_book`.`id` = `app_publisher_author_book`.`book_id`) GROUP BY `app_publisher_book`.`id` ORDER BY NULL; args=()
3
3
3
1
[Finished in 1.7s]
5. F和Q
1. 当需要字段和字段作比较的时候用F查询
2. 当查询条件是 或 的时候 用Q查询,因为默认的filter参数都是且的关系
6. 事务
保证数据的原子性操作!!!
import os
if __name__ == '__main__':
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings")
import django
django.setup()
import datetime
from app01 import models
try:
from django.db import transaction #导入事务模块
with transaction.atomic(): #使用with关键字,如果下面的内容出错,程序会自动回滚,把执行过的sql语句回滚到最原始的状态
new_publisher = models.Publisher.objects.create(name="火星出版社")
models.Book.objects.create(title="橘子物语", publish_date=datetime.date.today(), publisher_id=10) # 指定一个不存在的出版社id
except Exception as e:
print(str(e))
7. 执行原生的SQL语句(了解即可)
CSRF跨站请求伪造
1. 钓鱼网站的页面和正经网站的页面对浏览器来说有什么区别? (页面是怎么来的?)
钓鱼网站的页面是由 钓鱼网站的服务端给你返回的
正经网站的网页是由 正经网站的服务端给你返回的
2. Django中内置了一个专门处理csrf问题的中间件
django.middleware.csrf.CsrfViewMiddleware
这个中间件做的事情:
1. 在render返回页面的时候,在页面中塞了一个隐藏的input标签
用法:
我们在页面上 form表单 里面 写上 {% csrf_token %}
<input type="hidden" name="csrfmiddlewaretoken" value="8gthvLKulM7pqulNl2q3u46v1oEbKG7BSwg6qsHBv4zf0zj0UcbQmpbAdijqyhfE">
2. 当你提交POST数据的时候,它帮你做校验,如果校验不通过就拒绝这次请求