Django55道面试问题

1 列举Http请求中常见的请求方式

HTTP请求的方法:

HTTP/1.1协议中共定义了八种方法(有时也叫“动作”),来表明Request-URL指定的资源不同的操作方式

注意:

1.方法名称是区分大小写的,当某个请求所针对的资源不支持对应的请求方法的时候,服务器应当返回状态码405(Mothod Not Allowed);当服务器不认识或者不支持对应的请求方法时,应返回状态码501(Not Implemented)。

#2.HTTP服务器至少应该实现GET和HEAD/POST方法,其他方法都是可选的,此外除上述方法,特定的HTTP服务器支持扩展自定义的方法。

请求方式

GET
向特定的路径资源发出请求
注意:GET方法不应当被用于产生“副作用”的操作中,例如在WebApplication中,其中一个原因是GET可能会被网络蜘蛛等随意访问。Loadrunner中对应get请求函数:web_link和web_url
POST
向指定路径资源提交数据进行处理请求(一般用于提交表单或者上传文件)
数据被包含在请求体中,POST请求可能会导致新的资源的建立和/或已有资源的修改。Loadrunner中对应POST请求函数:web_submit_data,web_submit_form
OPTIONS
返回服务器针对特定资源所支持的HTTP请求方法
允许客户端查看服务器的性能,也可以利用向web服务器发送‘*’的请求来测试服务器的功能性
HEAD
向服务器索与GET请求相一致的响应,只不过响应体将不会被返回
这一方法可以再不必传输整个响应内容的情况下,就可以获取包含在响应小消息头中的元信息。
PUT
从客户端向服务器传送的数据取代指定的文档的内容
DELETE
请求服务器删除指定的页面
TRACE
回回显服务器收到的请求,主要用于测试或诊断
CONNECT
HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务

2 谈谈你对HTTP协议的认识

HTTP是一个属于应用层的面向对象的协议,HTTP协议工作于客户端-服务端架构之上。
浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。Web服务器根据接收到的请求后,向客户端发送响应信息。
基于TCP/IP
双方建立通信的顺序,以及Web页面显示需要处理的步骤,等等。像这样把与互联网相关联的协议集合起来总称为TCP/IP。而http协议是基于TCP/IP协议之上的应用层协议。
基于请求-响应模式
HTTP协议规定,请求从客户端发出,最后服务器端响应该请求并返回

无状态保存

HTTP是一种不保存状态,即无状态(stateless)协议。HTTP协议自身不对请求和响应之间的通信状态进行保存。也就是说在HTTP这个级别,协议对于发送过的请求或响应都不做持久化处理。
使用HTTP协议,每当有新的请求发送时,就会有对应的新响应产生。协议本身并不保留之前一切的请求或响应报文的信息。这是为了更快地处理大量事务,确保协议的可伸缩性,而特意把HTTP协议设计成如此简单的。可是,随着Web的不断发展,因无状态而导致业务处理变得棘手的情况增多了。比如,用户登录到一家购物网站,即使他跳转到该站的其他页面后,也需要能继续保持登录状态。针对这个实例,网站为了能够掌握是谁送出的请求,需要保存用户的状态。HTTP/1.1虽然是无状态协议,但为了实现期望的保持状态功能,于是引入了Cookie技术。有了Cookie再用HTTP协议通信,就可以管理状态了。

4 简述Django请求生命周期

一般是用户通过浏览器向我们的服务器发起一个请求(request),这个请求回去访问视图函数,(如果不涉及到数据调用,那么这个时候视图函数返回一个模板也就是一个网页给用户),视图函数调用模型,模型去数据库查找数据,然后逐级返回,视图函数把返回的数据填充到模板中空格中,最后返回网页给用户。
1.wsgi,请求封装后交给web框架(Flask、Django)
2.请求中间件,对请求进行校验或在请求对象中添加其他相关数据,例如:csrf、request.session -
3.路由匹配,根据浏览器发送的不同url去匹配不同的视图函数
4.视图函数,在视图函数中进行业务逻辑的处理,可能涉及到:orm、templates => 渲染 - 
5.响应中间件,对响应的数据进行处理。
6.wsgi,将响应的内容发送给浏览器。

5 简述什么是FBV和CBV

FBV(function base views)就是在视图函面使用函数处理请求

CBV(class base views)就是在视图里面使用类处理请求

6 谈一谈你对ORM的理解

ORM是“对象-关系-映射”的简称。

MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的工作量,不需要面对因数据库变更而导致的无效劳动

