其他方法 Methods that do not return QuerySets

所谓其他方法,也就是不返回QuerySet的方法.

不返回QuerySet的方法
条件 解释
get(**kwargs) 参数为关键字的查询条件,返回一个结果,如果找不到,会报 DoesNotExist 异常.如果找到多个,会报 MultipleObjectsReturned 异常.对一个QuerySet对象使用不带参数的get(),可以让其只返回第一个对象.今后遇到查询,还是优先使用filter方法比较好
create(**kwargs) 接受参数来建立一个对象,使用.create()方法就包含了.save()的过程,详细看这里
get_or_create(defaults=None, **kwargs) 用给定的查询条件寻找对象,如果找不到,就建立一个.这个方法返回一个元组(object,created),元组第一个元素是查询结果或者新建的数据,第二个是一个布尔值,如果新建了就是True,否则是False.这个方法实际过程相当于先去调用get(),如果产生了DoesNotExist异常,则会新建一个同样参数的对象.注意关键字参数里名称叫做defaults的关键字是不会成为内含的get()调用中的参数,只会在新建的时候发生作用.具体看这里
update_or_create(defaults=None, **kwargs) 和get_or_create类似,如果字段存在则更新,否则创建.defautls也是表示创建时候的其他字段.
bulk_create(objs, batch_size=None) 批量插入(新增)数据,objs是一个列表,batch_size表示一次插入的个数.具体看这里
in_bulk(id_list=None) id_list是一个主键列表,根据其中的主键,返回一个字典,键是主键,值是对应的数据行对象.如果不传参数,则返回所有主键和对应数据行构成的字典.在按照主键查询的时候经常用此方法.
iterator() QuerySet的方法,使用之后变成一个迭代器.
latest(field_name=None) 需要指定字段名,字段必须是时间类型的字段,直接返回时间最晚的那一行记录.
earliest(field_name=None) 和latest用法相同,返回时间最早的那一条记录,和latest经常使用在一些内容管理的查找上
update(**kwargs) 用在QuerySet上,更新QuerySet里所有对象的字段,隐含了save操作,返回受影响的行数.update不能够用在关联关系的操作上,不能直接通过外键名__字段名去更新其他表.之前说过查询的时候多用filter,因此今后就用update与filter搭配使用.
delete() 用在单个对象或者QuerySet上,表示将选择的行从表里删除,返回受影响的行数.
as_manager() 在每次写查询的models.Book.objects中的objects就是一个对象管理器,对象管理器的默认名称就是objects.这个方法就是产生一个带有QuerySet所有方法的管理器,替代了objects这个名字,具体看这里

补充部分

查看实际生成的SQL语句

在使用ORM的时候,有的时候需要知道实际生成的SQL语句,将如下部分复制到settings.py中,设置DEBUG=True,每次执行ORM操作的时候,就可以在python console中看到实际的SQL语句.

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}

在python程序中调用Django环境

一般来说我们在启动Django程序的时候才运行在Django环境中,单独写一个py文件,导入Django的库是无法进行操作的.
实际上Django环境是写在Django_admin等内容中的,直接使用会提示导入环境配置文件,只要根据提示操作即可,这里提供直接可供粘贴的代码:

import os

if __name__ == '__main__':
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings")
    import django
    django.setup()
#  在以上语句结束之后,就可以像编写views,models等文件中来导入Django的各种模块来进行操作,结果也与像在实际的Django环境中得到的结果一样
    from app01 import models
    books = models.Book.objects.all()
    print(books)

CSRF跨站请求伪造

在学完了Django的全部模块之后,在每次新建项目的时候都关闭了CSRF中间件,现在可以回来看看该部分内容了.
Django的核心其实就是settings.py里的各种中间件,因为Django将可编写的部分都交给了程序员,通过中间件将这些东西全部组织起来.
打开CSRF中间件,来编写一个最简单的登陆页面和函数:

# 视图函数
def login(request):
    if request.method == "GET":
        return render(request, "login.html")
    else:
        name = request.POST.get("username").strip()
        pwd = request.POST.get("password").strip()
        print(name, pwd)
        if name == "lee0709" and pwd == "1234":
            return redirect("http://conyli.cc")

页面如下:

<div class="container">
    <h1 class="text-center">请登陆</h1>
    <form action="/login/" method="post" class="form-horizontal">
        <div class="form-group">
            <label for="username">用户名</label>
            <input type="text" id="username" name="username">
        </div>
        <div class="form-group">
            <label for="password">用户名</label>
            <input type="text" id="password" name="password">
        </div>
        <div class="form-group">
        <button type="submit" class="btn btn-primary">提交</button>
        </div>
    </form>
</div>

在提交的时候,发现根本就没有提交到视图函数,而是返回错误如下:

Forbidden (403)
CSRF verification failed. Request aborted.
You are seeing this message because this site requires a CSRF cookie when submitting forms. This cookie is required for security reasons, to ensure that your browser is not being hijacked by third parties.
If you have configured your browser to disable cookies, please re-enable them, at least for this site, or for 'same-origin' requests.

可见出现了一个403错误,访问被阻止,错误信息显示CSRF验证失败,向该站点提交表单需要CSRF cookie,该cookie为了保证浏览器的访问没有被第三方劫持.如果将浏览器配置成不支持cookie,需要将cookie打开.
这个时候就需要了解一下CSRF.
CSRF的原理其实很简单,还记得最开始编写的简单版web处理程序,其实就是给服务端发送字符串,攻击者可以伪装成浏览器向服务端发送form表单进行操作,如果服务端对form表单不加以验证,则可能会执行浏览器发送的信息导致用户信息被冒用,比如下了不想要的订单.攻击者利用尚未过期的登录信息,欺骗用户浏览器,让其以用户的名义执行操作就是CSRF跨站请求伪造.
为此,服务端在每次接受表单的时候,必须要进行验证,通常采用的方式是,服务器在生成表单的提供给浏览器的时候,会额外在表单内添加一些验证数据叫做token(比如用隐藏的input框),这些数据只存在于网页中,不存在cookie中.用户提交表单时这些验证数据也会一并提交上去,服务器得到该验证数据进行验证,通过之后才会处理表单.而在CSRF的恶意请求中,提交的表单包含不正确的验证数据或者压根没有验证数据,服务端便不会接受这样的表单.

Django的中间件已经自动实现了token及验证, 需要打开中间件,然后在网站的form标签内部加上之前在模板内学过的 {% csrf_token %}.之后刷新页面,可以看到form表单内出现了一个新的input元素:

<input type="hidden" name="csrfmiddlewaretoken" value="ax7LQgKnJodvQR5kHGVC2UZOZ1nGWmYlXDFXTA9aTTXn5v34NADOFckRMeJAtAkV">

每次刷新页面时,value会变动,如果通不过验证,这个表单就不会提交到视图函数进行处理.这样就防止了CSRF攻击.