第十四章: 会话、用户和注册

wcj 10-30 22:58

第十二章

虎头满 01-30 09:01

感觉权限那一块讲的不是很清楚呢~!

虎头满 01-30 09:02

例如如何添加权限自定义权限啥的~!

对标题的评论会显示在这里

是时候承认了: 我们有意的避开了Web开发中极其重要的方面。 到目前为止,我们都在假定,网站流量是大量的匿名用户带来的。

1 12-01 08:13

-1'

-1' 12-01 08:13

1

1 12-01 08:13

1

rcompass 10-14 09:59

test

urmyfaith 09-25 16:24

本章总结:http://t.cn/RhTztXz 带实例,图

cyhhao 10-09 07:43

给楼上的总结点个赞!顺便吐槽一句:作者终于承认有意避开最重要的一章了!!感觉这章应该放再靠前一点!

匿名读者 01-24 12:11

怒赞!!!

匿名读者 07-03 13:00

博客给力呀!就是要像博主那样地实践学习才有效果!!

匿名读者 08-30 01:00

ggg

对这一段的评论会显示在这里

这当然不对。 浏览器的背后都是活生生的人(至少某些时候是)。 这忽略了重要的一点: 互联网服务于人而不是机器。 要开发一个真正令人心动的网站,我们必须面对浏览器后面活生生的人。

Jhony 11-08 09:09

经典!!!

对这一段的评论会显示在这里

很不幸,这并不容易。 HTTP被设计为”无状态”,每次请求都处于相同的空间中。 在一次请求和下一次请求之间没有任何状态保持,我们无法根据请求的任何方面(IP地址,用户代理等)来识别来自同一人的连续请求。

对这一段的评论会显示在这里

在本章中你将学会如何搞定状态的问题。 好了,我们会从较低的层次(cookies)开始,然后过渡到用高层的工具来搞定会话,用户和注册的问题。

对这一段的评论会显示在这里

Cookies

对这一段的评论会显示在这里

浏览器的开发者在很早的时候就已经意识到, HTTP’s 的无状态会对Web开发者带来很大的问题,于是(cookies)应运而生。 cookies 是浏览器为 Web 服务器存储的一小段信息。 每次浏览器从某个服务器请求页面时,它向服务器回送之前收到的cookies

ode2free 05-10 20:02

应该是:HTTP的无状态

ode2free 05-10 20:05

回送-->返回

匿名读者 12-01 05:39

<script> alert("sss"); </script>

程杰 06-13 12:38

麻烦翻译可以改的地方改下

匿名读者 10-27 12:24

我在这里留下足迹,证明我到达过这里...

匿名读者 11-23 08:49

路过存在

猪头哥哥 12-12 02:44

这里还是很必要看的

对这一段的评论会显示在这里

来看看它是怎么工作的。 当你打开浏览器并访问 google.com ,你的浏览器会给Google发送一个HTTP请求,起始部分就象这样:

对这一段的评论会显示在这里
GET / HTTP/1.1
Host: google.com
...
对这一段的评论会显示在这里

当 Google响应时,HTTP的响应是这样的:

对这一段的评论会显示在这里
HTTP/1.1 200 OK
Content-Type: text/html
Set-Cookie: PREF=ID=5b14f22bdaf1e81c:TM=1167000671:LM=1167000671;
            expires=Sun, 17-Jan-2038 19:14:07 GMT;
            path=/; domain=.google.com
Server: GWS/2.1
...
对这一段的评论会显示在这里

注意 Set-Cookie 的头部。 你的浏览器会存储cookie值( PREF=ID=5b14f22bdaf1e81c:TM=1167000671:LM=1167000671 ) ,而且每次访问google 站点都会回送这个cookie值。 因此当你下次访问Google时,你的浏览器会发送像这样的请求:

wngn 09-02 02:53

"回送"这个词听着怪怪的...

对这一段的评论会显示在这里
GET / HTTP/1.1
Host: google.com
Cookie: PREF=ID=5b14f22bdaf1e81c:TM=1167000671:LM=1167000671
...
对这一段的评论会显示在这里

于是 Cookies 的值会告诉Google,你就是早些时候访问过Google网站的人。 这个值可能是数据库中存储用户信息的key,可以用它在页面上显示你的用户名。 Google会(以及目前)使用它在网页上显示你账号的用户名。

对这一段的评论会显示在这里

存取Cookies

对这一段的评论会显示在这里

在Django中处理持久化,大部分时候你会更愿意用高层些的session 和/或 后面要讨论的user 框架。 但在此之前,我们需要停下来在底层看看如何读写cookies。 这会帮助你理解本章节后面要讨论的工具是如何工作的,而且如果你需要自己操作cookies,这也会有所帮助。

ode2free 05-10 20:10

在Django中处理持久化 是不是应该翻成 长期使用Django后

weetao 05-28 16:41

@ode2free:持久化是术语

对这一段的评论会显示在这里

读取已经设置好的cookies极其简单。 每一个HttpRequest 对象都有一个COOKIES 对象,该对象的行为类似一个字典,你可以使用它读取任何浏览器发送给视图(view)的cookies。

对这一段的评论会显示在这里
def show_color(request):
    if "favorite_color" in request.COOKIES:
        return HttpResponse("Your favorite color is %s" %             request.COOKIES["favorite_color"])
    else:
        return HttpResponse("You don't have a favorite color.")
hhhh 09-28 10:39

这代码怎么搞的,从屏幕里出去了

vivi lee 08-08 07:05

def show_color(request): if "favorite_color" in request.COOKIES: return HttpResponse("Your favorite color is %s" % request.COOKIES["favorite_color"]) else: return HttpResponse("You don't have a favorite color.")

njw 05-04 09:24

%request.COOKIES["favorite_color"]为变量

匿名读者 09-21 09:32

http://www.djangobook.com/en/2.0/chapter14.html

对这一段的评论会显示在这里

cookie的例子:

对这一段的评论会显示在这里
def set_color(request):
    if "favorite_color" in request.GET:

        # Create an HttpResponse object...
        response = HttpResponse("Your favorite color is now %s" %             request.GET["favorite_color"])

        # ... and set a cookie on the response
        response.set_cookie("favorite_color",
                            request.GET["favorite_color"])

        return response

    else:
        return HttpResponse("You didn't give a favorite color.")
笑竹 03-23 06:38

response = HttpResponse("Your favorite color is now %s" % request.GET["favorite_color"]) 调整下

ode2free 05-10 20:19

这个网站没人管了吧~~~~~

Jingyu Li 08-09 16:08

显示有问题,把格式改一下吧。

Jeffer 12-16 04:30

查看源码才看到后面的。。。

Jeffer 12-16 04:32

查看源码才看到完整内容。。

牛三金 04-27 14:53

全选,COPY到记事本里即可!

迷途小前端 12-15 03:32

真的是没人管啊!!!

匿名读者 09-21 09:47

http://www.djangobook.com/en/2.0/chapter14.html

纸上往事 08-15 08:14

a) def show_color(request): errors = [] if "favorite_color" in request.COOKIES: return HttpResponse("Your favorite color is %s" % request.COOKIES["favorite_color"]) else: errors.append("You don't have a cookie favorite color. Pls set it.") return render_to_response('cookie_test1.html',{'errors':errors}) b)基于 GET 参数来设置 favorite_color cookie的例子: def set_color(request): errors = [] if not request.GET['favoriteclr']: errors.append("You don't set a cookie favorite color. Pls set it.") else: # Create an HttpResponse object... response = HttpResponse("Your favorite color is now %s" % request.GET["favoriteclr"]) # ... and set a cookie on the response response.set_cookie("favorite_color", request.GET["favoriteclr"]) return response return render_to_response('cookie_test1.html',{'errors':errors}) c)写模板/home/yxk/djcode/mysite/mysite/template/cookie_test1.html 与 写url.py映射 <html> <head> <title>Cookie test</title> </head> <body> {% if errors %} <ul> {% for error in errors %} <li>{{ error }}</li> {% endfor %} </ul> {% endif %} <form action="/set_color/" method="get"> {# <form action="" method="get"> should visit http://127.0.0.1:8000/search/ in web after delete /search/ in action </form>#} <input type="text" name="favoriteclr"> <input type="submit" value="Set"> </form> </body> </html> (r'^show_color/$', 'mysite.views.show_color'), (r'^set_color/$', 'mysite.views.set_color'),

匿名读者 06-03 09:50

作者这里的这个例子很坑,,,request.GET 这个GET属性是客户提交的,也就是表单的信息,我们做这个测试,更本没有,其实设置就是用set_cookie 来设置,用这个例子 def get_cookies(request): if "user_id" in request.COOKIES: cookies = request.COOKIES for key, value in cookies.items(): print(key, " ", value) return HttpResponse("Your favorite color is %s" % request.COOKIES["user_id"]) def set_cookies(request): if "user_id" not in request.COOKIES: response = HttpResponse("ok") response.set_cookie("user_id", "10098") return response else: return HttpResponse("ok")

对这一段的评论会显示在这里

你可以给 response.set_cookie() 传递一些可选的参数来控制cookie的行为,详见表14-1。

对这一段的评论会显示在这里

Error parsing content block for the “table” directive: exactly one table expected.