7 rest_framework 认证组件的流程

rest_framework框架是基于CBV基础开发的(VPIView(View)),所以基本流程与CBV流程相似

当我们的请求发来后,会走as_views,执行view里面的方法,最开始都要执行dispatch方法

8 什么是中间件并简述其作用

中间件是一个用来处理Django的请求和响应的框架级别的钩子。它是一个轻量、低级别的插件系统,用于在全局范围内改变Django的输入和输出。每个中间件组件都负责做一些特定的功能。

中间件是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。

9 django 中间件生命周期

请求过来,中间件拦截一部分请求;比如验证session,没有登录的请求一些页面,跳转至登录页;(图片为中间件的请求过程.)再到urls,分发请求到views视图,通过CBV(dispatch反射)和FBV的get请求讲template页面渲染返回给用户;渲染之前可以从数据库拿出数据,放到render的参数里面传递过去,locals()表示把所有参数传递还可以实例化其他form类,并渲染给前端

10 django中怎么写原生SQL

列举django orm中三种能写sql语句的方法
使用extra:

查询人民邮电出版社出版并且价格大于50元的书籍
Book.objects.filter(publisher__name='人民邮电出版社').extra(where=['price>50'])

使用raw

books=Book.objects.raw('select * from hello_book')
for book in books:
    print book

自定义sql

from django.db import connection
 
cursor = connection.cursor()
cursor.execute("insert into hello_author(name) VALUES ('郭敬明')")
cursor.execute("update hello_author set name='韩寒' WHERE name='郭敬明'")
cursor.execute("delete from hello_author where name='韩寒'")
cursor.execute("select * from hello_author")
cursor.fetchone()
cursor.fetchall() 

13 视图函数中,接收的请求对象常用方法和属性有哪些

path属性,获取请求页面的全路径,不包括域名
method属性,获取请求中使用的HTTP方式的字符串表示。全大写表示
GET属性,获取HTTP GET方式请求传参,的参数(字典类型)
POST属性,获取表单类型的请求体数据
body属性获取最原始的请求体数据,自己按照请求体格式(JSON、XML等)进行解析。request.body返回bytes类型。
META属性获取请求头headers中的数据,request.META为字典类型。

14 常用视图响应的方式是什么?

视图的响应返回使用HttpResponse

HttpResponse(content=响应体, content_type=响应体数据类型, status=状态码)

16 路由匹配原则是什么?

关于正则匹配优先级(由上而下)

在url匹配列表中,如果第一条和第二条同时满足匹配规则,则优先匹配第一条。

17 缓存系统类型有哪些

全站缓存

MIDDLEWARE_CLASSES = (
    'django.middleware.cache.UpdateCacheMiddleware',  # 第一
    'django.middleware.common.CommonMiddleware',
    'django.middleware.cache.FetchFromCacheMiddleware',  # 最后
)

视图缓存

from django.views.decorators.cache import cache_page
import time
 
@cache_page(15) #超时时间为15秒
def index(request):
    t=time.time() #获取当前时间
    return render(request,"index.html",locals())

模板缓存

{% load cache %}
    

不缓存:-----{{ t }}

{% cache 2 'name' %} # 存的key

缓存:-----:{{ t }}

{% endcache %}

18 解决跨域的常用方式是什么?

跨域是指一个域下的文档或脚本试图去请求另一个域下的资源,这里跨域是广义的。

广义的跨域:

资源跳转:A链接、重定向、表单提交

资源嵌入:link script img frame等dom标签,还有样式中background:url()、@font-face()等文件外链

脚本请求:js发起的ajax请求、dom和js对象的跨域操作等
同源策略/SOP(Same origin policy)是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。

同源策略限制以下几种行为:

Cookie、LocalStorage 和 IndexDB 无法读取

DOM 和 Js对象无法获得

AJAX 请求不能发送

19 信号的作用是什么?

Django中如何在Model保存前做一定的固定操作,比如写一句日志?

关键词:信号

利用Django的Model的Signal Dispatcher, 通过django.db.models.signals.pre_save() 方法,在事件发生前,触发信号,这一切都被调度中的receiver方法深藏功与名的保存了。

信号的处理一般都写在Model中,举个例子:

import logging
from django.db import models
from django.db.models.signals import pre_save
from django.dispatch import receiver
 
class Order(models.Model):
    # ...
 
 
logger = logging.getLogger(__name__)
 
