Django ORM执行原生SQL
# extra
# 在QuerySet的基础上继续执行子语句
# extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
# select和select_params是一组,where和params是一组,tables用来设置from哪个表
# Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,))
# Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
# Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])
# Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid'])
举个例子:
models.UserInfo.objects.extra(
select={'newid':'select count(1) from app01_usertype where id>%s'},
select_params=[1,],
where = ['age>%s'],
params=[18,],
order_by=['-age'],
tables=['app01_usertype']
)
"""
select
app01_userinfo.id,
(select count(1) from app01_usertype where id>1) as newid
from app01_userinfo,app01_usertype
where
app01_userinfo.age > 18
order by
app01_userinfo.age desc
"""
# 执行原生SQL
# 更高灵活度的方式执行原生SQL语句
# from django.db import connection, connections
# cursor = connection.cursor() # cursor = connections['default'].cursor()
# cursor.execute("""SELECT * from auth_user where id = %s""", [1])
# row = cursor.fetchone()
ORM 执行原生SQL的方法
Django终端打印SQL语句
在Django项目的settings.py文件中,在最后复制粘贴如下代码:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}
即为你的Django项目配置上一个名为django.db.backends的logger实例即可查看翻译后的SQL语句。
在Python脚本中调用Django环境
import os
if __name__ == '__main__':
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings")
import django
django.setup()
from app01 import models
books = models.Book.objects.all()
print(books)
多对多的三种方式
多对多的方式:
1. ORM自动帮我创建第三张表
models.ManyToManyField(to="Book", related_name="authors")
2. 自己创建第三张表, 利用外键分别关联作者和书
# 书
class Book(models.Model):
title = models.CharField(max_length=32)
publish_date = models.DateField(auto_now_add=True)
price = models.DecimalField(max_digits=5, decimal_places=2)
# 创建外键,关联publish
publisher = models.ForeignKey(to="Publisher")
def __str__(self):
return self.title
# 作者
class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
phone = models.IntegerField()
def __str__(self):
return self.name
# 自己动手 创建作者和书关联的第三张表
# 此时 在ORM层面 作者和书就没有多对多的关系了
class Author2Book(models.Model):
id = models.AutoField(primary_key=True)
# 作者id
author = models.ForeignKey(to="Author")
# 书id
book = models.ForeignKey(to="Book")
class Meta:
# 建立唯一约束
unique_together = ("author", "book")
关联查询比较麻烦,因为没办法使用ORM提供的便利方法
3. 自己创建第三张表,使用ORM 的ManyToManyFiled()
from django.db import models
# Create your models here.
from django.db import models
# Create your models here.
from django.db import models
# Create your models here.
# 出版社
class Publisher(models.Model):
name = models.CharField(max_length=32)
city = models.CharField(max_length=32)
def __str__(self):
return self.name
# 书
class Book(models.Model):
title = models.CharField(max_length=32)
publish_date = models.DateField(auto_now_add=True)
price = models.DecimalField(max_digits=5, decimal_places=2)
# 创建外键,关联publish
publisher = models.ForeignKey(to="Publisher")
def __str__(self):
return self.title
# 作者
class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
phone = models.IntegerField()
# 通过through,告诉Django通过哪张表建立关系,through_fields来指定使用我创建的第三张表来构建多对多的关系
books = models.ManyToManyField(to="Book", through="Author2Book", through_fields=("author", "book",))
# 第一个字段: 多对多设置在哪一张表里, 第三张表通过什么字段找到这张表(Author) 就把这个字段写在前面
detail = models.OneToOneField(to="AuthorDetail")
def __str__(self):
return self.name
# 自己动手 创建作者和书关联的第三张表
# 此时 在ORM层面
class Author2Book(models.Model):
id = models.AutoField(primary_key=True)
# 作者id
author = models.ForeignKey(to="Author")
# 书id
book = models.ForeignKey(to="Book")
# memo
memo = models.CharField(max_length=64, null=True)
class Meta:
# 建立唯一约束
unique_together = ("author", "book")
# 作者详情
class AuthorDetail(models.Model):
# 爱好
hobby = models.CharField(max_length=32)
# 地址
addr = models.CharField(max_length=128)
使用此种方式创建多对多表的时候,没有 add() remove() 等方法
我们应该用哪种?
看情况:
1. 如果你第三张表没有额外的字段,就用第一种
2. 如果你第三张表有额外的字段,就用第三种或第一种
csrf简单用法
什么是CSRF ————跨站请求伪造
问题:
1. 钓鱼网站的页面和正经网站的页面对浏览器来说有什么区别? (页面是怎么来的?)
钓鱼网站的页面是由 钓鱼网站的服务端给你返回的
正经网站的网页是由 正经网站的服务端给你返回的
2. Django中内置了一个专门处理csrf问题的中间件
django.middleware.csrf.CsrfViewMiddleware
这个中间件做的事情:
1. 在render返回页面的时候,在页面中塞了一个隐藏的input标签
用法:
我们在页面上 form表单 里面 写上 {% csrf_token %}
<input type="hidden" name="csrfmiddlewaretoken" value="8gthvLKulM7pqulNl2q3u46v1oEbKG7BSwg6qsHBv4zf0zj0UcbQmpbAdijqyhfE">
2. 当你提交POST数据的时候,它帮你做校验,如果校验不通过就拒绝这次请求