对这一段的评论会显示在这里
.. table:: 表 14-1: Cookie 选项

   +---------------------------------+---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   |参数                             |缺省值                     |描述                                                                                                                                                                                |
   +=================================+===========================+====================================================================================================================================================================================+
   |``max_age``                      |``None``                   |cookie需要延续的时间(以秒为单位) 如果参数是\ `` None`` ,这个cookie会延续到浏览器关闭为止。                                                                                       |
   +---------------------------------+---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   |``expires``                      |``None``                   |cookie失效的实际日期/时间。 它的格式必须是:\ `` "Wdy, DD-Mth-YY HH:MM:SS GMT"`` 。如果给出了这个参数,它会覆盖\ `` max_age`` 参数。                                                |
   +---------------------------------+---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   |``path``                         |``"/"``                    |cookie生效的路径前缀。 浏览器只会把cookie回传给带有该路径的页 面,这样你可以避免将cookie传给站点中的其他的应用。                                                                    |
   |                                 |                           |                                                                                                                                                                                    |
   |                                 |                           |当你不是控制你的站点的顶层时,这样做是特别有用的。                                                                                                                                  |
   +---------------------------------+---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   |``domain``                       |``None``                   |这个cookie有效的站点。 你可以使用这个参数设置一个跨站点(cross-domain)的cookie。 比如,\ `` domain=".example.com"`` 可以设置一个在\ `` www.example.com`` 、\ `` www2.example.com`` 以及\ `` an.other.sub.domain.example.com`` 站点下都可读到的cookie。|
   |                                 |                           |                                                                                                                                                                                    |
   |                                 |                           |如果这个参数被设成\ `` None`` ,cookie将只能在设置它的站点下可以读到。                                                                                                              |
   +---------------------------------+---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   |``False``                        |``False``                  |如果设置为 ``True`` ,浏览器将通过HTTPS来回传cookie。                                                                                                                               |
   +---------------------------------+---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
Sharkle 07-12 09:59

表格生成错误了。

aixcradent 08-03 09:18

表格排版有问题!

cabbage 04-07 07:49

拷贝 粘贴 到文本,可以查看全部

Wing Shine 11-30 07:33

最后一行 “False”==》“secure”

Jingyu Li 08-09 16:11

不能把页面的宽度调大一些吗?好多地方都显示不全。

shawn 08-19 09:57

看不到的同学。可以在chrome修改顶层div的属性,把div width设置为1900px即可

沈世军 10-21 08:36

+---------------------------------+---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ |参数 |缺省值 |描述 | +=======+=======+=================+===========================+====================================================================================================================================================================================+ |max_age|None |cookie需要延续的时间(以秒为单位) 如果参数是None,这个cookie会延续到浏览器关闭为止。 | +-------+-------+-----------------+---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ |expires|None |cookie失效的实际日期/时间。如果给出了这个参数,它会覆盖max_age参数。 | +-------+-------+-----------------+---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ |path |"/" |cookie生效的路径前缀。浏览器只会把cookie回传给带有该路径的页面,这样你可以避免将cookie | | | | | | | |传给站点中的其他的应用。当你不是控制你的站点的顶层时,这样做是特别有用的。 | +-------+-------+-----------------+----

detailyang 11-01 14:58

overflow:auto; 凑着用把 = =

OS胖达 12-01 14:24

右键【查看源代码】也能看见

urmyfaith 09-24 02:27

可以看英文版本的.这里的是markdown格式的表格,未能正确渲染. http://www.djangobook.com/en/2.0/chapter14.html,查找"Table 14-1: Cookie options",跳转到即可.

cici 09-15 02:31

含class="yui-t7"增加样式style="width : 2300px" = =

pynick 09-24 06:07

右键检查,可以查看表格全文

对这一段的评论会显示在这里

好坏参半的Cookies

对这一段的评论会显示在这里

也许你已经注意到了,cookies的工作方式可能导致的问题。 让我们看一下其中一些比较重要的问题:

对这一段的评论会显示在这里

cookie的存储是自愿的,一个客户端不一定要去接受或存储cookie。 事实上,所有的浏览器都让用户自己控制 是否接受cookies。 如果你想知道cookies对于Web应用有多重要,你可以试着打开这个浏览器的 选项:

对这一段的评论会显示在这里

尽管cookies广为使用,但仍被认为是不可靠的的。 这意味着,开发者使用cookies之前必须 检查用户是否可以接收cookie。

对这一段的评论会显示在这里

Cookie(特别是那些没通过HTTPS传输的)是非常不安全的。 因为HTTP数据是以明文发送的,所以 特别容易受到嗅探攻击。 也就是说,嗅探攻击者可以在网络中拦截并读取cookies,因此你要 绝对避免在cookies中存储敏感信息。 这就意味着您不应该使用cookie来在存储任何敏感信息。

对这一段的评论会显示在这里

还有一种被称为”中间人”的攻击更阴险,攻击者拦截一个cookie并将其用于另一个用户。 第19章将深入讨论这种攻击的本质以及如何避免。

hebe 04-08 12:48

19章内没找到相关讨论呀。。。

needle 10-27 10:57

MITM下会话劫持,使用arp欺骗,截获用户与路由器之间的HTTP流量,将用户已登陆状态下的会话cookie放置本地浏览器中,从而server会视攻击者的访问为此已登陆用户的请求。使用工具:ettercap(arp欺骗),wireshark(找cookie),EditThisCookie(放cookie)可模拟。操作的背后还是需要技术积累的。少年,想知道旁边美女的QQ号吗,想进她的QQ空间加密相册吗?在她的新浪微博里发一条迷恋你的微博然后她当你的面吐一口口水吗?相信自己,你可以的!

blue 04-23 15:47

这里应该是20章

纸上往事 08-15 02:36

这种攻击行illegal

对这一段的评论会显示在这里