@receiver(pre_save, sender=Order)
def pre_save_handler(sender, **kwargs):
    
    # 我们可以在Order这个Model保存之前尽情调戏了:)
    logger.debug("{}".format(sender, **kwargs))
    print 'fuck universe'

这样应该就实现了题中的要求,类似的方法还有比如 pre_init 是在Model实例之前会触发, post_init 在实例之后触发,同理就是 pre_save 和 post_save 了。

20 Django的Model的继承有几种形式,分别是什么

抽象继承
表示你的父类仅仅是包含了多个子类的相同的字段,是为了重用,不会建表,我们只需要在抽象父类的Meta中设置abstract=True就行。比如:

class CommonInfo(models.Model):
    name = models.CharField(max_length=100)
    age = models.PositiveIntegerField()
 
    class Meta:
        abstract = True
 
class Student(CommonInfo):
    home_group = models.CharField(max_length=5)

Student模型将会有name,age,home_group三个字段。如果在抽象父类和子类中出现相同的字段名字,django会引发异常。

对于内联的Meta类的继承,一般的,父类的Meta类的属性会继承给子类,子类也可以在自己的Meta中重写或者拓展父类的Meta,拓展的话主要是继承父类的Meta:

class CommonInfo(models.Model):
    ...
    class Meta:
        abstract = True
        ordering = ['name']
 
class Student(CommonInfo):
    ...
    class Meta(CommonInfo.Meta):
        db_table = 'student_info'

这个时候,父类Meta中的abstract=True是不会传递给子类的,django会将子类的abstract设置为False

除了abstract之外,父类Meta中的db_table也不会继承给子类

在抽象类中使用关系(如外键,多对多关系,一对一关系)时候,肯定会设置related_name,但是子类继承抽象父类的时候,由于父类中的字段会继承给子类,则具有related_name的字段会被多个子类共享的。这样每一个子类的related_name就都一样了,其他模型通过related_name就不能找到正确的子类。

所以要正确设置related_name,related_name中必须包含%(app_label)s 和 %(class)s。如

%(app_label)s表示小写形式的,当前模型所在的,并且已经安装的app的名字

%(class)s表示小写形式的,当前子类的类名字。

在common/models.py,有

class Base(models.Model):
    m2m = models.ManyToManyField(OtherModel, related_name="%(app_label)s_%(class)s_related")
 
    class Meta:
        abstract = True
 
class ChildA(Base):
    pass
 
class ChildB(Base):
    pass
在rare/models.py,有

from common.models import Base
 
class ChildB(Base):
    pass

所以,上面的related_name就是 common_childa_related和 common_childb_related

多表继承

父类也是一个django模型,并且也会创建一个数据表,多表继承是django中隐式的一对一关系。例如:

class Place(models.Model):
    name = models.CharField(max_length=50)
    address = models.CharField(max_length=80)
 
class Restaurant(Place):
    serves_hot_dogs = models.BooleanField()
    serves_pizza = models.BooleanField()

其中虽然name和address存储在模型Place的表中,但是name和address对于Restaurant也是有效字段

>>> Place.objects.filter(name="Bob's Cafe")
>>> Restaurant.objects.filter(name="Bob's Cafe")

Restaurant和Place的关系,可以这么说:一个Restaurant一定是一个Place,而一个Place不一定是Restaurant

多表继承中,一般,父类的Meta属性不会继承到子类中,但是,ordering和 get_latest_by是继承的,如果子类不想继承父类的ordering的Meta,则可以手动显式的指定ordering=[]或者任何自己想要的值

多表继承的时候,是隐式的在父类和子类之间建立一个一对一关系,所以有时候,父类与其他类的关系会从父类下移到子类中。如果有多个子类,且子类不在关系中显式地指定related_name字段,django会引发验证错误
class Supplier(Place):
    # Must specify related_name on all relations.
    customers = models.ManyToManyField(Restaurant, related_name='provider')
所以,继承父类,一旦子类中有关系,就加上related_name吧

django自动在子类和非抽象父类之间创建一个一对一关系,如果你想控制由子类连接回父类的属性的名字,你可以创建一个一对一关系,然后设置parent_link=True

proxy model(代理模型)
在多表继承中,子类模型会创建一个数据表来存储不在父类模型中的额外字段,但是,如果我们只想改变某个模型的行为方法,而不是添加额外的字段,我们就可以使用

proxy model。代理model(proxy model)会继承父类的属性,并且只是添加一些对属性的操作的自定义方法而已。
class MyPerson(Person):
    class Meta:
        proxy = True
 
    def do_something(self):
        ...zh

这里,MyPerson没有多创建数据表,MyPerson也是对Person的数据表进行操作,一般的,我们可以把MyPerson当做Person来使用,只是在do_something这个方法略有不同,比如

>>> p = Person.objects.create(first_name="foobar")
>>> MyPerson.objects.get(first_name="foobar")


代理模型和原模型的区别如下面:

class OrderedPerson(Person):
    class Meta:
        ordering = ["last_name"]
        proxy = True

这里,OrderedPerson并不是创建了一个表,而是代理排序方法。也就是说,使用Person的检索方法并不会按last_name排序,而使用

OrderedPerson检索出来的结果是按last_name排序的。OrderedPerson使用与Person类一样的检索方法。

OrderPerson返回的queryset自然是Person的,这是当然的。我们不能要求django返回OrderedPerson类的queryset,因为OrderedPerson只是代理而已,又不是真实的数据库表类。

注意的是,

proxy model不能继承于抽象类,这是因为代理model是操作连接数据库的,也不能多重继承~因为你多重继承了,代理model就不知道去哪个父类找属性了

如果不指定代理model的manage,则代理model会自动继承父类的manage。我们也可以手动设置代理model的manage,这样,代理模型和父类模型的manage就分开了

为代理模型添加manage有两种方法:

一是直接在代理模型中直接指定manage

class NewManager(models.Manager):
    ...
 
class MyPerson(Person):
    objects = NewManager()
 
    class Meta:
        proxy = True

另外一种是当你不想覆盖父类模型中的manage但又想添加额外的manage,我们可以新建一个抽象模型,然后定义其manage,之后继承该抽象模型,如:

# Create an abstract class for the new manager.
class ExtraManagers(models.Model):
    secondary = NewManager()
 
    class Meta:
        abstract = True
 
class MyPerson(Person, ExtraManagers):
    class Meta:
        proxy = True

21 Django中查询queryset时什么情况下用Q

F:对数据本身的不同字段进行操作 如:比较和更新,对数据进行加减操作

Q:用于构造复杂的查询条件 如:& |操作

22 Django中想验证表单提交是否格式正确需要用到Form中的哪个函数

form.is_valid():返回布尔值

23 orm如何取消级联

在设置外键时,需要通过on_delete选项指明主表删除数据时,对于外键引用表数据如何处理,在django.db.models中包含了可选常量:

CASCADE 级联,删除主表数据时连通一起删除外键表中数据

PROTECT 保护,通过抛出ProtectedError异常,来阻止删除主表中被外键应用的数据

SET_NULL 设置为NULL,仅在该字段null=True允许为null时可用

SET_DEFAULT 设置为默认值,仅在该字段设置了默认值时可用

SET() 设置为特定值或者调用特定方法

25 简述Django对http请求的执行流程

在接受一个Http请求之前的准备,启动一个支持WSGI网关协议的服务器监听端口等待外界的Http请求,比如Django自带的开发者服务器或者uWSGI服务器。  

服务器根据WSGI协议指定相应的Handler来处理Http请求,并且初始化该Handler,在Django框架中由框架自身负责实现这一个Handler。 此时服务器已处于监听状态,可以接受外界的Http请求 当一个http请求到达服务器的时候   

服务器根据WSGI协议从Http请求中提取出必要的参数组成一个字典(environ)并传入Handler中进行处理。  

在Handler中对已经符合WSGI协议标准规定的http请求进行分析,比如加载Django提供的中间件,路由分配,调用路由匹配的视图等。 返回一个可以被浏览器解析的符合Http协议的HttpResponse。

25 Django中当用户登录到A服务器进入登陆状态,下次被nginx代理到B服务器会出现什么影响

如果用户在A应用服务器登陆的session数据没有共享到B应用服务器,那么之前的登录状态就没有

26 跨域请求Django是如何处理的

启用中间件
post请求
验证码
表单中添加{% csrf_token %}标签

27 查询集的两大特性?什么是惰性执行

惰性执行、缓存 。  
创建查询集不会访问数据库,直到调用数据时,才会访问数据库,调用数据的情况包括迭代、序列化、与if合用

28 查询集返回的列表过滤器有哪些

all():返回所有数据  
filter():返回满足条件的数据 
exclude():返回满足条件之外的数据,相当于sql语句中where部分的not关键字  
order_by():排序

29 django路由系统中include是干嘛用的?

include路由转发