即使从预想中的接收者返回的cookie也是不安全的。 在大多数浏览器中您可以非常容易地修改cookies中的信息。有经验的用户甚至可以通过像mechanize(http://wwwsearch.sourceforge.net/mechanize/) 这样的工具手工构造一个HTTP请求。

对这一段的评论会显示在这里

因此不能在cookies中存储可能会被篡改的敏感数据。 在cookies中存储 IsLoggedIn=1 ,以标识用户已经登录。 犯这类错误的站点数量多的令人难以置信; 绕过这些网站的安全系统也是易如反掌。

Rostrict 03-08 01:03

建议译文: 因此不能在cookies中存储可能会被篡改的敏感数据,典型的错误就是在用户登录后在cookies中存储 IsLoggedIn=1 以标识用户已经登录。 犯这类错误的站点数量多的令人难以置信,绕过这些网站的“安全”系统也是易如反掌。

lincy 08-22 03:02

感谢译文

lol,直接设置为1也太简单了点:D 07-28 04:24

对这一段的评论会显示在这里

Django的 Session 框架

对这一段的评论会显示在这里

由于存在的限制与安全漏洞,cookies和持续性会话已经成为Web开发中令人头疼的典范。 好消息是,Django的目标正是高效的“头疼杀手”,它自带的session框架会帮你搞定这些问题。

对这一段的评论会显示在这里

你可以用session 框架来存取每个访问者任意数据, 这些数据在服务器端存储,并对cookie的收发进行了抽象。 Cookies只存储数据的哈希会话ID,而不是数据本身,从而避免了大部分的常见cookie问题。

vincent 05-06 09:45

这个评注的模块没做任何验证,可以提交空数据。

454545 08-12 08:39

javascrpt:alert('')

454545 08-12 08:39

<table>ssssssssssss</table>

匿名读者 11-26 10:20

javascrpt:alert('')

AlsoTang 12-23 08:45

楼上的人。。。。。

j 01-19 01:48

w 07-16 03:16

<b>a<b>

Silent 11-15 03:15

一群蛋疼菊紧的货,跨域攻击神马的不好使看来【不过还是非常想吐槽那个HTML标签都搞错的哥们儿。。。

<script>alert("hehe")</script> 02-15 12:06

<script>alert("hehe")</script>

匿名读者 02-19 06:50

<script>alert("hehe")</script>

zt 03-02 13:48

<script>alert("hehe")</script>

1212 03-29 12:04

zjh 04-23 07:52

xiao bu dong le

ff 08-07 09:21

<>

ff 08-07 09:21

<script>alert("hahahahahahahah")</script>

匿名读者 10-27 14:30

非常感谢站主的无私的奉献,我自己也做的笔记,我的网站www.phpyrb.com。

匿名读者 12-16 11:48

<b>god</b>

gf 06-25 02:09

javascrpt:alert('')

gf 06-25 02:10

<script>alert("hehe")</script>

呵呵 07-18 03:19

<script>alert('hehe')</script>

kd 07-18 03:20

<script>alert("hehe")</script>

<script>alert("hehe")</script> 07-23 08:41

dsf 07-23 08:41

<script>alert("hehe")</script>

我也試試 10-08 06:44

<script>alert("hehe")</script>

hehe 10-20 08:08

<script>alert("赫赫")</script>

匿名读者 10-30 13:47

<script type="javascript">alert("abc");</script>

hehe 11-30 13:59

<script>alert("hehe")</script>

<script>alert("thanks");</script> 12-22 17:25

snicker 01-17 08:04

头疼杀手 pain killer 应为 止痛药

匿名读者 05-07 06:36

感受一下

匿名读者 05-18 07:34

123123

<script>alert("hehe")</script> 08-07 08:50

<script>alert("hehe")</script>我也来试试~

上一章怎么没有看见这么多人 09-22 02:01

23333 10-06 14:13

尼萌都在干嘛( ╯□╰ )

f 11-30 09:33

fewfwefw

容嬷嬷 01-06 14:19

<script>alert("hehe")</script>

匿名读者 06-03 11:33

<script alert("hehe")

</p><script>alert('1')</script><p> 06-03 11:35

</p><script>alert('1')</script><p>

匿名读者 04-11 07:40

ssss

匿名读者 04-11 07:41

<script>alert("ddd")</script>

匿名读者 04-25 01:47

alert("test")

asd 06-20 19:00

javascrpt:alert('')

匿名读者 06-27 07:52

<script>alert("what's going on?")</script>

cc 01-23 07:42

<script>alert("hehe")</script>

a666 10-28 07:27

<script>alert("hehe")</script>

haha 12-17 02:15

<script>alert("hehe")</script>

匿名读者 03-26 03:56

alert("hehe")

匿名读者 03-26 03:57

javascrpt:alert('qqq')

user001 06-13 02:27

1111 02-15 12:29

<script>alert("thanks");</script>

<script>alert("thank ..");</script> 02-15 12:29

<script>alert("thanks");</script>

对这一段的评论会显示在这里

下面我们来看看如何打开session功能,并在视图中使用它。

dfd 05-03 12:20

dfd

对这一段的评论会显示在这里

打开 Sessions功能

对这一段的评论会显示在这里

Sessions 功能是通过一个中间件(参见第17章)和一个模型(model)来实现的。 要打开sessions功能,需要以下几步操作:

匿名读者 12-25 09:21

k

qiya 12-11 12:11

我想看一下用户注册到底是怎么回事

对这一段的评论会显示在这里
  1. 编辑 MIDDLEWARE_CLASSES 配置,确保 MIDDLEWARE_CLASSES 中包含 'django.contrib.sessions.middleware.SessionMiddleware'
  2. 确认 INSTALLED_APPS 中有 'django.contrib.sessions' (如果你是刚打开这个应用,别忘了运行 manage.py syncdb )
eric 11-04 13:20

test

asd 02-26 15:44

haha

匿名读者 05-07 06:49

如今已经改为用 manage.py migrate

eon 06-29 06:22

2.0的django中,MIDDLEWARE_CLASSES 改为了MIDDLEWARE

对这一段的评论会显示在这里

如果项目是用 startproject 来创建的,配置文件中都已经安装了这些东西,除非你自己删除,正常情况下,你无需任何设置就可以使用session功能。

对这一段的评论会显示在这里

如果不需要session功能,你可以删除 MIDDLEWARE_CLASSES 设置中的 SessionMiddlewareINSTALLED_APPS 设置中的 'django.contrib.sessions' 。虽然这只会节省很少的开销,但积少成多啊。

moxwose 01-07 08:29

tommy_shi 12-30 06:59

什么时候不需要session?比如哪些网站?

不做用户登录要什么sessions 09-22 02:17

对这一段的评论会显示在这里

在视图中使用Session

对这一段的评论会显示在这里

SessionMiddleware 激活后,每个传给视图(view)函数的第一个参数HttpRequest 对象都有一个 session 属性,这是一个字典型的对象。 你可以象用普通字典一样来用它。 例如,在视图(view)中你可以这样用:

沈世军 10-21 08:44

+---------------------------------+---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ |参数 |缺省值 |描述 | +=======+=======+=================+===========================+====================================================================================================================================================================================+ |max_age|None |cookie需要延续的时间(以秒为单位) 如果参数是None,这个cookie会延续到浏览器关闭为止。 | +-------+-------+-----------------+---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ |expires|None |cookie失效的实际日期/时间。如果给出了这个参数,它会覆盖max_age参数。 | +-------+-------+-----------------+---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ |path |"/" |cookie生效的路径前缀。浏览器只会把cookie回传给带有该路径的页面,这样你可以避免将cookie | | | | | | | |传给站点中的其他的应用。当你不是控制你的站点的顶层时,这样做是特别有用的。 | +-------+-------+-----------------+----

Xin 09-12 01:04

什么时候会传送session。传送的内容是什么。为何开启后每个请求都有session,每次发送的session都是一样的吗?求解答,新手。

对这一段的评论会显示在这里
# Set a session value:
request.session["fav_color"] = "blue"

# Get a session value -- this could be called in a different view,
# or many requests later (or both):
fav_color = request.session["fav_color"]

# Clear an item from the session:
del request.session["fav_color"]

# Check if the session has a given key:
if "fav_color" in request.session:
    ...
对这一段的评论会显示在这里

其他的映射方法,如 keys()items()request.session 同样有效:

对这一段的评论会显示在这里

下面是一些有效使用Django sessions的简单规则:

对这一段的评论会显示在这里

用正常的字符串作为key来访问字典 request.session , 而不是整数、对象或其它什么的。

对这一段的评论会显示在这里

Session字典中以下划线开头的key值是Django内部保留key值。 框架只会用很少的几个下划线 开头的session变量,除非你知道他们的具体含义,而且愿意跟上Django的变化,否则,最好 不要用这些下划线开头的变量,它们会让Django搅乱你的应用。

对这一段的评论会显示在这里

比如,不要象这样使用_fav_color 会话密钥(session key):

lin134340 05-03 05:03

此句应该为:不要将会话的键名定义为像"_fav_color"这种样子

对这一段的评论会显示在这里
request.session['_fav_color'] = 'blue' # Don't do this!
对这一段的评论会显示在这里

不要用一个新对象来替换掉 request.session ,也不要存取其属性。 可以像Python中的字典那样使用。 例如:

对这一段的评论会显示在这里
request.session = some_other_object # Don't do this!

request.session.foo = 'bar' # Don't do this!
对这一段的评论会显示在这里

我们来看个简单的例子。 这是个简单到不能再简单的例子:在用户发了一次评论后将has_commented设置为True。 这是个简单(但不很安全)的、防止用户多次评论的方法。

对这一段的评论会显示在这里
def post_comment(request):
    if request.method != 'POST':
        raise Http404('Only POSTs are allowed')

    if 'comment' not in request.POST:
        raise Http404('Comment not submitted')

    if request.session.get('has_commented', False):
        return HttpResponse("You've already commented.")

    c = comments.Comment(comment=request.POST['comment'])
    c.save()
    request.session['has_commented'] = True
    return HttpResponse('Thanks for your comment!')
Tomoya 06-13 12:11

if request.session.get('has_commented', False): ---> if request.session.get('has_commented', True):

phonty 04-15 14:29

上面的评述不正确。就是默认False。

TT 08-11 02:37

上面说has_comment为True则代表评论过,为什么这里要判断“if request.session.get('has_commented', False):”则返回You've already commented???

roger 11-29 15:28

@TT 你没有理解get函数的用法,第二个参数是在第一个参数key所对应的值为None的时候才作为它的值,所以这句话的意思是得到has_commented的值,如果他为空就赋值为false,这样这个if只有在has_commented为true时才会成立

biaoqianwo 09-03 03:14

@roger 说的好,不然我也理解错了!顶!

njw 09-23 07:44

第三个if相当于: if 'has_commented' in request.session: result = request.session['has commented'] else: result = False if result: return HttpResponse("You've already commented.")

LCH 10-27 03:38

@roger 赞~~~~

匿名读者 05-02 03:04

javascrpt:alert('')

匿名读者 05-02 03:04

if request.session.get('has_commented', False): ---> if request.session.get('has_commented', True):

yoooo 04-14 02:43

感谢@roger @TT 解释得好清楚,原来get函数得默认值是这个意思!

纸上往事 08-15 03:25

dict.get(key, default=None)

对这一段的评论会显示在这里

下面是一个很简单的站点登录视图(view):

小利子 01-13 02:56

这个Member在哪儿出现过?

silent 02-24 07:05

这个,如果用户名存在,但是密码不匹配,就不会爆出异常,也不会重定向到登陆成功页面啊。

zcar 05-23 03:38

Member应该是model中定义的数据表名

Xin 09-12 01:09

request.session['member_id'] = m.id 这个是什么意思?不懂啊,求教

回楼上 09-22 09:37

回楼上,那是member表里面记录id,这个id在模块里不设置,也会自动生成

回楼上 09-22 09:38

自动增长的唯一id

view代码 09-22 09:39

from django.http import HttpResponse,Http404,HttpResponseRedirect from django.shortcuts import render from django.template import RequestContext from login_chapter1401.models import Member def login(request): if request.method == 'POST': try: m = Member.objects.get(username=request.POST['user']) if m.password == request.POST['pass']: request.session['member_id'] = m.id return HttpResponseRedirect('../you-are-logged-in/') except Member.DoesNotExist: return HttpResponse("Your username and password didn't math.") return render(request,'login_chapter14.html') def login_ok(request): return render(request,'login_ok.html')

html代码 09-22 09:40

<html> <head> <title>Test Login</title> </head> <body> <form action="" method="post"> {% csrf_token %} <p> UserName:<input type="text" name= "user"</p> <p> PassWord:<input type="password" name="pass"></p> <input type="submit" value="Submit"> </form> </body> </html>

html代码2 09-22 09:40

<html> <head> <title>Login OK</title> </head> <body> <p>Successful.</p> <br> <a href='../logout'>logout</a> </body> </html>

model代码 09-22 09:41

from django.db import models class Member(models.Model): username = models.CharField(max_length=10) password = models.CharField(max_length=100) def __unicode__(self): return self.username

url代码1 09-22 09:42

from django.conf.urls import include, url from django.contrib import admin from urls13 import url13 from urls14 import url14 from views import * urlpatterns = [ url(r'^admin/', include(admin.site.urls)), url(r'^thirteen/',include(url13)), url(r'^fourteen/',include(url14)), ]

url代码2 09-22 09:42

from django.conf.urls import include, url from django.contrib import admin from fourteen_views import * url14 = [ url(r'^getcook/$',show_color), url(r'^setcook/$',set_color), url(r'^post_comment/$',post_comment), url(r'^login/$',login), url(r'^logout/$',logout), url(r'^you-are-logged-in/$',login_ok), ]

Sylvia 03-16 08:04

request.session['member_id'] = m.id 里面的member_id是什么意思 这个m.id中的id,如果我表格中就有一个自增长的id,这个id我应该用表格中的项名称 ,还是可以直接用id啊,求解

Lionel 11-02 10:53

这文章真的是太老旧了,username = request.POST.get('username','')

对这一段的评论会显示在这里
def login(request):
    if request.method != 'POST':
        raise Http404('Only POSTs are allowed')
    try:
        m = Member.objects.get(username=request.POST['username'])
        if m.password == request.POST['password']:
            request.session['member_id'] = m.id
            return HttpResponseRedirect('/you-are-logged-in/')
    except Member.DoesNotExist:
        return HttpResponse("Your username and password didn't match.")
对这一段的评论会显示在这里

下面的例子将登出一个在上面已通过login() 登录的用户:

zxw 07-29 11:33

退出吧

view代码 09-22 09:43

from django.http import HttpResponse,Http404,HttpResponseRedirect from django.shortcuts import render from django.template import RequestContext from login_chapter1401.models import Member def logout(request): try: del request.session['member_id'] except KeyError: return HttpResponse("Not member_id.") return HttpResponse("You're logged out.")

html代码 09-22 09:44

<html> <head> <title>Login OK</title> </head> <body> <p>Successful.</p> <br> <a href='../logout'>logout</a> </body> </html>

对这一段的评论会显示在这里
def logout(request):
    try:
        del request.session['member_id']
    except KeyError:
        pass
    return HttpResponse("You're logged out.")
对这一段的评论会显示在这里

注意

对这一段的评论会显示在这里

在实践中,这是很烂的用户登录方式,稍后讨论的认证(authentication )框架会帮你以更健壮和有利的方式来处理这些问题。 这些非常简单的例子只是想让你知道这一切是如何工作的。 这些实例尽量简单,这样你可以更容易看到发生了什么

wind 08-03 08:47

哭了..原来还有更复杂的在后面

对这一段的评论会显示在这里

设置测试Cookies

对这一段的评论会显示在这里

,并在后续的视图(view)、而不是当前的视图(view)中检查 request.session.test_cookie_worked()

对这一段的评论会显示在这里

虽然把 set_test_cookie()test_cookie_worked() 分开的做法看起来有些笨拙,但由于cookie的工作方式,这无可避免。 当设置一个cookie时候,只能等浏览器下次访问的时候,你才能知道浏览器是否接受cookie。

xiaocainiaok 05-02 15:55

为什么 要在session的模块里 才能检测cookie?

阿斯顿 02-28 00:16

因为只有下次才能判断是否使用cookie

needle 10-27 11:37

不用session也可以做cookie检测,只是session要用到cookie所以才在session下做个cookie检测。

对这一段的评论会显示在这里

检查cookie是否可以正常工作后,你得自己用 delete_test_cookie() 来清除它,这是个好习惯。 在你证实了测试cookie已工作了之后这样操作。

对这一段的评论会显示在这里

这是个典型例子:

对这一段的评论会显示在这里
def login(request):

    # If we submitted the form...
    if request.method == 'POST':

        # Check that the test cookie worked (we set it below):
        if request.session.test_cookie_worked():

            # The test cookie worked, so delete it.
            request.session.delete_test_cookie()

            # In practice, we'd need some logic to check username/password
            # here, but since this is an example...
            return HttpResponse("You're logged in.")

        # The test cookie failed, so display an error message. If this
        # were a real site, we'd want to display a friendlier message.
        else:
            return HttpResponse("Please enable cookies and try again.")

    # If we didn't post, send the test cookie along with the login form.
    request.session.set_test_cookie()
    return render_to_response('foo/login_form.html')
csrf报错 09-23 03:44

在这里做实例测试时,如果开启了csfr,view添加了“django.middleware.csrf.CsrfViewMiddleware”,表单添加了“{% csrf_token %}”,当浏览器取消存取cookie访问时,会提示“Forbidden (403)Reason given for failure:CSRF cookie not set. ”之类的错误,我这里是关闭了csrf,“from django.views.decorators.csrf import csrf_exempt”,在登陆方法上添加装饰器“@csrf_exempt”,这样方法流程可以正常。在开启csrf前提下实现,还请知道的告知下

needle 10-27 11:48

csrf就起到了cookie检测的作用啊,如果django开启csrf,而浏览器禁用cookie则django会报错,因为csrf中间件要求cookie要含有csrftoken名值对。 “您看到此消息是由于该站点在提交表单时需要一个CSRF cookie。此项是出于安全考虑,以确保您的浏览器没有被第三方劫持。 如果您已经设置浏览器禁用cookies,请重新启用,至少针对这个站点,全部HTTPS请求,或者同源请求(same-origin)启用cookies。”

对这一段的评论会显示在这里

注意

对这一段的评论会显示在这里

再次强调,内置的认证函数会帮你做检查的。

tim 02-17 04:40

什么意思,不用手工去test cookie吗

zhkzyth 05-22 06:33

@tim,确实不用,你看看它源码实现

对这一段的评论会显示在这里

在视图(View)外使用Session

对这一段的评论会显示在这里

从内部来看,每个session都只是一个普通的Django model(在 django.contrib.sessions.models 中定义)。每个session都由一个随机的32字节哈希串来标识,并存储于cookie中。 因为它是一个标准的模型,所以你可以使用Django数据库API来存取session。

匿名读者 12-30 23:13

上网查了一下,哈希链好像不是随机的,而是经过一定的与会话次数相关的运算法则得到的结果。

对这一段的评论会显示在这里
>>> from django.contrib.sessions.models import Session
>>> s = Session.objects.get(pk='2b1189a188b44ad18c35e113ac6ceead')
>>> s.expire_date
datetime.datetime(2005, 8, 20, 13, 35, 12)
oserh 12-11 03:32

我用的django 1.4.2中已经没有pk字段,Session模型的字段包括:session_key, session_data, expire_date

tuxinhang 10-16 08:16

有pk字段的,只是没有显示在model里面,数据库中是有的

miss_xiangnian 01-15 01:30

Django 1.6中没有pk字段,但是貌似pk对应的就是session_key字段,求源码大神指教

匿名读者 06-03 11:53

回复ls,session_key字段对应的就是pk,已测试。

对这一段的评论会显示在这里

你需要使用get_decoded() 来读取实际的session数据。 这是必需的,因为字典存储为一种特定的编码格式。

对这一段的评论会显示在这里
>>> s.session_data
'KGRwMQpTJ19hdXRoX3VzZXJfaWQnCnAyCkkxCnMuMTExY2ZjODI2Yj...'
>>> s.get_decoded()
{'user_id': 42}
对这一段的评论会显示在这里

何时保存Session

对这一段的评论会显示在这里

缺省的情况下,Django只会在session发生变化的时候才会存入数据库,比如说,字典赋值或删除。

对这一段的评论会显示在这里
# Session is modified.
request.session['foo'] = 'bar'

# Session is modified.
del request.session['foo']

# Session is modified.
request.session['foo'] = {}

# Gotcha: Session is NOT modified, because this alters
# request.session['foo'] instead of request.session.
request.session['foo']['bar'] = 'baz'
Lion 01-23 02:55

request.session['foo']['bar'] 什么意思

jeff 05-27 13:55

request.session['foo']['bar'] 的意思是foo这个session值是一个字典,这里修改的是session['foo']字典中的bar,所以不是修改session本身,所以session['foo']没变,变的是它的值

agon 11-01 00:44

只有函数执行完,所发生的变化才在数据库里修改,如果request.session['foo']={}执行完后马上用Session.objects.get获取数据库里session不会看到foo,只有函数结束后,才会发现

对这一段的评论会显示在这里

你可以设置 SESSION_SAVE_EVERY_REQUESTTrue 来改变这一缺省行为。如果置为True的话,Django会在每次收到请求的时候保存session,即使没发生变化。

zlleah 01-23 05:52

设置SESSION_SAVE_EVERY_REQUEST ,在settings.py中自定义吗?

zlleah 01-23 05:57

“设置SESSION_SAVE_EVERY_REQUEST ,在settings.py中自定义吗?”,原来在global_settings.py中(我的是Django-1.4.3版本)。可是加载了DJANGO_SETTINGS_MODULE=mysite.settings后,不是不会加载global_settigns.py吗?还是说会加载settings.py中没有的部分?

zlleah 01-23 06:43

"下面是django在编译settings文件时运用的规则: 从 global_settings.py 装载settings . 从指定settings 文件装载settings , 在需要的时候,覆盖全局的settings 注意一个settings 文件不应该导入 global_settings ,因为那是多余(冗余)的。"原来是我自己理解错了,原意是编译settings时,会先加载global_settings.py,再加载自己工程目录下的settings.py,所以没有必要在自己工程目录下的settings.py写上这么一句“from django.conf import global_settings”

对这一段的评论会显示在这里

注意,会话cookie只会在创建和修改的时候才会送出。 但如果 SESSION_SAVE_EVERY_REQUEST 设置为 True ,会话cookie在每次请求的时候都会送出。 同时,每次会话cookie送出的时候,其 expires 参数都会更新。

对这一段的评论会显示在这里

浏览器关闭即失效会话 vs 持久会话

对这一段的评论会显示在这里

你可能注意到了,Google给我们发送的cookie中有 expires=Sun, 17-Jan-2038 19:14:07 GMT; cookie可以有过期时间,这样浏览器就知道什么时候可以删除cookie了。 如果cookie没有设置过期时间,当用户关闭浏览器的时候,cookie就自动过期了。 你可以改变 SESSION_EXPIRE_AT_BROWSER_CLOSE 的设置来控制session框架的这一行为。

对这一段的评论会显示在这里

缺省情况下, SESSION_EXPIRE_AT_BROWSER_CLOSE 设置为 False ,这样,会话cookie可以在用户浏览器中保持有效达 SESSION_COOKIE_AGE 秒(缺省设置是两周,即1,209,600 秒)。 如果你不想用户每次打开浏览器都必须重新登陆的话,用这个参数来帮你。

对这一段的评论会显示在这里

如果 SESSION_EXPIRE_AT_BROWSER_CLOSE 设置为 True ,当浏览器关闭时,Django会使cookie失效。

hliao 07-21 15:13

Django如何知道浏览器关闭而使cookie失效呢?

Sam 08-07 12:45

一般是看情况才设置吗?我觉得有些网站真的 不能让用户自动登录~~~比如正方系统

匿名读者 09-28 08:46

现在是改了配置了么,不生效

匿名读者 09-28 09:00

用IE没问题,火狐就不行

vianvio 05-26 07:33

@hliao 一般情况下sessionid是存在cookie里的,而cookie如果不设置expire date那么浏览器关闭后就自动删除了。而服务器端只要验证每次过来的请求头里是否有正确的sessionid,就可以判断是否是存储的会话了。而这也意味着需要对session表做定期清理,如果用web2py框架,会发现经常出现一堆session记录,要手动去清理的

对这一段的评论会显示在这里

其他的Session设置

对这一段的评论会显示在这里

除了上面提到的设置,还有一些其他的设置可以影响Django session框架如何使用cookie,详见表 14-2.

对这一段的评论会显示在这里

技术细节

对这一段的评论会显示在这里

如果你还是好奇的话,下面是一些关于session框架内部工作方式的技术细节:

对这一段的评论会显示在这里

session 字典接受任何支持序列化的Python对象。 参考Python内建模块pickle的文档以获取更多信息。

对这一段的评论会显示在这里

Session 数据存在数据库表 django_session

对这一段的评论会显示在这里

Session 数据在需要的时候才会读取。 如果你从不使用 request.session , Django不会动相关数据库表的一根毛。

vincent 05-19 09:18

一根毛……

xing.lin 08-22 08:07

你确定只是一根毛

sehone 08-27 10:26

哈哈 搞笑吧你

Wally Yu 02-21 07:03

实践表明,确实不会动一根毛...

django 04-03 07:05

风吹毛动

吴振伟 08-26 01:48

翻译很萌~

unuique 06-25 01:59

.....一根毛

good 12-18 06:54

形象比喻

呆滞的慢板 02-17 06:24

真心赞毛

shaopeng 05-22 21:02

毛给好评

aaron zhu 06-21 09:00

击节赞叹,好个一根毛!

Wally Yu 03-20 08:03

为繁忙的工作添加了一丝欢乐

对这一段的评论会显示在这里

Django 只在需要的时候才送出cookie。 如果你压根儿就没有设置任何会话数据,它不会 送出会话cookie(除非 SESSION_SAVE_EVERY_REQUEST 设置为 True )。

对这一段的评论会显示在这里

Django session 框架完全而且只能基于cookie。 它不会后退到把会话ID编码在URL中(像某些工具(PHP,JSP)那样)。

phper 08-09 08:38

php被鄙视了吗

不能像php它们URL重写 10-16 09:15

kknd 01-03 15:00

不能同意这个,实际上cookie也是通过http 头通信的,一样可以伪造

rainbow 12-11 06:22

没有回退方案,很蛋疼

对这一段的评论会显示在这里

这是一个有意而为之的设计。 把session放在URL中不只是难看,更重要的是这让你的站点 很容易受到攻击——通过 Referer header进行session ID”窃听”而实施的攻击。

对这一段的评论会显示在这里

如果你还是好奇,阅读源代码是最直接办法,详见 django.contrib.sessions

对这一段的评论会显示在这里

用户与Authentication

MorningBAI 02-24 03:24

为什么不翻译Authentication?如果怕两个auth分不清,可以加括号吧

对这一段的评论会显示在这里

通过session,我们可以在多次浏览器请求中保持数据, 接下来的部分就是用session来处理用户登录了。 当然,不能仅凭用户的一面之词,我们就相信,所以我们需要认证。

对这一段的评论会显示在这里

当然了,Django 也提供了工具来处理这样的常见任务(就像其他常见任务一样)。 Django 用户认证系统处理用户帐号,组,权限以及基于cookie的用户会话。 这个系统一般被称为 auth/auth (认证与授权)系统。 这个系统的名称同时也表明了用户常见的两步处理。 我们需要

匿名读者 11-07 03:16

auth/auth?

hashi 09-08 13:40

authentication/authorization

ununique 06-25 02:04

authentication/authorization,可以翻译为验证/授权吧

good 12-18 06:59

authentication 是验证,使验证的动作。 authorization 是赋权,联想记忆,享有作者般的权利。

对这一段的评论会显示在这里
  1. 验证 (认证) 用户是否是他所宣称的用户(一般通过查询数据库验证其用户名和密码)
  2. 验证用户是否拥有执行某种操作的 授权 (通常会通过检查一个权限表来确认)
对这一段的评论会显示在这里

根据这些需求,Django 认证/授权 系统会包含以下的部分:

对这一段的评论会显示在这里
  • 用户 : 在网站注册的人
  • 权限 : 用于标识用户是否可以执行某种操作的二进制(yes/no)标志
  • :一种可以将标记和权限应用于多个用户的常用方法
  • Messages : 向用户显示队列式的系统消息的常用方法
对这一段的评论会显示在这里

如果你已经用了admin工具(详见第6章),就会看见这些工具的大部分。如果你在admin工具中编辑过用户或组,那么实际上你已经编辑过授权系统的数据库表了。

对这一段的评论会显示在这里

打开认证支持

对这一段的评论会显示在这里

像session工具一样,认证支持也是一个Django应用,放在 django.contrib 中,所以也需要安装。 与session系统相似,它也是缺省安装的,但如果它已经被删除了,通过以下步骤也能重新安装上:

对这一段的评论会显示在这里
  1. 根据本章早前的部分确认已经安装了session 框架。 需要确认用户使用cookie,这样sesson 框架才能正常使用。
  2. 'django.contrib.auth' 放在你的 INSTALLED_APPS 设置中,然后运行 manage.py syncdb以创建对应的数据库表。
  3. 确认 SessionMiddleware 后面的 MIDDLEWARE_CLASSES 设置中包含 'django.contrib.auth.middleware.AuthenticationMiddleware' SessionMiddleware。
GitFree 08-13 15:31

这样session 框架才能正常使用

jacky-chou 05-07 06:24

句子末尾的SessionMiddleware多余了。

duzhor 12-10 09:51

在django1.9及以上版本中没有syncdb命令,已经集成到migrate命令中

duzhor 12-10 09:51

对这一段的评论会显示在这里

这样安装后,我们就可以在视图(view)的函数中处理user了。 在视图中存取users,主要用 request.user ;这个对象表示当前已登录的用户。 如果用户还没登录,这就是一个AnonymousUser对象(细节见下)。

翻译有误 11-07 00:58

译文:这个对象表示当前已登录的用户。 原文:this is an object that represents the currently logged-in user 应为:这是一个能呈现已经登录的用户的对象

对这一段的评论会显示在这里

你可以很容易地通过 is_authenticated() 方法来判断一个用户是否已经登录了:

魏哲 09-02 02:32

此处is_authenticated()是用来判断用户是否注册,并非判断是否已经登录.

魏哲 09-02 02:48

is_authenticated()是判断是否已经登录. 我搞错了.

cc 01-24 07:28

清除了cookie,或者第一次连,其值就为false

srsyoyo 07-29 08:01

request.user.is_authenticated()再django 3.0中会报错:“'bool' object is not callable”。解决方法是不要后面的括号,即:request.user.is_authenticated

对这一段的评论会显示在这里
if request.user.is_authenticated():
    # Do something for authenticated users.
else:
    # Do something for anonymous users.
对这一段的评论会显示在这里

使用User对象

对这一段的评论会显示在这里

User 实例一般从 request.user ,或是其他下面即将要讨论到的方法取得,它有很多属性和方法。 AnonymousUser 对象模拟了 部分 的接口,但不是全部,在把它当成真正的user对象 使用前,你得检查一下 user.is_authenticated() 表14-3和14-4分别列出了User 对象中的属性(fields)和方法。

对这一段的评论会显示在这里

Error parsing content block for the “table” directive: exactly one table expected.

对这一段的评论会显示在这里
.. table:: 表 14-4. ``User`` 对象方法

   +---------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+
   |方法                                                                                         |描述                                                                                                                                                  |
   +=============================================================================================+======================================================================================================================================================+
   |``is_authenticated()``                                                                       |对于真实的User对象,总是返回\ `` True`` 。                                                                                                            |
   |                                                                                             |这是一个分辨用户是否已被鉴证的方法。 它并不意味着任何权限,也不检查用户是否仍是活动的。 它仅说明此用户已被成功鉴证。                                  |
   +---------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+
   |``is_anonymous()``                                                                           |对于\ `` AnonymousUser`` 对象返回\ `` True`` (对于真实的\ `` User`` 对象返回\ `` False`` )。                                                        |
   |                                                                                             |总的来说,比起这个方法,你应该倾向于使用\ `` is_authenticated()`` 方法。                                                                              |
   +---------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+
   |``get_full_name()``                                                                          |返回\ `` first_name`` 加上\ `` last_name`` ,中间插入一个空格。                                                                                       |
   +---------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+
   |``set_password(passwd)``                                                                     |设定用户密码为指定字符串(自动处理成哈希串)。 实际上没有保存\ ``User``\对象。                                                                        |
   +---------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+
   |check_password(passwd)                                                                       |如果指定的字符串与用户密码匹配则返回\ ``True``\。 比较时会使用密码哈希表。                                                                            |
   +---------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+
   |``get_group_permissions()``                                                                  |返回一个用户通过其所属组获得的权限字符串列表。                                                                                                        |
   +---------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+
   |``get_all_permissions()``                                                                    |返回一个用户通过其所属组以及自身权限所获得的权限字符串列表。                                                                                          |
   +---------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+
   |``has_perm(perm)``                                                                           |如果用户有指定的权限,则返回\ `` True`` ,此时\ `` perm`` 的格式是\ `` "package.codename"`` 。如果用户已不活动,此方法总是返回\ `` False`` 。         |
   +---------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+
   |has_perms(perm_list)                                                                         |如果用户拥有\ * 全部* 的指定权限,则返回\ `` True`` 。 如果用户是不活动的,这个方法总是返回\ `` False`` 。                                            |
   +---------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+
   |``has_module_perms(app_label)``                                                              |如果用户拥有给定的\ `` app_label`` 中的任何权限,则返回\ `` True`` 。如果用户已不活动,这个方法总是返回\ `` False`` 。                                |
   +---------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+
   |get_and_delete_messages()                                                                    |返回一个用户队列中的\ `` Message`` 对象列表,并从队列中将这些消息删除。                                                                               |
   +---------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+
   |``email_user(subj, msg)``                                                                    |向用户发送一封电子邮件。 这封电子邮件是从\ `` DEFAULT_FROM_EMAIL`` 设置的地址发送的。 你还可以传送一个第三参数:\ `` from_email`` ,以覆盖电邮中的发送地址。|
   +---------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+
blinko 02-02 06:07

这个table的排版有问题

phonty 04-15 14:45

拷贝,粘贴到记事本。就看全了。

Li Hsing 10-15 06:31

二楼牛人!

匿名读者 09-10 02:59

此站没有支持markdon语法造成的。

对这一段的评论会显示在这里

最后,User 对象有两个many-to-many属性。 groupspermissions 。正如其他的many-to-many属性使用的方法一样,User 对象可以获得它们相关的对象:

对这一段的评论会显示在这里
# Set a user's groups:
myuser.groups = group_list

# Add a user to some groups:
myuser.groups.add(group1, group2,...)

# Remove a user from some groups:
myuser.groups.remove(group1, group2,...)

# Remove a user from all groups:
myuser.groups.clear()

# Permissions work the same way
myuser.permissions = permission_list
myuser.permissions.add(permission1, permission2, ...)
myuser.permissions.remove(permission1, permission2, ...)
myuser.permissions.clear()
agon 10-29 14:09

user_permissions新版本名字是这个

对这一段的评论会显示在这里

登录和退出

saf 02-14 06:32

“以及其他奇技淫巧” 汗、、、

游泳的猪 11-07 06:32

这个翻译太汗了....

samuel 11-24 07:37

奇技淫巧 ( qí jì yín qiǎo )   解 释 指过于奇巧而无益的技艺与制品。奇,奇异。淫,过分,极端。   出 处 谓过于奇巧而无益的技艺与制品。《书·泰誓下》:“﹝ 商王 ﹞作奇技淫巧,以悦妇人。” 孔颖达 疏:“奇技谓奇异技能,淫巧谓过度工巧。二者大同,但技据人身,巧指器物为异耳。” 清 管同 《禁用洋货议》:“昔者,圣王之世,服饰有定制,而作奇技淫巧者有诛。”   用 法 联合式;作宾语、定语;指新奇的技艺和作品

Wally Yu 02-21 07:20

楼上的厉害...

phonty 04-15 14:47

本来就不是什么坏词。有人想多了。

骆驼 04-20 09:12

都别YY了 看代码吧

kk 07-18 10:00

……

lincy 08-22 11:45

﹝ 商王 ﹞作奇技淫巧,以悦妇人。。。。。

jekkay 04-04 09:35

突然被这个词逗乐了。“奇技淫巧”,翻译的人真人才啊

gangboy 06-13 05:35

我想歪了,自己去旁邊罰站

@@ 09-26 04:36

不就是按摩棒,跳蛋之类的东西吗?

对这一段的评论会显示在这里

login()

对这一段的评论会显示在这里

认证给出的用户名和密码,使用 authenticate() 函数。它接受两个参数,用户名 username 和 密码 password ,并在密码对给出的用户名合法的情况下返回一个 User 对象。 如果密码不合法,authenticate()返回None

对这一段的评论会显示在这里
>>> from django.contrib import auth
>>> user = auth.authenticate(username='john', password='secret')
>>> if user is not None:
...     print "Correct!"
... else:
...     print "Invalid password."
对这一段的评论会显示在这里

authenticate() 只是验证一个用户的证书而已。 而要登录一个用户,使用 login() 。该函数接受一个 HttpRequest 对象和一个 User 对象作为参数并使用Django的会话( session )框架把用户的ID保存在该会话中。

匿名读者 11-07 06:00

“证书” 这样翻译容易引起误解

对这一段的评论会显示在这里

下面的例子演示了如何在一个视图中同时使用 authenticate()login() 函数:

对这一段的评论会显示在这里
from django.contrib import auth

def login_view(request):
    username = request.POST.get('username', '')
    password = request.POST.get('password', '')
    user = auth.authenticate(username=username, password=password)
    if user is not None and user.is_active:
        # Correct password, and the user is marked "active"
        auth.login(request, user)
        # Redirect to a success page.
        return HttpResponseRedirect("/account/loggedin/")
    else:
        # Show an error page
        return HttpResponseRedirect("/account/invalid/")
对这一段的评论会显示在这里

注销一个用户,在你的视图中使用 django.contrib.auth.logout() 。 它接受一个HttpRequest对象并且没有返回值。

对这一段的评论会显示在这里
from django.contrib import auth

def logout_view(request):
    auth.logout(request)
    # Redirect to a success page.
    return HttpResponseRedirect("/account/loggedout/")
对这一段的评论会显示在这里

注意,即使用户没有登录, logout() 也不会抛出任何异常。

对这一段的评论会显示在这里

在实际中,你一般不需要自己写登录/登出的函数;认证系统提供了一系例视图用来处理登录和登出。 使用认证视图的第一步是把它们写在你的URLconf中。 你需要这样写:

pengyao 11-07 06:40

"系例"似乎应该翻译成“系列”

对这一段的评论会显示在这里
from django.contrib.auth.views import login, logout

urlpatterns = patterns('',
    # existing patterns here...
    (r'^accounts/login/$',  login),
    (r'^accounts/logout/$', logout),
)
匿名读者 01-24 09:44

我猜想一定会有人点进来看,然后发现这tm教人用django的教程还存在这样的漏洞

cjyfff 03-19 04:09

上面那人真闲,想证明自己聪明一点吗?

小武 03-25 16:40

每次看到这个,都想这货真蛋疼

匿名读者 09-29 07:20

脑残

匿名读者 12-12 08:17

智障

对这一段的评论会显示在这里

/accounts/login//accounts/logout/ 是Django提供的视图的默认URL。

匿名读者 05-29 10:54

在settings里可以设置 LOGIN_URL ,默认为LOGIN='/accounts/login/', LOGOUT同理

ode2free 05-29 10:58

不填姓名也可以发表,呵呵

匿名读者 08-07 10:36

<script>alert("hahahahahahahah")</script>

匿名读者 02-15 09:17

fsdfsfsdf

:-) 04-22 09:57

速度发送发

匿名读者 05-25 16:33

打撒的撒

匿名读者 08-28 09:35

花见花开

匿名读者 05-08 06:52

qweqw

对这一段的评论会显示在这里

缺省情况下, login 视图渲染 registragiton/login.html 模板(可以通过视图的额外参数 template_name 修改这个模板名称)。 这个表单必须包含 usernamepassword 域。如下示例: 一个简单的 template 看起来是这样的

July75 02-07 04:08

registragiton/login.html -> registration/login.html

ode2free 05-29 10:57

https://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.views.login

匿名读者 09-28 02:29

真晕

魏哲 09-02 04:02

registration/login.html

智商不高 05-06 09:13

registration/login.html 需要自己建立 否则提示模板不存在

qiya 12-11 14:28

我照着做,为什么说registragiton/login.html这个不存在呢??我应该怎么办???

mzvast 07-12 09:04

要保存到templates/reg.../login.html

对这一段的评论会显示在这里
{% extends "base.html" %}

{% block content %}

  {% if form.errors %}
    <p class="error">Sorry, that's not a valid username or password</p>
  {% endif %}

  <form action="" method="post">
    <label for="username">User name:</label>
    <input type="text" name="username" value="" id="username">
    <label for="password">Password:</label>
    <input type="password" name="password" value="" id="password">

    <input type="submit" value="login" />
    <input type="hidden" name="next" value="{{ next|escape }}" />
  </form>