通常,我们会在每个app里,各自创建一个urls.py路由模块,然后从根路由出发,将app所属的url请求,全部转发到相应的urls.py模块中。

30 urlpatterns中的name与namespace有什么作用?你是如何使用的?

别名,给路由起一个别名

名称空间,防止多个应用之间的路由重复

31 如何根据urlpatterns中的name反向生成url,这样反向生成url的方式有几种?

使用HttpResponseRedirect redirect和reverse 状态码:302,301

32 如何给一个字段设置一个主键?

primary_key

34 DateTimeField类型中的auto_now与auto_now_add有什么区别

DateTimeField.auto_now

这个参数的默认值为false,设置为true时,能够在保存该字段时,将其值设置为当前时间,并且每次修改model,都会自动更新。因此这个参数在需要存储“最后修改时间”的场景下,十分方便。需要注意的是,设置该参数为true时,并不简单地意味着字段的默认值为当前时间,而是指字段会被“强制”更新到当前时间,你无法程序中手动为字段赋值;如果使用django再带的admin管理器,那么该字段在admin中是只读的。
DateTimeField.auto_now_add

这个参数的默认值也为False,设置为True时,会在model对象第一次被创建时,将字段的值设置为创建时的时间,以后修改对象时,字段的值不会再更新。该属性通常被用在存储“创建时间”的场景下。与auto_now类似,auto_now_add也具有强制性,一旦被设置为True,就无法在程序中手动为字段赋值,在admin中字段也会成为只读的。

35 selected_related与prefetch_related有什么区别?

在Django中,所有的Queryset都是惰性的,意思是当创建一个查询集的时候,并没有跟数据库发生任何交互。因此我们可以对查询集进行级联的filter等操作,只有在访问Queryset的内容的时候,Django才会真正进行数据库的访问。而多频率、复杂的数据库查询往往是性能问题最大的根源。

不过我们实际开发中,往往需要访问到外键对象的其他属性。如果按照默认的查询方式去遍历取值,那么会造成多次的数据库查询,效率可想而知。

在查询对象集合的时候,把指定的外键对象也一并完整查询加载,避免后续的重复查询。

1,select_related适用于外键和多对一的关系查询;

2,prefetch_related适用于一对多或者多对多的查询。

36 class Meta中的元信息字段有哪些

通过一个内嵌类 "class Meta" 给你的 model 定义元数据, 类似下面这样:

class User(AbstractUser):
    """用户模型类"""
    mobile = models.CharField(max_length=11, unique=True, verbose_name='手机号')
    email_active = models.BooleanField(default=False, verbose_name='邮箱验证状态')
    default_address = models.ForeignKey('Address', related_name='users', null=True, blank=True,
                                        on_delete=models.SET_NULL, verbose_name='默认地址')
 
    class Meta:
        db_table = 'tb_users'
        verbose_name = '用户'
        verbose_name_plural = verbose_name

37 django的M2M关系,如何手动生成第三张表?

tags = models.ManyToManyField(
    to="Tag",
    through='Article2Tag',
    through_fields=('article', 'tag'),
)

38 在Django中,服务端给客户端响应信息有几种方式?分别是什么?

HTTPresponse
jsonresponse
redirect

39 web框架的本质是什么?

本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端。

40 创建Django工程、Django app、以及运行的命令

# 创建新的项目
django-admin.py startproject my_project
# 在Django项目(my_project)的根目录下执行
python3 manage.py startapp my_app
# 启动Django中的开发服务器
# run server
python3 manage.py runserver

41 django中csrf的实现机制

第一步:django第一次响应来自某个客户端的请求时,后端随机产生一个token值,把这个token保存在SESSION状态中;同时,后端把这个token放到cookie中交给前端页面;

第二步:下次前端需要发起请求(比如发帖)的时候把这个token值加入到请求数据或者头信息中,一起传给后端;Cookies:{csrftoken:xxxxx}

第三步:后端校验前端请求带过来的token和SESSION里的token是否一致;

43 什么是Cookie、如何获取、设置Cookie

会话跟踪技术,保留用户

Cookie是由服务器创建,然后通过响应发送给客户端的一个键值对。

具体一个浏览器针对一个服务器存储的key-value

response.set_cookie("is_login",True)
request.COOKIES.get("is_login")

44 什么是session,与cookie的对比、设置、获取、清空session