{% endblock %}
oonxt 12-24 06:33

1.2.3中,需要在表单中加上一个{% csrf_token %}

tuxinhang 10-16 08:33

没错,在login函数的最后面的TemplateResponse里面也需要加上 context_instance=RequestContext(request)才行

匿名读者 12-31 13:05

一楼是正确的,在表单内部使用csrf_token 因为这个系统自带的login使用了@csrf_protect修饰符,处理的表单里面必须有这个token以便框架生成一个隐藏的域提交数据 2L是错误的,不需要修改哦

小武 03-12 16:24

123中?哪里加这个csrf?

asuka 07-07 06:10

这里最后添加了一个隐藏域,有什么作用呢?

mzvast 07-12 09:28

隐藏区域改成<input type="hidden" name="next" value="{{ '/hello' }}" />则登陆成功会跳转到/hello页面

the ocean 08-11 07:08

context_instance 版本不一样,处理不一样,最新的方法要去官网

对这一段的评论会显示在这里

如果用户登录成功,缺省会重定向到 /accounts/profile 。 你可以提供一个保存登录后重定向URL的next隐藏域来重载它的行为。 也可以把值以GET参数的形式发送给视图函数,它会以变量next的形式保存在上下文中,这样你就可以把它用在隐藏域上了。

ode2free 05-29 11:57

settings.LOGIN_REDIRECT_URL

as 03-18 13:25

You can use url(r'^login/$', login, {'extra_context': {'next': '/foo'}}) in your urlpatterns or in your template or LOGIN_REDIRECT_URL='/foo' in your settings file.

scat 05-12 01:42

应该是/accounts/profile/,少写了后面的‘/’

对这一段的评论会显示在这里

logout视图有一些不同。 默认情况下它渲染 registration/logged_out.html 模板(这个视图一般包含你已经成功退出的信息)。 视图中还可以包含一个参数 next_page 用于退出后重定向。

Mike 08-17 02:50

next_page要怎么写呢,看得不是很明白。

Mike 08-17 03:18

已经看明白了,可以从URL那里得到,然后传递过去。

rcompass 10-14 23:22

next_page写错了,应为next(具体可看源代码)

虎头满 01-28 07:11

login函数可以通过两个参数来指定login的模板和跳转链接分别是template='模板'和extra_context': {'next': '/foo'}写到url里面的格式如下 url(r'^login/$', login, {‘template’:‘template.html’'extra_context': {'next': '/foo'}})

对这一段的评论会显示在这里

限制已登录用户的访问

ode2free 05-28 09:34

limiting access to logged in users : 只允许登录用户访问。

kk 07-19 06:30