Session是服务器端技术,利用这个技术,服务器在运行时可以 为每一个用户的浏览器创建一个其独享的session对象,由于 session为用户浏览器独享,所以用户在访问服务器的web资源时 ,可以把各自的数据放在各自的session中,当用户再去访问该服务器中的其它web资源时,其它web资源再从用户各自的session中 取出数据为用户服务。 
request.session["is_login"] = True
is_login = request.session.get("is_login")
request.session.flush()

45 什么是CSRF,及防范方式

启用中间件
post请求
验证码
表单中添加{%csrf_token%}标签

46 get请求和post请求的区别

GET提交的数据会放在URL之后,以?分割URL和传输数据,参数之间以&相连,如EditBook?name=test1&id=123456。POST方法是把提交的数据放在HTTP包的Body中。
GET提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST方法提交的数据没有限制。
GET与POST请求在服务端获取请求数据方式不同。
GET方式提交数据,会带来安全问题,比如一个登录页面,通过GET方式提交数据时,用户名和密码将出现在URL上,如果页面可以被缓存或者其他人可以访问这台机器,就可以从历史记录获得该用户的账号和密码。

47 如何使用django加密

Django 内置的User类提供了用户密码的存储、验证、修改等功能,默认使用pbkdf2_sha256方式来存储和管理用的密码。

django通过setting.py文件中的PASSWORD_HASHERS来设置选择要使用的算法,列表的第一个元素 (即settings.PASSWORD_HASHERS[0]) 会用于储存密码, 所有其它元素都是用于验证的哈希值,它们可以用于检查现有的密码。意思是如果你打算使用不同的算法,你需要修改PASSWORD_HASHERS,来将你最喜欢的算法在列表中放在首位。

一个settings中的Password_hashers看起来是这样的:

PASSWORD_HASHERS = ( 
    'django.contrib.auth.hashers.PBKDF2PasswordHasher',
    'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
    'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
    'django.contrib.auth.hashers.BCryptPasswordHasher',
    'django.contrib.auth.hashers.SHA1PasswordHasher',
    'django.contrib.auth.hashers.MD5PasswordHasher',
    'django.contrib.auth.hashers.CryptPasswordHasher',
)

具体的密码生成以及验证实现

from django.contrib.auth.hashers import make_password,check_password
 
pwd='4562154'
mpwd=make_password(pwd,None,'pbkdf2_sha256')  # 创建django密码,第三个参数为加密算法
pwd_bool=check_password(pwd,mpwd)  # 返回的是一个bool类型的值,验证密码正确与否
Django之密码加密
通过django自带的类库,来加密解密很方便,下面来简单介绍下;

导入包:

from django.contrib.auth.hashers import make_password, check_password
一个是生成密码,一个是核对密码。

例如:

make_password("123456")
得到结果:

u'pbkdf2_sha25615000MAjic3nDGFoi$qbclz+peplspCbRF6uoPZZ42aJIIkMpGt6lQ+Iq8nfQ='

另外也可以通过参数来生成密码:

>>> make_password("123456", None, 'pbkdf2_sha256')

校验:

校验就是通过check_password(原始值, 生成的密文)来校验密码的。

>>> check_password("123456","pbkdf2_sha25615000MAjic3nDGFoi$qbclz+peplspCbRF6uoPZZ42aJIIkMpGt6lQ+Iq8nfQ=")
>>> True

48 解释blank和null

blank

设置为True时,字段可以为空。设置为False时,字段是必须填写的。字符型字段CharField和TextField是用空字符串来存储空值的。如果为True,字段允许为空,默认不允许。

null

设置为True时,django用Null来存储空值。日期型、时间型和数字型字段不接受空字符串。所以设置IntegerField,DateTimeField型字段可以为空时,需要将blank,null均设为True。

如果为True,空值将会被存储为NULL,默认为False。

如果想设置BooleanField为空时可以选用NullBooleanField型字段。

一句话概括

null 是针对数据库而言,如果 null=True, 表示数据库的该字段可以为空。NULL represents non-existent data.
blank 是针对表单的,如果 blank=True,表示你的表单填写该字段的时候可以不填。比如 admin 界面下增加 model 一条记录的时候。直观的看到就是该字段不是粗体

49 QueryDict和dict区别

在 HttpRequest 对象中,属性 GET 和 POST 得到的都是 django.http.QueryDict 所创建的实例。这是一个 django 自定义的类似字典的类,用来处理同一个键带多个值的情况。

在 python 原始的字典中,当一个键出现多个值的时候会发生冲突,只保留最后一个值。而在 HTML 表单中,通常会发生一个键有多个值的情况,例如