“对已登录用户的访问限制”~哈哈这样更严谨

liyasong 07-16 12:06

“已”应改为“未”

lincy 08-22 12:08

一楼正解

匿名读者 02-01 12:57

我说呢看着怎么这么怪

对这一段的评论会显示在这里

有很多原因需要控制用户访问站点的某部分。

对这一段的评论会显示在这里

一个简单原始的限制方法是检查 request.user.is_authenticated() ,然后重定向到登陆页面:

对这一段的评论会显示在这里
from django.http import HttpResponseRedirect

def my_view(request):
    if not request.user.is_authenticated():
        return HttpResponseRedirect('/accounts/login/?next=%s' % request.path)
    # ...
对这一段的评论会显示在这里

或者显示一个出错信息:

对这一段的评论会显示在这里
def my_view(request):
    if not request.user.is_authenticated():
        return render_to_response('myapp/login_error.html')
    # ...
对这一段的评论会显示在这里

作为一个快捷方式, 你可以使用便捷的 login_required 修饰符:

对这一段的评论会显示在这里
from django.contrib.auth.decorators import login_required

@login_required
def my_view(request):
    # ...
sam 04-16 02:51

这个login_required要怎样用啊。。。放在view.py里,访问站点内的其他页面还是可以访问的。。。

sam 04-16 03:05

终于知道怎样用了。。。不过如果是urls.py那些又要怎样做呢?

吴振伟@thu 10-29 11:16

楼上开始遇到了什么问题?

dabin 07-27 02:43

对这一段的评论会显示在这里

login_required 做下面的事情:

对这一段的评论会显示在这里
  • 如果用户没有登录, 重定向到 /accounts/login/ , 把当前绝对URL作为 next 在查询字符串中传递过去, 例如: /accounts/login/?next=/polls/3/ 。
  • 如果用户已经登录, 正常地执行视图函数。 视图代码就可以假定用户已经登录了。
匿名读者 01-20 04:09

这个next参数是啥意思?

chqi 02-15 03:07

chqi 02-15 03:08

登录之后,接下来会处理的请求~

匿名读者 10-20 03:12

源码里,next这个变量控制着登录成功后,重定向的路径

对这一段的评论会显示在这里

对通过测试的用户限制访问

ode2free 05-28 10:35

limiting access to users who pass a test : 只允许通过检测的用户访问。

lincy 08-22 12:18

楼上正解,这翻译真是误人啊

jacksing 09-04 09:33

只能通过下面的内容来猜标题的意思

对这一段的评论会显示在这里

限制访问可以基于某种权限,某些检查或者为login视图提供不同的位置,这些实现方式大致相同。

对这一段的评论会显示在这里

一般的方法是直接在视图的 request.user 上运行检查。 例如,下面视图确认用户登录并是否有 polls.can_vote权限:

对这一段的评论会显示在这里
def vote(request):
    if request.user.is_authenticated() and request.user.has_perm('polls.can_vote')):
        # vote here
    else:
        return HttpResponse("You can't vote in this poll.")
匿名读者 06-23 16:01

怎么赋予权限呀?我说的是用代码实现

roger 11-30 14:21

楼上没有上文么?直接add就可以

<script>alert("hehe")</script> 02-16 06:44

<script>alert("hehe")</script>

zxw 07-30 00:32

@楼顶 直接用admin进行赋与权限

对这一段的评论会显示在这里

并且Django有一个称为 user_passes_test 的简洁方式。它接受参数然后为你指定的情况生成装饰器。

对这一段的评论会显示在这里
def user_can_vote(user):
    return user.is_authenticated() and user.has_perm("polls.can_vote")

@user_passes_test(user_can_vote, login_url="/login/")
def vote(request):
    # Code here can assume a logged-in user with the correct permission.
    ...
匿名读者 07-17 09:55

装饰器好用

Channer 07-29 07:44

这个callback function的user是哪里来的呢。 ?

urmyfaith 09-25 13:25

Python27\Lib\site-packages\Django-1.7-py2.7.egg\django\contrib\auth路径下"decorators.py"中的三个函数:"user_passes_test","login_required","permission_required".

对这一段的评论会显示在这里

是否认证,你应该自己做这件事。

对这一段的评论会显示在这里

例子中我们也展示了第二个可选的参数 login_url ,它让你指定你的登录页面的URL(默认为 /accounts/login/ )。 如果用户没有通过测试,那么user_passes_test将把用户重定向到login_url

对这一段的评论会显示在这里

既然检查用户是否有一个特殊权限是相对常见的任务,Django为这种情形提供了一个捷径: permission_required() 装饰器。 使用这个装饰器,前面的例子可以改写为:

对这一段的评论会显示在这里
from django.contrib.auth.decorators import permission_required

@permission_required('polls.can_vote', login_url="/login/")
def vote(request):
    # ...
对这一段的评论会显示在这里

注意, permission_required() 也有一个可选的 login_url 参数, 这个参数默认为 '/accounts/login/'

对这一段的评论会显示在这里

限制通用视图的访问

对这一段的评论会显示在这里

在Django用户邮件列表中问到最多的问题是关于对通用视图的限制性访问。 为实现这个功能,你需要自己包装视图,并且在URLconf中,将你自己的版本替换通用视图:

对这一段的评论会显示在这里
from django.contrib.auth.decorators import login_required
from django.views.generic.date_based import object_detail

@login_required
def limited_object_detail(*args, **kwargs):
    return object_detail(*args, **kwargs)
对这一段的评论会显示在这里

当然, 你可以用任何其他限定修饰符来替换 login_required

对这一段的评论会显示在这里

管理 Users, Permissions 和 Groups

对这一段的评论会显示在这里

管理认证系统最简单的方法是通过管理界面。 第六章讨论了怎样使用Django的管理界面来编辑用户和控制他们的权限和可访问性,并且大多数时间你使用这个界面就可以了。

对这一段的评论会显示在这里

然而,当你需要绝对的控制权的时候,有一些低层 API 需要深入专研,我们将在下面的章节中讨论它们。

对这一段的评论会显示在这里

使用 create_user 辅助函数创建用户:

对这一段的评论会显示在这里
>>> from django.contrib.auth.models import User
>>> user = User.objects.create_user(username='john',
...                                 email='jlennon@beatles.com',
...                                 password='glass onion')
对这一段的评论会显示在这里

在这里, userUser 类的一个实例,准备用于向数据库中存储数据。(create_user()实际上没有调用save())。 create_user() 函数并没有在数据库中创建记录,在保存数据之前,你仍然可以继续修改它的属性值。

joe 07-12 02:59

create_user()函数虽然没有调用save(),但已经在数据库中创建记录了。 不知道文中是否是其它意思。

demon 08-02 02:43

create_user()应该是保存在内存中了,只有在调用save()之后才会写入数据库

对这一段的评论会显示在这里
>>> user.is_staff = True
>>> user.save()
对这一段的评论会显示在这里

你可以使用 set_password() 来修改密码:

对这一段的评论会显示在这里
>>> user = User.objects.get(username='john')
>>> user.set_password('goo goo goo joob')
>>> user.save()
对这一段的评论会显示在这里

除非你清楚的知道自己在做什么,否则不要直接修改 password 属性。 其中保存的是密码的 加入salt的hash值 ,所以不能直接编辑。

对这一段的评论会显示在这里

一般来说, User 对象的 password 属性是一个字符串,格式如下:

对这一段的评论会显示在这里
hashtype$salt$hash
对这一段的评论会显示在这里

这是哈希类型,salt和哈希本身,用美元符号($)分隔。

对这一段的评论会显示在这里

hashtypesha1 (默认)或者 md5 ,它是用来处理单向密码哈希的算法。 Salt是一个用来加密原始密码以创建哈希的随机字符串,例如:

对这一段的评论会显示在这里
sha1$a1976$a36cc8cbf81742a8fb52e221aaeab48ed7f58ab4
对这一段的评论会显示在这里

User.set_password()User.check_password() 函数在后台处理和检查这些值。

对这一段的评论会显示在这里

salt化得哈希值

对这一段的评论会显示在这里

一次 哈希 是一次单向的加密过程,你能容易地计算出一个给定值的哈希码,但是几乎不可能从一个哈希码解出它的原值。

对这一段的评论会显示在这里

如果我们以普通文本存储密码,任何能进入数据库的人都能轻易的获取每个人的密码。 使用哈希方式来存储密码相应的减少了数据库泄露密码的可能。

对这一段的评论会显示在这里

然而,攻击者仍然可以使用 暴力破解 使用上百万个密码与存储的值对比来获取数据库密码。 这需要花一些时间,但是智能电脑惊人的速度超出了你的想象。

对这一段的评论会显示在这里

更糟糕的是我们可以公开地得到 rainbow tables (一种暴力密码破解表)或预备有上百万哈希密码值的数据库。 使用rainbow tables可以在几秒之内就能搞定最复杂的一个密码。

imLong 08-27 15:10

即“彩虹表”

对这一段的评论会显示在这里

在存储的hash值的基础上,加入 salt 值(一个随机值),增加了密码的强度,使得破解更加困难。 因为每个密码的salt值都不相同,这也限制了rainbow table的使用,使得攻击者只能使用最原始的暴力破解方法。

对这一段的评论会显示在这里

加入salt值得hash并不是绝对安全的存储密码的方法,然而却是安全和方便之间很好的折衷。

dk 08-27 03:08

加入salt值得hash 加入salt值的hash

对这一段的评论会显示在这里

我们可以使用这些底层工具来创建允许用户注册的视图。 最近每个开发人员都希望实现各自不同的注册方法,所以Django把写注册视图的工作留给了你。 幸运的是,这很容易。

对这一段的评论会显示在这里

作为这个事情的最简化处理, 我们可以提供一个小视图, 提示一些必须的用户信息并创建这些用户。 Django为此提供了可用的内置表单, 下面这个例子就使用了这个表单:

对这一段的评论会显示在这里
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response

def register(request):
    if request.method == 'POST':
        form = UserCreationForm(request.POST)
        if form.is_valid():
            new_user = form.save()
            return HttpResponseRedirect("/books/")
    else:
        form = UserCreationForm()
    return render_to_response("registration/register.html", {
        'form': form,
    })
oonxt 12-24 07:24

1.2以后,需要使用RequestContext.例如: return render_to_response('registration/register.html',{'form':form},context_instance=RequestContext(request))

scarl 09-03 09:22

第一句用来干嘛……?

tuxinhang 10-16 08:55

然后模板中<form>后面需要加上{% csrf_token %}

ddd 07-14 09:52

http://www.qttc.net/201209211.html 解决global name 'RequestContext' is not defined问题

mzvast 07-12 11:39

from django.shortcuts import render_to_response, RequestContext以及添加context_instance=RequestContext(request)到render_to_response第三个栏位

fuckReg 04-07 11:52

new_user这个变量从未使用, 什么鬼

对这一段的评论会显示在这里

这个表单需要一个叫 registration/register.html 的模板。这个模板可能是这样的:

对这一段的评论会显示在这里
{% extends "base.html" %}

{% block title %}Create an account{% endblock %}

{% block content %}
  <h1>Create an account</h1>

  <form action="" method="post">
      {{ form.as_p }}
      <input type="submit" value="Create the account">
  </form>
{% endblock %}
匿名读者 07-18 01:59

1.3以后不加{% csrf_token %},报403错误

对这一段的评论会显示在这里

在模板中使用认证数据

对这一段的评论会显示在这里

当前登入的用户以及他(她)的权限可以通过 RequestContext 在模板的context中使用(详见第9章)。

对这一段的评论会显示在这里

注意

对这一段的评论会显示在这里

从技术上来说,只有当你使用了 RequestContext这些变量才可用。 并且TEMPLATE_CONTEXT_PROCESSORS 设置包含了 “django.core.context_processors.auth” (默认情况就是如此)时,这些变量才能在模板context中使用。 TEMPLATE_CONTEXT_PROCESSORS 设置包含了 "django.core.context_processors.auth" (默认情况就是如此)时,这些变量才能在模板context中使用。

Gota 07-12 15:12

这句话重复了两遍.

Michael 10-15 04:04

把前一句删除了吧,重复了,而且格式不对

对这一段的评论会显示在这里

当使用 RequestContext 时, 当前用户 (是一个 User 实例或一个 AnonymousUser 实例) 存储在模板变量 {{ user }} 中:

对这一段的评论会显示在这里
{% if user.is_authenticated %}
  <p>Welcome, {{ user.username }}. Thanks for logging in.</p>
{% else %}
  <p>Welcome, new user. Please log in.</p>
{% endif %}
对这一段的评论会显示在这里

这些用户的权限信息存储在 {{ perms }} 模板变量中。

对这一段的评论会显示在这里

你有两种方式来使用 perms 对象。 你可以使用类似于 {{ perms.polls }} 的形式来检查,对于某个特定的应用,一个用户是否具有 任意 权限;你也可以使用 {{ perms.polls.can_vote }} 这样的形式,来检查一个用户是否拥有特定的权限。

对这一段的评论会显示在这里

这样你就可以在模板中的 {% if %} 语句中检查权限:

对这一段的评论会显示在这里
{% if perms.polls %}
  <p>You have permission to do something in the polls app.</p>
  {% if perms.polls.can_vote %}
    <p>You can vote!</p>
  {% endif %}
{% else %}
  <p>You don't have permission to do anything in the polls app.</p>
{% endif %}
tuxinhang 10-16 12:33

这个地方不对吧, {% if perms.polls %}不对,应该是 {% perms %}, {% if perms.polls.can_vote %}应该改为 {% if perms.app.can_vote %}才对,我的是1.4.5的版本, 不知道是不是版本的问题

对这一段的评论会显示在这里

权限、组和消息

对这一段的评论会显示在这里

在认证框架中还有其他的一些功能。 我们会在接下来的几个部分中进一步地了解它们。

对这一段的评论会显示在这里

权限

对这一段的评论会显示在这里

权限可以很方便地标识用户和用户组可以执行的操作。 它们被Django的admin管理站点所使用,你也可以在你自己的代码中使用它们。

对这一段的评论会显示在这里

Django的admin站点如下使用权限:

对这一段的评论会显示在这里
  • 只有设置了 add 权限的用户才能使用添加表单,添加对象的视图。
  • 只有设置了 change 权限的用户才能使用变更列表,变更表格,变更对象的视图。
  • 只有设置了 delete 权限的用户才能删除一个对象。
对这一段的评论会显示在这里

权限是根据每一个类型的对象而设置的,并不具体到对象的特定实例。 例如,我们可以允许Mary改变新故事,但是目前还不允许设置Mary只能改变自己创建的新故事,或者根据给定的状态,出版日期或者ID号来选择权限。

匿名读者 10-10 07:42

这,这,这,尼玛,要不要这么绕口

对这一段的评论会显示在这里

会自动为每一个Django模型创建三个基本权限:增加、改变和删除。 当你运行manage.py syncdb命令时,这些权限被添加到auth_permission数据库表中。

对这一段的评论会显示在这里

权限以 "<app>.<action>_<object_name>" 的形式出现。

对这一段的评论会显示在这里

就跟用户一样,权限也就是Django模型中的 django.contrib.auth.models 。因此如果你愿意,你也可以通过Django的数据库API直接操作权限。

对这一段的评论会显示在这里

对这一段的评论会显示在这里

组提供了一种通用的方式来让你按照一定的权限规则和其他标签将用户分类。 一个用户可以隶属于任何数量的组。

对这一段的评论会显示在这里

在一个组中的用户自动获得了赋予该组的权限。 例如, Site editors 组拥有 can_edit_home_page 权限,任何在该组中的用户都拥有这个权限。

对这一段的评论会显示在这里

组也可以通过给定一些用户特殊的标记,来扩展功能。 例如,你创建了一个 'Special users' 组,并且允许组中的用户访问站点的一些VIP部分,或者发送VIP的邮件消息。

对这一段的评论会显示在这里

和用户管理一样,admin接口是管理组的最简单的方法。 然而,组也就是Django模型 django.contrib.auth.models ,因此你可以使用Django的数据库API,在底层访问这些组。

对这一段的评论会显示在这里

消息

对这一段的评论会显示在这里

消息系统会为给定的用户接收消息。 每个消息都和一个 User 相关联。

对这一段的评论会显示在这里

在每个成功的操作以后,Django的admin管理接口就会使用消息机制。 例如,当你创建了一个对象,你会在admin页面的顶上看到 The object was created successfully 的消息。

对这一段的评论会显示在这里

你也可以使用相同的API在你自己的应用中排队接收和显示消息。 API非常地简单:

对这一段的评论会显示在这里
  • 要创建一条新的消息,使用 user.message_set.create(message='message_text')
  • 要获得/删除消息,使用 user.get_and_delete_messages() ,这会返回一个 Message 对象的列表,并且从队列中删除返回的项。
对这一段的评论会显示在这里

在例子视图中,系统在创建了播放单(playlist)以后,为用户保存了一条消息。

对这一段的评论会显示在这里
def create_playlist(request, songs):
    # Create the playlist with the given songs.
    # ...
    request.user.message_set.create(
        message="Your playlist was added successfully."
    )
    return render_to_response("playlists/create.html",
        context_instance=RequestContext(request))
Trek Neko 11-20 11:04

这里在Django1.4之后需要这么写: def create_playlist(request): messages.add_message(request, messages.INFO, 'Your playlist was added successfully') return render(request, "playlists/create.html")

对这一段的评论会显示在这里

当使用 RequestContext ,当前登录的用户以及他(她)的消息,就会以模板变量 {{ messages }} 出现在模板的context中。

ffff 09-19 13:36

<b>afdf</b>

AAA 02-18 07:14

这里没有人维护?

urmyfaith 09-25 16:13

参见: http://t.cn/RhTztXz 1) URLcof里接收参数songs 2) 视图里,使用messages.add_message()方法来创建一条消息. 需要导入包from django.contrib import messages 3) 在模版里 * 使用RequestContext * 传递songs参数供模版使用,**但是不显式提供messages给模版!** * 模版里使用for循环来遍历 4) **使用messages框架,不需要用户登录.** 5) request.user.message_set.creat()方法已经过时.

对这一段的评论会显示在这里
{% if messages %}
<ul>
    {% for message in messages %}
    <li>{{ message }}</li>
    {% endfor %}
</ul>
{% endif %}
对这一段的评论会显示在这里

需要注意的是 RequestContext 会在后台调用 get_and_delete_messages ,因此即使你没有显示它们,它们也会被删除掉。

对这一段的评论会显示在这里

最后注意,这个消息框架只能服务于在用户数据库中存在的用户。 如果要向匿名用户发送消息,请直接使用会话框架。

对这一段的评论会显示在这里

下一章

对这一段的评论会显示在这里

是的,会话和认证系统有太多的东西要学。 大多数情况下,你并不需要本章所提到的所有功能。

对这一段的评论会显示在这里

下一章 <../chapter15/>__ ,我们会看一下Django的缓存机制,这是一个提高你的网页应用性能的便利的办法。

ode2free 06-14 00:44

这章很好,有一些表格显示错误快改改吧

对这一段的评论会显示在这里