ID English原文 中文翻译 最近翻译记录 状态 操作
0#翻译 Chapter 14: 第十四章: 翻译
1#翻译 Sessions, Users, and Registration 会话、用户和注册 翻译
4#翻译 It's time for a confession: 是时候承认了: 翻译
5#翻译 we've been deliberately ignoring an important aspect of Web development prior to this point. 我们有意的避开了Web开发中极其重要的方面。 翻译
6#翻译 So far, we've thought of the traffic visiting our sites as some faceless, anonymous mass hurtling itself against our carefully designed pages. 到目前为止,我们都在假定,网站流量是大量的匿名用户带来的。 翻译
8#翻译 This isn't true, of course. 这当然不对。 翻译
9#翻译 The browsers hitting our sites have real humans behind them (most of the time, at least). 浏览器的背后都是活生生的人(至少某些时候是)。 翻译
10#翻译 That's a big thing to ignore: 这忽略了重要的一点: 翻译
11#翻译 the Internet is at its best when it serves to connect <emphasis>people</emphasis> , not machines. 互联网服务于人而不是机器。 翻译
12#翻译 If we're going to develop truly compelling sites, eventually we're going to have to deal with the bodies behind the browsers. 要开发一个真正令人心动的网站,我们必须面对浏览器后面活生生的人。 翻译
14#翻译 Unfortunately, it's not all that easy. 很不幸,这并不容易。 翻译
15#翻译 HTTP is designed to be <emphasis>stateless</emphasis> that is, each and every request happens in a vacuum. HTTP被设计为&quot;无状态&quot;,每次请求都处于相同的空间中。 翻译
16#翻译 There's no persistence between one request and the next, and we can't count on any aspects of a request (IP address, user agent, etc.) to consistently indicate successive requests from the same person. 在一次请求和下一次请求之间没有任何状态保持,我们无法根据请求的任何方面(IP地址,用户代理等)来识别来自同一人的连续请求。 翻译
18#翻译 In this chapter you'll learn how to handle this lack of state. 在本章中你将学会如何搞定状态的问题。 翻译
19#翻译 We'll start at the lowest level (<emphasis>cookies</emphasis> ), and work up to the high-level tools for handling sessions, users and registration. 好了,我们会从较低的层次(<emphasis>cookies</emphasis>)开始,然后过渡到用高层的工具来搞定会话,用户和注册的问题。 翻译
21#翻译 Cookies Cookies 翻译
23#翻译 Browser developers long ago recognized that HTTP's statelessness poses a huge problem for Web developers, and thus <emphasis>cookies</emphasis> were born. 浏览器的开发者在很早的时候就已经意识到, HTTP协议的无状态性会对Web开发者带来很大的问题,于是(<emphasis>cookies</emphasis>)应运而生。 翻译
24#翻译 A cookie is a small piece of information that browsers store on behalf of Web servers. cookies 是浏览器为 Web 服务器存储的一小段信息。 翻译
25#翻译 Every time a browser requests a page from a certain server, it gives back the cookie that it initially received. 每次浏览器从某个服务器请求页面时,它向服务器回送之前收到的cookies 翻译
27#翻译 Let's take a look how this might work. 来看看它是怎么工作的。 翻译
28#翻译 When you open your browser and type in <literal>google.com</literal> , your browser sends an HTTP request to Google that starts something like this: 当你打开浏览器并访问 <literal>google.com</literal> ,你的浏览器会给Google发送一个HTTP请求,起始部分就象这样: 翻译
31#翻译 When Google replies, the HTTP response looks something like the following: 当 Google响应时,HTTP的响应是这样的: 翻译
34#翻译 Notice the <literal>Set-Cookie</literal> header. 注意 <literal>Set-Cookie</literal> 的头部。 翻译
35#翻译 Your browser will store that cookie value (<literal>PREF=ID=5b14f22bdaf1e81c:TM=1167000671:LM=1167000671</literal> ) and serve it back to Google every time you access the site. 你的浏览器会存储cookie值( <literal>PREF=ID=5b14f22bdaf1e81c:TM=1167000671:LM=1167000671</literal> ) ,而且每次访问google 站点都会回送这个cookie值。 翻译
36#翻译 So the next time you access Google, your browser is going to send a request like this: 因此当你下次访问Google时,你的浏览器会发送像这样的请求: 翻译
39#翻译 Google then can use that <literal>Cookie</literal> value to know that you're the same person who accessed the site earlier. 于是 <literal>Cookies</literal> 的值会告诉Google,你就是早些时候访问过Google网站的人。 翻译
40#翻译 This value might, for example, be a key into a database that stores user information. 这个值可能是数据库中存储用户信息的key,可以用它在页面上显示你的用户名。 翻译
41#翻译 Google could (and does) use it to display your account's username on the page. Google会(以及目前)使用它在网页上显示你账号的用户名。 翻译
43#翻译 Getting and Setting Cookies 存取Cookies 翻译
45#翻译 When dealing with persistence in Django, most of the time you'll want to use the higher-level session and/or user frameworks discussed a little later in this chapter. 在Django中处理持久化,大部分时候你会更愿意用高层些的session 和/或 后面要讨论的user 框架。 翻译
46#翻译 However, first look at how to read and write cookies at a low level. 但在此之前,我们需要停下来在底层看看如何读写cookies。 翻译
47#翻译 This should help you understand how the rest of the tools discussed in the chapter actually work, and it will come in handy if you ever need to play with cookies directly. 这会帮助你理解本章节后面要讨论的工具是如何工作的,而且如果你需要自己操作cookies,这也会有所帮助。 翻译
49#翻译 Reading cookies that are already set is simple. 读取已经设置好的cookies极其简单。 翻译
50#翻译 Every <literal>HttpRequest</literal> object has a <literal>COOKIES</literal> object that acts like a dictionary; you can use it to read any cookies that the browser has sent to the view: 每一个<literal> HttpRequest</literal> 对象都有一个<literal> COOKIES</literal> 对象,该对象的行为类似一个字典,你可以使用它读取任何浏览器发送给视图(view)的cookies。 翻译
53#翻译 Writing cookies is slightly more complicated. 写cookies稍微复杂点。 翻译
54#翻译 You need to use the <literal>set_cookie()</literal> method on an <literal>HttpResponse</literal> object. 你需要使用 <literal>HttpResponse</literal>对象的 <literal>set_cookie()</literal>方法。 翻译
55#翻译 Here's an example that sets the <literal>favorite_color</literal> cookie based on a <literal>GET</literal> parameter: 这儿有个基于 <literal>GET</literal> 参数来设置 <literal>favorite_color</literal> cookie的例子: 翻译
58#翻译 You can also pass a number of optional arguments to <literal>response.set_cookie()</literal> that control aspects of the cookie, as shown in Table 14-1. 你可以给 <literal>response.set_cookie()</literal> 传递一些可选的参数来控制cookie的行为,详见表14-1。 翻译
60#翻译 <table> 翻译 翻译
61#翻译 Table 14-1: 表 14-1: 翻译
62#翻译 Cookie options Cookie 选项 翻译
63#翻译 <tgroup cols="3"><colspec colwidth="11"/><colspec colwidth="9"/><colspec colwidth="60"/><thead><row><entry> 翻译 翻译
64#翻译 Parameter 参数 翻译
66#翻译 Default 缺省值 翻译
68#翻译 Description 描述 翻译
69#翻译 </entry></row></thead><tbody><row><entry> 翻译 翻译
70#翻译 <literal>max_age</literal> <literal>max_age</literal> 翻译
71#翻译 </entry><entry> 翻译 翻译
72#翻译 <literal>None</literal> <literal>None</literal> 翻译
73#翻译 </entry><entry> 翻译 翻译
74#翻译 Age (in seconds) that the cookie should last. cookie需要延续的时间(以秒为单位) 翻译
75#翻译 If this parameter is <literal>None</literal> , the cookie will last only until the browser is closed. 如果参数是<literal> None</literal> ,这个cookie会延续到浏览器关闭为止。 翻译
76#翻译 </entry></row><row><entry> 翻译 翻译
77#翻译 <literal>expires</literal> <literal>expires</literal> 翻译
78#翻译 </entry><entry> 翻译 翻译
79#翻译 <literal>None</literal> <literal>None</literal> 翻译
80#翻译 </entry><entry> 翻译 翻译
81#翻译 The actual date/time when the cookie should expire. cookie失效的实际日期/时间。 翻译
82#翻译 It needs to be in the format <literal>&quot;Wdy, DD-Mth-YY HH:MM:SS GMT&quot;</literal> . If given, this parameter overrides the <literal>max_age</literal> parameter. 它的格式必须是:<literal> "Wdy, DD-Mth-YY HH:MM:SS GMT"</literal> 。如果给出了这个参数,它会覆盖<literal> max_age</literal> 参数。 翻译
83#翻译 </entry></row><row><entry> 翻译 翻译
84#翻译 <literal>path</literal> <literal>path</literal> 翻译
85#翻译 </entry><entry> 翻译 翻译
86#翻译 <literal>&quot;/&quot;</literal> <literal>"/"</literal> 翻译
87#翻译 </entry><entry> 翻译 翻译
88#翻译 The path prefix that this cookie is valid for. cookie生效的路径前缀。 翻译
89#翻译 Browsers will only pass the cookie back to pages below this path prefix, so you can use this to prevent cookies from being sent to other sections of your site. 浏览器只会把cookie回传给带有该路径的页 面,这样你可以避免将cookie传给站点中的其他的应用。 翻译
90#翻译 This is especially useful when you don't control the top level of your sites domain. 当你不是控制你的站点的顶层时,这样做是特别有用的。 翻译
91#翻译 </entry></row><row><entry> 翻译 翻译
92#翻译 <literal>domain</literal> <literal>domain</literal> 翻译
93#翻译 </entry><entry> 翻译 翻译
94#翻译 <literal>None</literal> <literal>None</literal> 翻译
95#翻译 </entry><entry> 翻译 翻译
96#翻译 The domain that this cookie is valid for. 这个cookie有效的站点。 翻译
97#翻译 You can use this parameter to set a cross-domain cookie. 你可以使用这个参数设置一个跨站点(cross-domain)的cookie。 翻译
98#翻译 For example, <literal>domain=&quot;.example.com&quot;</literal> will set a cookie that is readable by the domains <literal>www.example.com</literal> , <literal>www2.example.com</literal> , and <literal>an.other.sub.domain.example.com</literal> . 比如,<literal> domain=".example.com"</literal> 可以设置一个在<literal> www.example.com</literal> 、<literal> www2.example.com</literal> 以及<literal> an.other.sub.domain.example.com</literal> 站点下都可读到的cookie。 翻译
99#翻译 If this parameter is set to <literal>None</literal> , a cookie will only be readable by the domain that set it. 如果这个参数被设成<literal> None</literal> ,cookie将只能在设置它的站点下可以读到。 翻译
100#翻译 </entry></row><row><entry> 翻译 翻译
101#翻译 <literal>secure</literal> <literal>False</literal> 翻译
102#翻译 </entry><entry> 翻译 翻译
103#翻译 <literal>False</literal> <literal>False</literal> 翻译
104#翻译 </entry><entry> 翻译 翻译
105#翻译 If set to <literal>True</literal> , this parameter instructs the browser to only return this cookie to pages accessed over HTTPS. 如果设置为 <literal>True</literal> ,浏览器将通过HTTPS来回传cookie。 翻译
106#翻译 </entry></row></tbody></tgroup></table><cnid>27 翻译 翻译
107#翻译 The Mixed Blessing of Cookies 好坏参半的Cookies 翻译
109#翻译 You might notice a number of potential problems with the way cookies work. 也许你已经注意到了,cookies的工作方式可能导致的问题。 翻译
110#翻译 Let's look at some of the more important ones: 让我们看一下其中一些比较重要的问题: 翻译
112#翻译 Storage of cookies is voluntary; a client does not have to accept or store cookies. cookie的存储是自愿的,一个客户端不一定要去接受或存储cookie。 翻译
113#翻译 In fact, all browsers enable users to control the policy for accepting cookies. 事实上,所有的浏览器都让用户自己控制 是否接受cookies。 翻译
114#翻译 If you want to see just how vital cookies are to the Web, try turning on your browser's prompt to accept every cookie option. 如果你想知道cookies对于Web应用有多重要,你可以试着打开这个浏览器的 选项: 翻译
116#翻译 Despite their nearly universal use, cookies are still the definition of unreliability. 尽管cookies广为使用,但仍被认为是不可靠的的。 翻译
117#翻译 This means that developers should check that a user actually accepts cookies before relying on them. 这意味着,开发者使用cookies之前必须 检查用户是否可以接收cookie。 翻译
119#翻译 Cookies (especially those not sent over HTTPS) are not secure. Cookie(特别是那些没通过HTTPS传输的)是非常不安全的。 翻译
120#翻译 Because HTTP data is sent in cleartext, cookies are extremely vulnerable to snooping attacks. 因为HTTP数据是以明文发送的,所以 特别容易受到嗅探攻击。 翻译
121#翻译 That is, an attacker snooping on the wire can intercept a cookie and read it. 也就是说,嗅探攻击者可以在网络中拦截并读取cookies,因此你要 绝对避免在cookies中存储敏感信息。 翻译
122#翻译 This means you should never store sensitive information in a cookie. 这就意味着您不应该使用cookie来在存储任何敏感信息。 翻译
124#翻译 There's an even more insidious attack, known as a <emphasis>man-in-the-middle</emphasis> attack, wherein an attacker intercepts a cookie and uses it to pose as another user. 还有一种被称为&quot;中间人&quot;的攻击更阴险,攻击者拦截一个cookie并将其用于另一个用户。 翻译
125#翻译 Chapter 20 discusses attacks of this nature in depth, as well as ways to prevent it. 第19章将深入讨论这种攻击的本质以及如何避免。 翻译
127#翻译 Cookies aren't even secure from their intended recipients. 即使从预想中的接收者返回的cookie也是不安全的。 翻译
128#翻译 Most browsers provide easy ways to edit the content of individual cookies, and resourceful users can always use tools like mechanize (<reference name="http://wwwsearch.sourceforge.net/mechanize/" refuri="http://wwwsearch.sourceforge.net/mechanize/">http://wwwsearch.sourceforge.net/mechanize/</reference>) to construct HTTP requests by hand. 在大多数浏览器中您可以非常容易地修改cookies中的信息。有经验的用户甚至可以通过像mechanize(<reference name="http://wwwsearch.sourceforge.net/mechanize/" refuri="http://wwwsearch.sourceforge.net/mechanize/">http://wwwsearch.sourceforge.net/mechanize/</reference>) 这样的工具手工构造一个HTTP请求。 翻译
130#翻译 So you can't store data in cookies that might be sensitive to tampering. 因此不能在cookies中存储可能会被篡改的敏感数据。 翻译
131#翻译 The canonical mistake in this scenario is storing something like <literal>IsLoggedIn=1</literal> in a cookie when a user logs in. 在cookies中存储 <literal>IsLoggedIn=1</literal> ,以标识用户已经登录。 翻译
132#翻译 You'd be amazed at the number of sites that make mistakes of this nature; it takes only a second to fool these sites' security systems. 犯这类错误的站点数量多的令人难以置信; 绕过这些网站的安全系统也是易如反掌。 翻译
134#翻译 Django's Session Framework Django的 Session 框架 翻译
136#翻译 With all of these limitations and potential security holes, it's obvious that cookies and persistent sessions are examples of those pain points in Web development. 由于存在的限制与安全漏洞,cookies和持续性会话已经成为Web开发中令人头疼的典范。 翻译
137#翻译 Of course, Django's goal is to be an effective painkiller, so it comes with a session framework designed to smooth over these difficulties for you. 好消息是,Django的目标正是高效的“头疼杀手”,它自带的session框架会帮你搞定这些问题。 翻译
139#翻译 This session framework lets you store and retrieve arbitrary data on a per-site visitor basis. 你可以用session 框架来存取每个访问者任意数据, 翻译
140#翻译 It stores data on the server side and abstracts the sending and receiving of cookies. 这些数据在服务器端存储,并对cookie的收发进行了抽象。 翻译
141#翻译 Cookies use only a hashed session ID not the data itself thus protecting you from most of the common cookie problems. Cookies只存储数据的哈希会话ID,而不是数据本身,从而避免了大部分的常见cookie问题。 翻译
143#翻译 Let's look at how to enable sessions and use them in views. 下面我们来看看如何打开session功能,并在视图中使用它。 翻译
145#翻译 Enabling Sessions 打开 Sessions功能 翻译
147#翻译 Sessions are implemented via a piece of middleware (see Chapter 17) and a Django model. Sessions 功能是通过一个中间件(参见第17章)和一个模型(model)来实现的。 翻译
148#翻译 To enable sessions, you'll need to follow these steps: 要打开sessions功能,需要以下几步操作: 翻译
150#翻译 Edit your <literal>MIDDLEWARE_CLASSES</literal> setting and make sure <literal>MIDDLEWARE_CLASSES</literal> contains <literal>'django.contrib.sessions.middleware.SessionMiddleware'</literal> . 编辑 <literal>MIDDLEWARE_CLASSES</literal> 配置,确保 <literal>MIDDLEWARE_CLASSES</literal> 中包含 <literal>'django.contrib.sessions.middleware.SessionMiddleware'</literal>。 翻译
152#翻译 Make sure <literal>'django.contrib.sessions'</literal> is in your <literal>INSTALLED_APPS</literal> setting (and run <literal>manage.py syncdb</literal> if you have to add it). 确认 <literal>INSTALLED_APPS</literal> 中有 <literal>'django.contrib.sessions'</literal> (如果你是刚打开这个应用,别忘了运行 <literal>manage.py syncdb</literal> ) 翻译
154#翻译 The default skeleton settings created by <literal>startproject</literal> have both of these bits already installed, so unless you've removed them, you probably don't have to change anything to get sessions to work. 如果项目是用 <literal>startproject</literal> 来创建的,配置文件中都已经安装了这些东西,除非你自己删除,正常情况下,你无需任何设置就可以使用session功能。 翻译
156#翻译 If you don't want to use sessions, you might want to remove the <literal>SessionMiddleware</literal> line from <literal>MIDDLEWARE_CLASSES</literal> and <literal>'django.contrib.sessions'</literal> from your <literal>INSTALLED_APPS</literal> . It will save you only a small amount of overhead, but every little bit counts. 如果不需要session功能,你可以删除 <literal>MIDDLEWARE_CLASSES</literal> 设置中的 <literal>SessionMiddleware</literal> 和 <literal>INSTALLED_APPS</literal> 设置中的 <literal>'django.contrib.sessions'</literal> 。虽然这只会节省很少的开销,但积少成多啊。 翻译
158#翻译 Using Sessions in Views 在视图中使用Session 翻译
160#翻译 When <literal>SessionMiddleware</literal> is activated, each <literal>HttpRequest</literal> object the first argument to any Django view function will have a <literal>session</literal> attribute, which is a dictionary-like object. <literal>SessionMiddleware</literal> 激活后,每个传给视图(view)函数的第一个参数``HttpRequest`` 对象都有一个 <literal>session</literal> 属性,这是一个字典型的对象。 翻译
161#翻译 You can read it and write to it in the same way you'd use a normal dictionary. 你可以象用普通字典一样来用它。 翻译
162#翻译 For example, in a view you could do stuff like this: 例如,在视图(view)中你可以这样用: 翻译
165#翻译 You can also use other dictionary methods like <literal>keys()</literal> and <literal>items()</literal> on <literal>request.session</literal> . 其他的映射方法,如 <literal>keys()</literal> 和 <literal>items()</literal> 对 <literal>request.session</literal> 同样有效: 翻译
167#翻译 There are a couple of simple rules for using Django's sessions effectively: 下面是一些有效使用Django sessions的简单规则: 翻译
169#翻译 Use normal Python strings as dictionary keys on <literal>request.session</literal> (as opposed to integers, objects, etc.). 用正常的字符串作为key来访问字典 <literal>request.session</literal> , 而不是整数、对象或其它什么的。 翻译
171#翻译 Session dictionary keys that begin with an underscore are reserved for internal use by Django. Session字典中以下划线开头的key值是Django内部保留key值。 翻译
172#翻译 In practice, the framework uses only a small number of underscore-prefixed session variables, but unless you know what they all are (and you are willing to keep up with any changes in Django itself), staying away from underscore prefixes will keep Django from interfering with your application. 框架只会用很少的几个下划线 开头的session变量,除非你知道他们的具体含义,而且愿意跟上Django的变化,否则,最好 不要用这些下划线开头的变量,它们会让Django搅乱你的应用。 翻译
174#翻译 For example, don't use a session key called <literal>_fav_color</literal> , like this: 比如,不要象这样使用<literal> _fav_color</literal> 会话密钥(session key): 翻译
177#翻译 Don't replace <literal>request.session</literal> with a new object, and don't access or set its attributes. 不要用一个新对象来替换掉 <literal>request.session</literal> ,也不要存取其属性。 翻译
178#翻译 Use it like a Python dictionary. 可以像Python中的字典那样使用。 翻译
179#翻译 Examples: 例如: 翻译
182#翻译 Let's take a look at a few quick examples. 我们来看个简单的例子。 翻译
183#翻译 This simplistic view sets a <literal>has_commented</literal> variable to <literal>True</literal> after a user posts a comment. 这是个简单到不能再简单的例子:在用户发了一次评论后将<literal>has_commented</literal>设置为<literal>True</literal>。 翻译
184#翻译 It's a simple (if not particularly secure) way of preventing a user from posting more than one comment: 这是个简单(但不很安全)的、防止用户多次评论的方法。 翻译
187#翻译 This simplistic view logs in a member of the site: 下面是一个很简单的站点登录视图(view): 翻译
190#翻译 And this one logs out a member who has been logged in via <literal>login()</literal> above: 下面的例子将登出一个在上面已通过<literal> login()</literal> 登录的用户: 翻译
193#翻译 Note 注意 翻译
195#翻译 In practice, this is a lousy way of logging users in. 在实践中,这是很烂的用户登录方式,稍后讨论的认证(authentication )框架会帮你以更健壮和有利的方式来处理这些问题。 翻译
196#翻译 The authentication framework discussed shortly handles this task for you in a much more robust and useful manner. 这些非常简单的例子只是想让你知道这一切是如何工作的。 翻译
197#翻译 These examples are deliberately simplistic so that you can easily see what's going on. 这些实例尽量简单,这样你可以更容易看到发生了什么 翻译
199#翻译 Setting Test Cookies 设置测试Cookies 翻译
201#翻译 As mentioned above, you can't rely on every browser accepting cookies. 就像前面提到的,你不能指望所有的浏览器都可以接受cookie。 翻译
202#翻译 So, as a convenience, Django provides an easy way to test whether a user's browser accepts cookies. 因此,为了使用方便,Django提供了一个简单的方法来测试用户的浏览器是否接受cookie。 翻译
203#翻译 Just call <literal>request.session.set_test_cookie()</literal> in a view, and check <literal>request.session.test_cookie_worked()</literal> in a subsequent view not in the same view call. 你只需在视图(view)中调用 <literal>request.session.set_test_cookie()</literal> ,并在后续的视图(view)、而不是当前的视图(view)中检查 <literal>request.session.test_cookie_worked()</literal> 。 翻译
205#翻译 This awkward split between <literal>set_test_cookie()</literal> and <literal>test_cookie_worked()</literal> is necessary due to the way cookies work. 虽然把 <literal>set_test_cookie()</literal> 和 <literal>test_cookie_worked()</literal> 分开的做法看起来有些笨拙,但由于cookie的工作方式,这无可避免。 翻译
206#翻译 When you set a cookie, you can't actually tell whether a browser accepted it until the browser's next request. 当设置一个cookie时候,只能等浏览器下次访问的时候,你才能知道浏览器是否接受cookie。 翻译
208#翻译 It's good practice to use <literal>delete_test_cookie()</literal> to clean up after yourself. 检查cookie是否可以正常工作后,你得自己用 <literal>delete_test_cookie()</literal> 来清除它,这是个好习惯。 翻译
209#翻译 Do this after you've verified that the test cookie worked. 在你证实了测试cookie已工作了之后这样操作。 翻译
211#翻译 Here's a typical usage example: 这是个典型例子: 翻译
214#翻译 Note 注意 翻译
216#翻译 Again, the built-in authentication functions handle this check for you. 再次强调,内置的认证函数会帮你做检查的。 翻译
218#翻译 Using Sessions Outside of Views 在视图(View)外使用Session 翻译
220#翻译 Internally, each session is just a normal Django model defined in <literal>django.contrib.sessions.models</literal> . Each session is identified by a more-or-less random 32-character hash stored in a cookie. 从内部来看,每个session都只是一个普通的Django model(在 <literal>django.contrib.sessions.models</literal> 中定义)。每个session都由一个随机的32字节哈希串来标识,并存储于cookie中。 翻译
221#翻译 Because it's a normal model, you can access sessions using the normal Django database API: 因为它是一个标准的模型,所以你可以使用Django数据库API来存取session。 翻译
224#翻译 You'll need to call <literal>get_decoded()</literal> to get the actual session data. 你需要使用<literal>get_decoded()</literal> 来读取实际的session数据。 翻译
225#翻译 This is necessary because the dictionary is stored in an encoded format: 这是必需的,因为字典存储为一种特定的编码格式。 翻译
228#翻译 When Sessions Are Saved 何时保存Session 翻译
230#翻译 By default, Django only saves to the database if the session has been modified that is, if any of its dictionary values have been assigned or deleted: 缺省的情况下,Django只会在session发生变化的时候才会存入数据库,比如说,字典赋值或删除。 翻译
233#翻译 To change this default behavior, set <literal>SESSION_SAVE_EVERY_REQUEST</literal> to <literal>True</literal> . If <literal>SESSION_SAVE_EVERY_REQUEST</literal> is <literal>True</literal> , Django will save the session to the database on every single request, even if it wasn't changed. 你可以设置 <literal>SESSION_SAVE_EVERY_REQUEST</literal> 为 <literal>True</literal> 来改变这一缺省行为。如果置为True的话,Django会在每次收到请求的时候保存session,即使没发生变化。 翻译
235#翻译 Note that the session cookie is sent only when a session has been created or modified. 注意,会话cookie只会在创建和修改的时候才会送出。 翻译
236#翻译 If <literal>SESSION_SAVE_EVERY_REQUEST</literal> is <literal>True</literal> , the session cookie will be sent on every request. 但如果 <literal>SESSION_SAVE_EVERY_REQUEST</literal> 设置为 <literal>True</literal> ,会话cookie在每次请求的时候都会送出。 翻译
237#翻译 Similarly, the <literal>expires</literal> part of a session cookie is updated each time the session cookie is sent. 同时,每次会话cookie送出的时候,其 <literal>expires</literal> 参数都会更新。 翻译
239#翻译 Browser-Length Sessions vs. 浏览器关闭即失效会话 vs 翻译
240#翻译 Persistent Sessions 持久会话 翻译
242#翻译 You might have noticed that the cookie Google sent us at the beginning of this chapter contained <literal>expires=Sun, 17-Jan-2038 19:14:07 GMT;</literal> . Cookies can optionally contain an expiration date that advises the browser on when to remove the cookie. 你可能注意到了,Google给我们发送的cookie中有 <literal>expires=Sun, 17-Jan-2038 19:14:07 GMT;</literal> cookie可以有过期时间,这样浏览器就知道什么时候可以删除cookie了。 翻译
243#翻译 If a cookie doesn't contain an expiration value, the browser will expire it when the user closes his or her browser window. 如果cookie没有设置过期时间,当用户关闭浏览器的时候,cookie就自动过期了。 翻译
244#翻译 You can control the session framework's behavior in this regard with the <literal>SESSION_EXPIRE_AT_BROWSER_CLOSE</literal> setting. 你可以改变 <literal>SESSION_EXPIRE_AT_BROWSER_CLOSE</literal> 的设置来控制session框架的这一行为。 翻译
246#翻译 By default, <literal>SESSION_EXPIRE_AT_BROWSER_CLOSE</literal> is set to <literal>False</literal> , which means session cookies will be stored in users' browsers for <literal>SESSION_COOKIE_AGE</literal> seconds (which defaults to two weeks, or 1,209,600 seconds). 缺省情况下, <literal>SESSION_EXPIRE_AT_BROWSER_CLOSE</literal> 设置为 <literal>False</literal> ,这样,会话cookie可以在用户浏览器中保持有效达 <literal>SESSION_COOKIE_AGE</literal> 秒(缺省设置是两周,即1,209,600 秒)。 翻译
247#翻译 Use this if you don't want people to have to log in every time they open a browser. 如果你不想用户每次打开浏览器都必须重新登陆的话,用这个参数来帮你。 翻译
249#翻译 If <literal>SESSION_EXPIRE_AT_BROWSER_CLOSE</literal> is set to <literal>True</literal> , Django will use browser-length cookies. 如果 <literal>SESSION_EXPIRE_AT_BROWSER_CLOSE</literal> 设置为 <literal>True</literal> ,当浏览器关闭时,Django会使cookie失效。 翻译
251#翻译 Other Session Settings 其他的Session设置 翻译
253#翻译 Besides the settings already mentioned, a few other settings influence how Django's session framework uses cookies, as shown in Table 14-2. 除了上面提到的设置,还有一些其他的设置可以影响Django session框架如何使用cookie,详见表 14-2. 翻译
256#翻译 Table 14-2. 表 14-2. 翻译
257#翻译 Settings that influence cookiebehavior 影响cookie行为的设置 翻译
258#翻译 <tgroup cols="3"><colspec colwidth="25"/><colspec colwidth="40"/><colspec colwidth="15"/><thead><row><entry> 翻译 翻译
259#翻译 Setting 设置 翻译
260#翻译 </entry><entry> 翻译 翻译
261#翻译 Description 描述 翻译
262#翻译 </entry><entry> 翻译 翻译
263#翻译 Default 缺省 翻译
264#翻译 </entry></row></thead><tbody><row><entry> 翻译 翻译
265#翻译 <literal>SESSION_COOKIE_DOMAIN</literal> <literal>SESSION_COOKIE_DOMAIN</literal> 翻译
266#翻译 </entry><entry> 翻译 翻译
267#翻译 The domain to use for session cookies. 使用会话cookie(session cookies)的站点。 翻译
268#翻译 Set this to a string such as <literal>&quot;.example.com&quot;</literal> for cross-domain cookies, or use <literal>None</literal> for a standard cookie. 将它设成一个字符串,就好象<literal> ".example.com"</literal> 以用于跨站点(cross-domain)的cookie,或<literal> None</literal> 以用于单个站点。 翻译
269#翻译 </entry><entry> 翻译 翻译
270#翻译 <literal>None</literal> <literal>None</literal> 翻译
271#翻译 </entry></row><row><entry> 翻译 翻译
272#翻译 <literal>SESSION_COOKIE_NAME</literal> <literal>SESSION_COOKIE_NAME</literal> 翻译
273#翻译 </entry><entry> 翻译 翻译
274#翻译 The name of the cookie to use for sessions. 会话中使用的cookie的名字。 翻译
275#翻译 This can be any string. 它可以是任意的字符串。 翻译
276#翻译 </entry><entry> 翻译 翻译
277#翻译 <literal>&quot;sessionid&quot;</literal> <literal>"sessionid"</literal> 翻译
278#翻译 </entry></row><row><entry> 翻译 翻译
279#翻译 <literal>SESSION_COOKIE_SECURE</literal> <literal>SESSION_COOKIE_SECURE</literal> 翻译
280#翻译 </entry><entry> 翻译 翻译
281#翻译 Whether to use a secure cookie for the session cookie. 是否在session中使用安全cookie。 翻译
282#翻译 If this is set to <literal>True</literal> , the cookie will be marked as secure, which means that browsers will ensure that the cookie is only sent via HTTPS. 如果设置 <literal>True</literal> , cookie就会标记为安全, 这意味着cookie只会通过HTTPS来传输。 翻译
283#翻译 </entry><entry> 翻译 翻译
284#翻译 <literal>False</literal> <literal>False</literal> 翻译
285#翻译 </entry></row></tbody></tgroup></table><cnid>99 翻译 翻译
286#翻译 Technical Details 技术细节 翻译
288#翻译 For the curious, here are a few technical notes about the inner workings of the session framework: 如果你还是好奇的话,下面是一些关于session框架内部工作方式的技术细节: 翻译
290#翻译 The session dictionary accepts any Python object capable of being pickled. session 字典接受任何支持序列化的Python对象。 翻译
291#翻译 See the documentation for Python's built-in <literal>pickle</literal> module for information about how this works. 参考Python内建模块<literal>pickle</literal>的文档以获取更多信息。 翻译
293#翻译 Session data is stored in a database table named <literal>django_session</literal> . Session 数据存在数据库表 <literal>django_session</literal> 中 翻译
295#翻译 Session data is fetched upon demand. Session 数据在需要的时候才会读取。 翻译
296#翻译 If you never access <literal>request.session</literal> , Django won't hit that database table. 如果你从不使用 <literal>request.session</literal> , Django不会动相关数据库表的一根毛。 翻译
298#翻译 Django only sends a cookie if it needs to. Django 只在需要的时候才送出cookie。 翻译
299#翻译 If you don't set any session data, it wont send a session cookie (unless <literal>SESSION_SAVE_EVERY_REQUEST</literal> is set to <literal>True</literal> ). 如果你压根儿就没有设置任何会话数据,它不会 送出会话cookie(除非 <literal>SESSION_SAVE_EVERY_REQUEST</literal> 设置为 <literal>True</literal> )。 翻译
301#翻译 The Django sessions framework is entirely, and solely, cookie based. Django session 框架完全而且只能基于cookie。 翻译
302#翻译 It does not fall back to putting session IDs in URLs as a last resort, as some other tools (PHP, JSP) do. 它不会后退到把会话ID编码在URL中(像某些工具(PHP,JSP)那样)。 翻译
304#翻译 This is an intentional design decision. 这是一个有意而为之的设计。 翻译
305#翻译 Putting sessions in URLs don't just make URLs ugly, but also make your site vulnerable to a certain form of session ID theft via the <literal>Referer</literal> header. 把session放在URL中不只是难看,更重要的是这让你的站点 很容易受到攻击——通过 <literal>Referer</literal> header进行session ID&quot;窃听&quot;而实施的攻击。 翻译
307#翻译 If you're still curious, the source is pretty straightforward; look in <literal>django.contrib.sessions</literal> for more details. 如果你还是好奇,阅读源代码是最直接办法,详见 <literal>django.contrib.sessions</literal> 。 翻译
309#翻译 Users and Authentication 用户与Authentication 翻译
311#翻译 Sessions give us a way of persisting data through multiple browser requests; the second part of the equation is using those sessions for user login. 通过session,我们可以在多次浏览器请求中保持数据, 接下来的部分就是用session来处理用户登录了。 翻译
312#翻译 Of course, we can't just trust that users are who they say they are, so we need to authenticate them along the way. 当然,不能仅凭用户的一面之词,我们就相信,所以我们需要认证。 翻译
314#翻译 Naturally, Django provides tools to handle this common task (and many others). 当然了,Django 也提供了工具来处理这样的常见任务(就像其他常见任务一样)。 翻译
315#翻译 Django's user authentication system handles user accounts, groups, permissions, and cookie-based user sessions. Django 用户认证系统处理用户帐号,组,权限以及基于cookie的用户会话。 翻译
316#翻译 This system is often referred to as an <emphasis>auth/auth</emphasis> (authentication and authorization) system. 这个系统一般被称为 <emphasis>auth/auth</emphasis> (认证与授权)系统。 翻译
317#翻译 That name recognizes that dealing with users is often a two-step process. 这个系统的名称同时也表明了用户常见的两步处理。 翻译
318#翻译 We need to 我们需要 翻译
320#翻译 Verify (<emphasis>authenticate</emphasis> ) that a user is who he or she claims to be (usually by checking a username and password against a database of users) 验证 (<emphasis>认证</emphasis>) 用户是否是他所宣称的用户(一般通过查询数据库验证其用户名和密码) 翻译
322#翻译 Verify that the user is <emphasis>authorized</emphasis> to perform some given operation (usually by checking against a table of permissions) 验证用户是否拥有执行某种操作的 <emphasis>授权</emphasis> (通常会通过检查一个权限表来确认) 翻译
324#翻译 Following these needs, Django's auth/auth system consists of a number of parts: 根据这些需求,Django 认证/授权 系统会包含以下的部分: 翻译
326#翻译 <emphasis>Users</emphasis> : People registered with your site <emphasis>用户</emphasis> : 在网站注册的人 翻译
328#翻译 <emphasis>Permissions</emphasis> : Binary (yes/no) flags designating whether a user may perform a certain task <emphasis>权限</emphasis> : 用于标识用户是否可以执行某种操作的二进制(yes/no)标志 翻译
330#翻译 <emphasis>Groups</emphasis> : A generic way of applying labels and permissions to more than one user <emphasis>组</emphasis> :一种可以将标记和权限应用于多个用户的常用方法 翻译
332#翻译 <emphasis>Messages</emphasis> : A simple way to queue and display system messages to users <emphasis>Messages</emphasis> : 向用户显示队列式的系统消息的常用方法 翻译
334#翻译 If you've used the admin tool (discussed in Chapter 6), you've already seen many of these tools, and if you've edited users or groups in the admin tool, you've actually been editing data in the auth system's database tables. 如果你已经用了admin工具(详见第6章),就会看见这些工具的大部分。如果你在admin工具中编辑过用户或组,那么实际上你已经编辑过授权系统的数据库表了。 翻译
336#翻译 Enabling Authentication Support 打开认证支持 翻译
338#翻译 Like the session tools, authentication support is bundled as a Django application in <literal>django.contrib</literal> that needs to be installed. 像session工具一样,认证支持也是一个Django应用,放在 <literal>django.contrib</literal> 中,所以也需要安装。 翻译
339#翻译 Also like the session tools, it's also installed by default, but if you've removed it, you'll need to follow these steps to install it: 与session系统相似,它也是缺省安装的,但如果它已经被删除了,通过以下步骤也能重新安装上: 翻译
341#翻译 Make sure the session framework is installed as described earlier in this chapter. 根据本章早前的部分确认已经安装了session 框架。 翻译
342#翻译 Keeping track of users obviously requires cookies, and thus builds on the session framework. 需要确认用户使用cookie,这样sesson 框架才能正常使用。 翻译
344#翻译 Put <literal>'django.contrib.auth'</literal> in your <literal>INSTALLED_APPS</literal> setting and run <literal>manage.py syncdb</literal> to install the appropriate database tables. 将 <literal>'django.contrib.auth'</literal> 放在你的 <literal>INSTALLED_APPS</literal> 设置中,然后运行 <literal>manage.py syncdb</literal>以创建对应的数据库表。 翻译
346#翻译 Make sure that <literal>'django.contrib.auth.middleware.AuthenticationMiddleware'</literal> is in your <literal>MIDDLEWARE_CLASSES</literal> setting <emphasis>after</emphasis> 确认 <literal>SessionMiddleware</literal> 后面的 <literal>MIDDLEWARE_CLASSES</literal> 设置中包含 <literal>'django.contrib.auth.middleware.AuthenticationMiddleware'</literal> 翻译
347#翻译 <literal>SessionMiddleware</literal> . SessionMiddleware。 翻译
349#翻译 With that installation out of the way, we're ready to deal with users in view functions. 这样安装后,我们就可以在视图(view)的函数中处理user了。 翻译
350#翻译 The main interface you'll use to access users within a view is <literal>request.user</literal> ; this is an object that represents the currently logged-in user. 在视图中存取users,主要用 <literal>request.user</literal> ;这个对象表示当前已登录的用户。 翻译
351#翻译 If the user isn't logged in, this will instead be an <literal>AnonymousUser</literal> object (see below for more details). 如果用户还没登录,这就是一个<literal>AnonymousUser</literal>对象(细节见下)。 翻译
353#翻译 You can easily tell if a user is logged in with the <literal>is_authenticated()</literal> method: 你可以很容易地通过 <literal>is_authenticated()</literal> 方法来判断一个用户是否已经登录了: 翻译
356#翻译 Using Users 使用User对象 翻译
358#翻译 Once you have a <literal>User</literal> often from <literal>request.user</literal> , but possibly through one of the other methods discussed shortly you have a number of fields and methods available on that object. <literal>User</literal> 实例一般从 <literal>request.user</literal> ,或是其他下面即将要讨论到的方法取得,它有很多属性和方法。 翻译
359#翻译 <literal>AnonymousUser</literal> objects emulate <emphasis>some</emphasis> of this interface, but not all of it, so you should always check <literal>user.is_authenticated()</literal> before assuming you're dealing with a bona fide user object. <literal>AnonymousUser</literal> 对象模拟了 <emphasis>部分</emphasis> 的接口,但不是全部,在把它当成真正的user对象 使用前,你得检查一下 <literal>user.is_authenticated()</literal> 翻译
360#翻译 Tables 14-3 and 14-4 list the fields and methods, respectively, on <literal>User</literal> objects. 表14-3和14-4分别列出了<literal> User</literal> 对象中的属性(fields)和方法。 翻译
362#翻译 <table> 翻译 翻译
363#翻译 Table 14-3. 表 14-3. 翻译
364#翻译 Fields on <literal>User</literal> Objects <literal>User</literal> 对象属性 翻译
365#翻译 <tgroup cols="2"><colspec colwidth="16"/><colspec colwidth="65"/><thead><row><entry> 翻译 翻译
366#翻译 Field 属性 翻译
367#翻译 </entry><entry> 翻译 翻译
368#翻译 Description 描述 翻译
369#翻译 </entry></row></thead><tbody><row><entry> 翻译 翻译
370#翻译 <literal>username</literal> username 翻译
371#翻译 </entry><entry> 翻译 翻译
372#翻译 Required; 30 characters or fewer. 必需的,不能多于30个字符。 翻译
373#翻译 Alphanumeric characters only (letters, digits, and underscores). 仅用字母数字式字符(字母、数字和下划线)。 翻译
374#翻译 </entry></row><row><entry> 翻译 翻译
375#翻译 <literal>first_name</literal> <literal>first_name</literal> 翻译
376#翻译 </entry><entry> 翻译 翻译
377#翻译 Optional; 30 characters or fewer. 可选; 少于等于30字符。 翻译
378#翻译 </entry></row><row><entry> 翻译 翻译
381#翻译 Optional; 30 characters or fewer. 可选; 少于等于30字符。 翻译
382#翻译 </entry></row><row><entry> 翻译 翻译
385#翻译 Optional. 可选。 翻译
386#翻译 E-mail address. 邮件地址。 翻译
387#翻译 </entry></row><row><entry> 翻译 翻译
388#翻译 <literal>password</literal> <literal>password</literal> 翻译
389#翻译 </entry><entry> 翻译 翻译
390#翻译 Required. 必需的。 翻译
391#翻译 A hash of, and metadata about, the password (Django doesn't store the raw password). 密码的哈希值(Django不储存原始密码)。 翻译
392#翻译 See the Passwords section for more about this value. 翻译 翻译
393#翻译 </entry></row><row><entry> 翻译 翻译
396#翻译 Boolean. 布尔值。 翻译
397#翻译 Designates whether this user can access the admin site. 用户是否拥有网站的管理权限。 翻译
400#翻译 </entry><entry> 翻译 翻译
401#翻译 Boolean. 布尔值. 翻译
402#翻译 Designates whether this account can be used to log in. 设置该账户是否可以登录。 翻译
403#翻译 Set this flag to <literal>False</literal> instead of deleting accounts. 把该标志位置为<literal>False</literal>而不是直接删除账户。 翻译
407#翻译 Boolean. 布尔值 翻译
408#翻译 Designates that this user has all permissions without explicitly assigning them. 标识用户是否拥有所有权限,无需显式地权限分配定义。 翻译
410#翻译 <literal>last_login</literal> <literal>last_login</literal> 翻译
411#翻译 </entry><entry> 翻译 翻译
412#翻译 A datetime of the user's last login. 用户上次登录的时间日期。 翻译
413#翻译 This is set to the current date/time by default. 它被默认设置为当前的日期/时间。 翻译
414#翻译 </entry></row><row><entry> 翻译 翻译
417#翻译 A datetime designating when the account was created. 账号被创建的日期时间 翻译
418#翻译 This is set to the current date/time by default when the account is created. 当账号被创建时,它被默认设置为当前的日期/时间。 翻译
419#翻译 </entry></row></tbody></tgroup></table><cnid>131 翻译 翻译
420#翻译 <table> 翻译 翻译
421#翻译 Table 14-4. 表 14-4. 翻译
422#翻译 Methods on <literal>User</literal> Objects <literal>User</literal> 对象方法 翻译
423#翻译 <tgroup cols="2"><colspec colwidth="31"/><colspec colwidth="50"/><thead><row><entry> 翻译 翻译
424#翻译 Method 方法 翻译
426#翻译 Description 描述 翻译
430#翻译 Always returns <literal>True</literal> for real <literal>User</literal> objects. 对于真实的User对象,总是返回<literal> True</literal> 。 翻译
431#翻译 This is a way to tell if the user has been authenticated. 这是一个分辨用户是否已被鉴证的方法。 翻译
432#翻译 This does not imply any permissions, and it doesn't check if the user is active. 它并不意味着任何权限,也不检查用户是否仍是活动的。 翻译
433#翻译 It only indicates that the user has sucessfully authenticated. 它仅说明此用户已被成功鉴证。 翻译
434#翻译 </entry></row><row><entry> 翻译 翻译
437#翻译 Returns <literal>True</literal> only for <literal>AnonymousUser</literal> objects (and <literal>False</literal> for real <literal>User</literal> objects). 对于<literal> AnonymousUser</literal> 对象返回<literal> True</literal> (对于真实的<literal> User</literal> 对象返回<literal> False</literal> )。 翻译
438#翻译 Generally, you should prefer using <literal>is_authenticated()</literal> to this method. 总的来说,比起这个方法,你应该倾向于使用<literal> is_authenticated()</literal> 方法。 翻译
439#翻译 </entry></row><row><entry> 翻译 翻译
442#翻译 Returns the <literal>first_name</literal> plus the <literal>last_name</literal> , with a space in between. 返回<literal> first_name</literal> 加上<literal> last_name</literal> ,中间插入一个空格。 翻译
443#翻译 </entry></row><row><entry> 翻译 翻译
444#翻译 <literal>set_password(passwd)</literal> <literal>set_password(passwd)</literal> 翻译
445#翻译 </entry><entry> 翻译 翻译
446#翻译 Sets the user's password to the given raw string, taking care of the password hashing. 设定用户密码为指定字符串(自动处理成哈希串)。 翻译
447#翻译 This doesn't actually save the <literal>User</literal> object. 实际上没有保存<literal>User</literal>对象。 翻译
448#翻译 </entry></row><row><entry> 翻译 翻译
449#翻译 <literal>check_password(passwd)</literal> check_password(passwd) 翻译
450#翻译 </entry><entry> 翻译 翻译
451#翻译 Returns <literal>True</literal> if the given raw string is the correct password for the user. 如果指定的字符串与用户密码匹配则返回<literal>True</literal>。 翻译
452#翻译 This takes care of the password hashing in making the comparison. 比较时会使用密码哈希表。 翻译
453#翻译 </entry></row><row><entry> 翻译 翻译
456#翻译 Returns a list of permission strings that the user has through the groups he or she belongs to. 返回一个用户通过其所属组获得的权限字符串列表。 翻译
457#翻译 </entry></row><row><entry> 翻译 翻译
460#翻译 Returns a list of permission strings that the user has, both through group and user permissions. 返回一个用户通过其所属组以及自身权限所获得的权限字符串列表。 翻译
461#翻译 </entry></row><row><entry> 翻译 翻译
464#翻译 Returns <literal>True</literal> if the user has the specified permission, where <literal>perm</literal> is in the format <literal>&quot;package.codename&quot;</literal> . If the user is inactive, this method will always return <literal>False</literal> . 如果用户有指定的权限,则返回<literal> True</literal> ,此时<literal> perm</literal> 的格式是<literal> "package.codename"</literal> 。如果用户已不活动,此方法总是返回<literal> False</literal> 。 翻译
465#翻译 </entry></row><row><entry> 翻译 翻译
466#翻译 <literal>has_perms(perm_list)</literal> has_perms(perm_list) 翻译
467#翻译 </entry><entry> 翻译 翻译
468#翻译 Returns <literal>True</literal> if the user has <emphasis>all</emphasis> of the specified permissions. 如果用户拥有<emphasis> 全部</emphasis> 的指定权限,则返回<literal> True</literal> 。 翻译
469#翻译 If the user is inactive, this method will always return <literal>False</literal> . 如果用户是不活动的,这个方法总是返回<literal> False</literal> 。 翻译
470#翻译 </entry></row><row><entry> 翻译 翻译
471#翻译 <literal>has_module_perms(app_label)</literal> <literal>has_module_perms(app_label)</literal> 翻译
472#翻译 </entry><entry> 翻译 翻译
473#翻译 Returns <literal>True</literal> if the user has any permissions in the given <literal>app_label</literal> . If the user is inactive, this method will always return <literal>False</literal> . 如果用户拥有给定的<literal> app_label</literal> 中的任何权限,则返回<literal> True</literal> 。如果用户已不活动,这个方法总是返回<literal> False</literal> 。 翻译
474#翻译 </entry></row><row><entry> 翻译 翻译
475#翻译 <literal>get_and_delete_messages()</literal> get_and_delete_messages() 翻译
476#翻译 </entry><entry> 翻译 翻译
477#翻译 Returns a list of <literal>Message</literal> objects in the user's queue and deletes the messages from the queue. 返回一个用户队列中的<literal> Message</literal> 对象列表,并从队列中将这些消息删除。 翻译
478#翻译 </entry></row><row><entry> 翻译 翻译
479#翻译 <literal>email_user(subj, msg)</literal> <literal>email_user(subj, msg)</literal> 翻译
480#翻译 </entry><entry> 翻译 翻译
481#翻译 Sends an email to the user. 向用户发送一封电子邮件。 翻译
482#翻译 This email is sent from the <literal>DEFAULT_FROM_EMAIL</literal> setting. 这封电子邮件是从<literal> DEFAULT_FROM_EMAIL</literal> 设置的地址发送的。 翻译
483#翻译 You can also pass a third argument, <literal>from_email</literal> , to override the From address on the email. 你还可以传送一个第三参数:<literal> from_email</literal> ,以覆盖电邮中的发送地址。 翻译
484#翻译 </entry></row></tbody></tgroup></table><cnid>132 翻译 翻译
485#翻译 Finally, <literal>User</literal> objects have two many-to-many fields: 最后,<literal> User</literal> 对象有两个many-to-many属性。 翻译
486#翻译 <literal>groups</literal> and <literal>permissions</literal> . <literal>User</literal> objects can access their related objects in the same way as any other many-to-many field: <literal> groups</literal> 和<literal> permissions</literal> 。正如其他的many-to-many属性使用的方法一样,<literal> User</literal> 对象可以获得它们相关的对象: 翻译
489#翻译 Logging In and Out 登录和退出 翻译
491#翻译 Django provides built-in view functions for handling logging in and out (and a few other nifty tricks), but before we get to those, let's take a look at how to log users in and out by hand. Django 提供内置的视图(view)函数用于处理登录和退出 (以及其他奇技淫巧),但在开始前,我们来看看如何手工登录和退出。 翻译
492#翻译 Django provides two functions to perform these actions in <literal>django.contrib.auth</literal> : <literal>authenticate()</literal> and <literal>login()</literal> . Django提供两个函数来执行<literal>django.contrib.auth</literal>中的动作 : <literal>authenticate()</literal> 和<literal>login()</literal>。 翻译
494#翻译 To authenticate a given username and password, use <literal>authenticate()</literal> . It takes two keyword arguments, <literal>username</literal> and <literal>password</literal> , and it returns a <literal>User</literal> object if the password is valid for the given username. 认证给出的用户名和密码,使用 <literal>authenticate()</literal> 函数。它接受两个参数,用户名 username 和 密码 password ,并在密码对给出的用户名合法的情况下返回一个 User 对象。 翻译
495#翻译 If the password is invalid, <literal>authenticate()</literal> returns <literal>None</literal> : 如果密码不合法,<literal>authenticate()</literal>返回<literal>None</literal>。 翻译
498#翻译 <literal>authenticate()</literal> only verifies a user's credentials. <literal>authenticate()</literal> 只是验证一个用户的证书而已。 翻译
499#翻译 To log in a user, use <literal>login()</literal> . It takes an <literal>HttpRequest</literal> object and a <literal>User</literal> object and saves the user's ID in the session, using Djangos session framework. 而要登录一个用户,使用 <literal>login()</literal> 。该函数接受一个 <literal>HttpRequest</literal> 对象和一个 <literal>User</literal> 对象作为参数并使用Django的会话( <literal>session</literal> )框架把用户的ID保存在该会话中。 翻译
501#翻译 This example shows how you might use both <literal>authenticate()</literal> and <literal>login()</literal> within a view function: 下面的例子演示了如何在一个视图中同时使用 <literal>authenticate()</literal> 和 <literal>login()</literal> 函数: 翻译
504#翻译 To log out a user, use <literal>django.contrib.auth.logout()</literal> within your view. 注销一个用户,在你的视图中使用 <literal>django.contrib.auth.logout()</literal> 。 翻译
505#翻译 It takes an <literal>HttpRequest</literal> object and has no return value: 它接受一个<literal>HttpRequest</literal>对象并且没有返回值。 翻译
508#翻译 Note that <literal>auth.logout()</literal> doesn't throw any errors if the user wasnt logged in. 注意,即使用户没有登录, <literal>logout()</literal> 也不会抛出任何异常。 翻译
510#翻译 In practice, you usually will not need to write your own login/logout functions; the authentication system comes with a set of views for generically handling logging in and out. 在实际中,你一般不需要自己写登录/登出的函数;认证系统提供了一系例视图用来处理登录和登出。 翻译
511#翻译 The first step in using these authentication views is to wire them up in your URLconf. 使用认证视图的第一步是把它们写在你的URLconf中。 翻译
512#翻译 You'll need to add this snippet: 你需要这样写: 翻译
515#翻译 <literal>/accounts/login/</literal> and <literal>/accounts/logout/</literal> are the default URLs that Django uses for these views. <literal>/accounts/login/</literal> 和 <literal>/accounts/logout/</literal> 是Django提供的视图的默认URL。 翻译
517#翻译 By default, the <literal>login</literal> view renders a template at <literal>registration/login.html</literal> (you can change this template name by passing an extra view argument ,``template_name``). 缺省情况下, <literal>login</literal> 视图渲染 <literal>registragiton/login.html</literal> 模板(可以通过视图的额外参数 <literal>template_name</literal> 修改这个模板名称)。 翻译
518#翻译 This form needs to contain a <literal>username</literal> and a <literal>password</literal> field. 这个表单必须包含 <literal>username</literal> 和 <literal>password</literal> 域。如下示例: 翻译
519#翻译 A simple template might look like this: 一个简单的 template 看起来是这样的 翻译
522#翻译 If the user successfully logs in, he or she will be redirected to <literal>/accounts/profile/</literal> by default. 如果用户登录成功,缺省会重定向到 <literal>/accounts/profile</literal> 。 翻译
523#翻译 You can override this by providing a hidden field called <literal>next</literal> with the URL to redirect to after logging in. 你可以提供一个保存登录后重定向URL的<literal>next</literal>隐藏域来重载它的行为。 翻译
524#翻译 You can also pass this value as a <literal>GET</literal> parameter to the login view and it will be automatically added to the context as a variable called <literal>next</literal> that you can insert into that hidden field. 也可以把值以<literal>GET</literal>参数的形式发送给视图函数,它会以变量<literal>next</literal>的形式保存在上下文中,这样你就可以把它用在隐藏域上了。 翻译
526#翻译 The logout view works a little differently. logout视图有一些不同。 翻译
527#翻译 By default it renders a template at <literal>registration/logged_out.html</literal> (which usually contains a You've successfully logged out message). 默认情况下它渲染 <literal>registration/logged_out.html</literal> 模板(这个视图一般包含你已经成功退出的信息)。 翻译
528#翻译 However, you can call the view with an extra argument, <literal>next_page</literal> , which will instruct the view to redirect after a logout. 视图中还可以包含一个参数 <literal>next_page</literal> 用于退出后重定向。 翻译
530#翻译 Limiting Access to Logged-in Users 限制已登录用户的访问 翻译
532#翻译 Of course, the reason we're going through all this trouble is so we can limit access to parts of our site. 有很多原因需要控制用户访问站点的某部分。 翻译
534#翻译 The simple, raw way to limit access to pages is to check <literal>request.user.is_authenticated()</literal> and redirect to a login page: 一个简单原始的限制方法是检查 <literal>request.user.is_authenticated()</literal> ,然后重定向到登陆页面: 翻译
537#翻译 or perhaps display an error message: 或者显示一个出错信息: 翻译
540#翻译 As a shortcut, you can use the convenient <literal>login_required</literal> decorator: 作为一个快捷方式, 你可以使用便捷的 <literal>login_required</literal> 修饰符: 翻译
543#翻译 <literal>login_required</literal> does the following: <literal>login_required</literal> 做下面的事情: 翻译
545#翻译 If the user isn't logged in, redirect to <literal>/accounts/login/</literal> , passing the current URL path in the query string as <literal>next</literal> , for example: 如果用户没有登录, 重定向到 <literal>/accounts/login/</literal> , 把当前绝对URL作为 <literal>next</literal> 在查询字符串中传递过去, 例如: 翻译
546#翻译 <literal>/accounts/login/?next=/polls/3/</literal> . /accounts/login/?next=/polls/3/ 。 翻译
548#翻译 If the user is logged in, execute the view normally. 如果用户已经登录, 正常地执行视图函数。 翻译
549#翻译 The view code can then assume that the user is logged in. 视图代码就可以假定用户已经登录了。 翻译
551#翻译 Limiting Access to Users Who Pass a Test 对通过测试的用户限制访问 翻译
553#翻译 Limiting access based on certain permissions or some other test, or providing a different location for the login view works essentially the same way. 限制访问可以基于某种权限,某些检查或者为login视图提供不同的位置,这些实现方式大致相同。 翻译
555#翻译 The raw way is to run your test on <literal>request.user</literal> in the view directly. 一般的方法是直接在视图的 <literal>request.user</literal> 上运行检查。 翻译
556#翻译 For example, this view checks to make sure the user is logged in and has the permission <literal>polls.can_vote</literal> (more about how permissions works follows): 例如,下面视图确认用户登录并是否有 <literal>polls.can_vote</literal>权限: 翻译
559#翻译 Again, Django provides a shortcut called <literal>user_passes_test</literal> . It takes arguments and generates a specialized decorator for your particular situation: 并且Django有一个称为 <literal>user_passes_test</literal> 的简洁方式。它接受参数然后为你指定的情况生成装饰器。 翻译
562#翻译 <literal>user_passes_test</literal> takes one required argument: <literal>user_passes_test</literal> 使用一个必需的参数: 翻译
563#翻译 a callable that takes a <literal>User</literal> object and returns <literal>True</literal> if the user is allowed to view the page. 一个可调用的方法,当存在 <literal>User</literal> 对象并当此用户允许查看该页面时返回 <literal>True</literal> 。 翻译
564#翻译 Note that <literal>user_passes_test</literal> does not automatically check that the <literal>User</literal> is authenticated; you should do that yourself. 注意 user_passes_test 不会自动检查 User 是否认证,你应该自己做这件事。 翻译
566#翻译 In this example we're also showing the second (optional) argument, <literal>login_url</literal> , which lets you specify the URL for your login page (<literal>/accounts/login/</literal> by default). 例子中我们也展示了第二个可选的参数 <literal>login_url</literal> ,它让你指定你的登录页面的URL(默认为 <literal>/accounts/login/</literal> )。 翻译
567#翻译 If the user doesn't pass the test, then the <literal>user_passes_test</literal> decorator will redirect the user to the <literal>login_url</literal> . 如果用户没有通过测试,那么<literal>user_passes_test</literal>将把用户重定向到<literal>login_url</literal> 翻译
569#翻译 Because it's a relatively common task to check whether a user has a particular permission, Django provides a shortcut for that case: 既然检查用户是否有一个特殊权限是相对常见的任务,Django为这种情形提供了一个捷径: 翻译
570#翻译 the <literal>permission_required()</literal> decorator. <literal>permission_required()</literal> 装饰器。 翻译
571#翻译 Using this decorator, the earlier example can be written as follows: 使用这个装饰器,前面的例子可以改写为: 翻译
574#翻译 Note that <literal>permission_required()</literal> also takes an optional <literal>login_url</literal> parameter, which also defaults to <literal>'/accounts/login/'</literal> . 注意, <literal>permission_required()</literal> 也有一个可选的 <literal>login_url</literal> 参数, 这个参数默认为 <literal>'/accounts/login/'</literal> 。 翻译
576#翻译 Limiting Access to Generic Views 限制通用视图的访问 翻译
578#翻译 One of the most frequently asked questions on the Django users list deals with limiting access to a generic view. 在Django用户邮件列表中问到最多的问题是关于对通用视图的限制性访问。 翻译
579#翻译 To pull this off, you'll need to write a thin wrapper around the view and point your URLconf to your wrapper instead of the generic view itself: 为实现这个功能,你需要自己包装视图,并且在URLconf中,将你自己的版本替换通用视图: 翻译
582#翻译 You can, of course, replace <literal>login_required</literal> with any of the other limiting decorators. 当然, 你可以用任何其他限定修饰符来替换 <literal>login_required</literal> 。 翻译
584#翻译 Managing Users, Permissions, and Groups 管理 Users, Permissions 和 Groups 翻译
586#翻译 The easiest way by far to manage the auth system is through the admin interface. 管理认证系统最简单的方法是通过管理界面。 翻译
587#翻译 Chapter 6 discusses how to use Django's admin site to edit users and control their permissions and access, and most of the time you'll just use that interface. 第六章讨论了怎样使用Django的管理界面来编辑用户和控制他们的权限和可访问性,并且大多数时间你使用这个界面就可以了。 翻译
589#翻译 However, there are low-level APIs you can dive into when you need absolute control, and we discuss these in the sections that follow. 然而,当你需要绝对的控制权的时候,有一些低层 API 需要深入专研,我们将在下面的章节中讨论它们。 翻译
591#翻译 Creating Users 创建用户 翻译
593#翻译 Create users with the <literal>create_user</literal> helper function: 使用 <literal>create_user</literal> 辅助函数创建用户: 翻译
596#翻译 At this point, <literal>user</literal> is a <literal>User</literal> instance ready to be saved to the database (<literal>create_user()</literal> doesn't actually call <literal>save()</literal> itself). 在这里, <literal>user</literal> 是 <literal>User</literal> 类的一个实例,准备用于向数据库中存储数据。(<literal>create_user()</literal>实际上没有调用<literal>save()</literal>)。 翻译
597#翻译 You can continue to change its attributes before saving, too: <literal>create_user()</literal> 函数并没有在数据库中创建记录,在保存数据之前,你仍然可以继续修改它的属性值。 翻译
600#翻译 Changing Passwords 修改密码 翻译
602#翻译 You can change a password with <literal>set_password()</literal> : 你可以使用 <literal>set_password()</literal> 来修改密码: 翻译
605#翻译 Don't set the <literal>password</literal> attribute directly unless you know what you're doing. 除非你清楚的知道自己在做什么,否则不要直接修改 <literal>password</literal> 属性。 翻译
606#翻译 The password is actually stored as a <emphasis>salted hash</emphasis> and thus can't be edited directly. 其中保存的是密码的 <emphasis>加入salt的hash值</emphasis> ,所以不能直接编辑。 翻译
608#翻译 More formally, the <literal>password</literal> attribute of a <literal>User</literal> object is a string in this format: 一般来说, <literal>User</literal> 对象的 <literal>password</literal> 属性是一个字符串,格式如下: 翻译
611#翻译 That's a hash type, the salt, and the hash itself, separated by the dollar sign ($) character. 这是哈希类型,salt和哈希本身,用美元符号($)分隔。 翻译
613#翻译 <literal>hashtype</literal> is either <literal>sha1</literal> (default) or <literal>md5</literal> , the algorithm used to perform a one-way hash of the password. <literal>hashtype</literal> 是 <literal>sha1</literal> (默认)或者 <literal>md5</literal> ,它是用来处理单向密码哈希的算法。 翻译
614#翻译 <literal>salt</literal> is a random string used to salt the raw password to create the hash, for example: Salt是一个用来加密原始密码以创建哈希的随机字符串,例如: 翻译
617#翻译 The <literal>User.set_password()</literal> and <literal>User.check_password()</literal> functions handle the setting and checking of these values behind the scenes. <literal>User.set_password()</literal> 和 <literal>User.check_password()</literal> 函数在后台处理和检查这些值。 翻译
619#翻译 Salted hashes salt化得哈希值 翻译
621#翻译 A <emphasis>hash</emphasis> is a one-way cryptographic function that is, you can easily compute the hash of a given value, but it's nearly impossible to take a hash and reconstruct the original value. 一次 <emphasis>哈希</emphasis> 是一次单向的加密过程,你能容易地计算出一个给定值的哈希码,但是几乎不可能从一个哈希码解出它的原值。 翻译
623#翻译 If we stored passwords as plain text, anyone who got their hands on the password database would instantly know everyone's password. 如果我们以普通文本存储密码,任何能进入数据库的人都能轻易的获取每个人的密码。 翻译
624#翻译 Storing passwords as hashes reduces the value of a compromised database. 使用哈希方式来存储密码相应的减少了数据库泄露密码的可能。 翻译
626#翻译 However, an attacker with the password database could still run a <emphasis>brute- force</emphasis> attack, hashing millions of passwords and comparing those hashes against the stored values. 然而,攻击者仍然可以使用 <emphasis>暴力破解</emphasis> 使用上百万个密码与存储的值对比来获取数据库密码。 翻译
627#翻译 This takes some time, but less than you might think. 这需要花一些时间,但是智能电脑惊人的速度超出了你的想象。 翻译
629#翻译 Worse, there are publicly available <emphasis>rainbow tables</emphasis> , or databases of pre-computed hashes of millions of passwords. 更糟糕的是我们可以公开地得到 <emphasis>rainbow tables</emphasis> (一种暴力密码破解表)或预备有上百万哈希密码值的数据库。 翻译
630#翻译 With a rainbow table, an experienced attacker could break most passwords in seconds. 使用rainbow tables可以在几秒之内就能搞定最复杂的一个密码。 翻译
632#翻译 Adding a <emphasis>salt</emphasis> basically an initial random value to the stored hash adds another layer of difficulty to breaking passwords. 在存储的hash值的基础上,加入 <emphasis>salt</emphasis> 值(一个随机值),增加了密码的强度,使得破解更加困难。 翻译
633#翻译 Because salts differ from password to password, they also prevent the use of a rainbow table, thus forcing attackers to fall back on a brute-force attack, itself made more difficult by the extra entropy added to the hash by the salt. 因为每个密码的salt值都不相同,这也限制了rainbow table的使用,使得攻击者只能使用最原始的暴力破解方法。 翻译
635#翻译 While salted hashes aren't absolutely the most secure way of storing passwords, they're a good middle ground between security and convenience. 加入salt值得hash并不是绝对安全的存储密码的方法,然而却是安全和方便之间很好的折衷。 翻译
637#翻译 Handling Registration 处理注册 翻译
639#翻译 We can use these low-level tools to create views that allow users to sign up for new accounts. 我们可以使用这些底层工具来创建允许用户注册的视图。 翻译
640#翻译 Different developers implement registration differently, so Django leaves writing a registration view up to you. 最近每个开发人员都希望实现各自不同的注册方法,所以Django把写注册视图的工作留给了你。 翻译
641#翻译 Luckily, it's pretty easy. 幸运的是,这很容易。 翻译
643#翻译 At its simplest, we could provide a small view that prompts for the required user information and creates those users. 作为这个事情的最简化处理, 我们可以提供一个小视图, 提示一些必须的用户信息并创建这些用户。 翻译
644#翻译 Django provides a built-in form you can use for this purpose, which we'll use in this example: Django为此提供了可用的内置表单, 下面这个例子就使用了这个表单: 翻译
647#翻译 This form assumes a template named <literal>registration/register.html</literal> . Here's an example of what that template might look like: 这个表单需要一个叫 <literal>registration/register.html</literal> 的模板。这个模板可能是这样的: 翻译
650#翻译 Using Authentication Data in Templates 在模板中使用认证数据 翻译
652#翻译 The current logged-in user and his or her permissions are made available in the template context when you use <literal>RequestContext</literal> (see Chapter 9). 当前登入的用户以及他(她)的权限可以通过 <literal>RequestContext</literal> 在模板的context中使用(详见第9章)。 翻译
654#翻译 Note 注意 翻译
656#翻译 Technically, these variables are only made available in the template context if you use <literal>RequestContext</literal> 从技术上来说,只有当你使用了 <literal>RequestContext</literal> 翻译
657#翻译 <emphasis>and</emphasis> your <literal>TEMPLATE_CONTEXT_PROCESSORS</literal> setting contains <literal>&quot;django.core.context_processors.auth&quot;</literal> , which is the default. <emphasis>并且</emphasis>TEMPLATE_CONTEXT_PROCESSORS 设置包含了 "django.core.context_processors.auth" (默认情况就是如此)时,这些变量才能在模板context中使用。 翻译
658#翻译 Again, see Chapter 9 for more information. 详细信息请参阅第九章。 翻译
660#翻译 When using <literal>RequestContext</literal> , the current user (either a <literal>User</literal> instance or an <literal>AnonymousUser</literal> instance) is stored in the template variable <literal>{{ user }}</literal> : 当使用 <literal>RequestContext</literal> 时, 当前用户 (是一个 <literal>User</literal> 实例或一个 <literal>AnonymousUser</literal> 实例) 存储在模板变量 <literal>{{ user }}</literal> 中: 翻译
663#翻译 This user's permissions are stored in the template variable <literal>{{ perms }}</literal> . This is a template-friendly proxy to a couple of permission methods described shortly. 这些用户的权限信息存储在 <literal>{{ perms }}</literal> 模板变量中。这是一些列权限方法的简短代理。 翻译
665#翻译 There are two ways you can use this <literal>perms</literal> object. 你有两种方式来使用 <literal>perms</literal> 对象。 翻译
666#翻译 You can use something like <literal>{% if perms.polls %}</literal> to check if the user has <emphasis>any</emphasis> permissions for some given application, or you can use something like <literal>{% if perms.polls.can_vote %}</literal> to check if the user has a specific permission. 你可以使用类似于 <literal>{{ perms.polls }}</literal> 的形式来检查,对于某个特定的应用,一个用户是否具有 <emphasis>任意</emphasis> 权限;你也可以使用 <literal>{{ perms.polls.can_vote }}</literal> 这样的形式,来检查一个用户是否拥有特定的权限。 翻译
668#翻译 Thus, you can check permissions in template <literal>{% if %}</literal> statements: 这样你就可以在模板中的 <literal>{% if %}</literal> 语句中检查权限: 翻译
671#翻译 Permissions, Groups and Messages 权限、组和消息 翻译
673#翻译 There are a few other bits of the authentication framework that we've only dealt with in passing. 在认证框架中还有其他的一些功能。 翻译
674#翻译 We'll take a closer look at them in the following sections. 我们会在接下来的几个部分中进一步地了解它们。 翻译
676#翻译 Permissions 权限 翻译
678#翻译 Permissions are a simple way to mark users and groups as being able to perform some action. 权限可以很方便地标识用户和用户组可以执行的操作。 翻译
679#翻译 They are usually used by the Django admin site, but you can easily use them in your own code. 它们被Django的admin管理站点所使用,你也可以在你自己的代码中使用它们。 翻译
681#翻译 The Django admin site uses permissions as follows: Django的admin站点如下使用权限: 翻译
683#翻译 Access to view the add form, and add an object is limited to users with the <emphasis>add</emphasis> permission for that type of object. 只有设置了 <emphasis>add</emphasis> 权限的用户才能使用添加表单,添加对象的视图。 翻译
685#翻译 Access to view the change list, view the change form, and change an object is limited to users with the <emphasis>change</emphasis> permission for that type of object. 只有设置了 <emphasis>change</emphasis> 权限的用户才能使用变更列表,变更表单,变更对象的视图。 翻译
687#翻译 Access to delete an object is limited to users with the <emphasis>delete</emphasis> permission for that type of object. 只有设置了 <emphasis>delete</emphasis> 权限的用户才能删除一个对象。 翻译
689#翻译 Permissions are set globally per type of object, not per specific object instance. 权限是根据每一个类型的对象而设置的,并不具体到对象的特定实例。 翻译
690#翻译 For example, it's possible to say Mary may change news stories, but permissions don't let you say Mary may change news stories, but only the ones she created herself or Mary may only change news stories that have a certain status, publication date, or ID. 例如,我们可以允许Mary改变新闻故事,但是目前还不允许设置Mary只能改变自己创建的新闻故事,或者是给定状态,出版日期或者ID号的新闻故事。 翻译
692#翻译 These three basic permissions add, change, and delete are automatically created for each Django model. 会自动为每一个Django模型创建三个基本权限:增加、改变和删除。 翻译
693#翻译 Behind the scenes, these permissions are added to the <literal>auth_permission</literal> database table when you run <literal>manage.py syncdb</literal> . 当你运行<literal>manage.py syncdb</literal>命令时,这些权限被添加到<literal>auth_permission</literal>数据库表中。 翻译
695#翻译 These permissions will be of the form <literal>&quot;<app>.<action>_<object_name>&quot;</literal> . That is, if you have a <literal>polls</literal> application with a <literal>Choice</literal> model, you'll get permissions named <literal>&quot;polls.add_choice&quot;</literal> , <literal>&quot;polls.change_choice&quot;</literal> , and <literal>&quot;polls.delete_choice&quot;</literal> . 权限以 <literal>"._"</literal> 的形式出现。就是说,假如你的应用<literal>polls</literal>有一个<literal>Choice</literal>模型,那么对应的权限就是<literal>"polls.add_choice"</literal>,<literal>"polls.change_choice"<literal>和<literal>"polls.delete_choice"</literal>。 翻译
697#翻译 Just like users, permissions are implemented in a Django model that lives in <literal>django.contrib.auth.models</literal> . This means that you can use Django's database API to interact directly with permissions if you like. 就跟用户一样,权限也就是Django模型中的 <literal>django.contrib.auth.models</literal> 。因此如果你愿意,你也可以通过Django的数据库API直接操作权限。 翻译
699#翻译 Groups 翻译
701#翻译 Groups are a generic way of categorizing users so you can apply permissions, or some other label, to those users. 组提供了一种通用的方式来让你将用户分类,这样就可以为组内的用户授予权限规则或其他标签。 翻译
702#翻译 A user can belong to any number of groups. 一个用户可以隶属于任何数量的组。 翻译
704#翻译 A user in a group automatically has the permissions granted to that group. 在一个组中的用户自动获得了赋予该组的权限。 翻译
705#翻译 For example, if the group <literal>Site editors</literal> has the permission <literal>can_edit_home_page</literal> , any user in that group will have that permission. 例如, 如果<literal>Site editors</literal> 组拥有 <literal>can_edit_home_page</literal> 权限,那么该组中的任何用户都拥有这个权限。 翻译
707#翻译 Groups are also a convenient way to categorize users to give them some label, or extended functionality. 组也可以通过给定一些用户特殊的标记,来扩展功能。 翻译
708#翻译 For example, you could create a group <literal>'Special users'</literal> , and you could write code that could, say, give those users access to a members-only portion of your site, or send them members-only e-mail messages. 例如,你可以创建一个 <literal>'Special users'</literal> 组,并且允许组中的用户访问站点的一些VIP部分,或者发送VIP的邮件消息。 翻译
710#翻译 Like users, the easiest way to manage groups is through the admin interface. 和用户管理一样,admin接口是管理组的最简单的方法。 翻译
711#翻译 However, groups are also just Django models that live in <literal>django.contrib.auth.models</literal> , so once again you can always use Django's database APIs to deal with groups at a low level. 然而,组也就是Django模型 <literal>django.contrib.auth.models</literal> ,因此你可以使用Django的数据库API,在底层访问这些组。 翻译
713#翻译 Messages 消息 翻译
715#翻译 The message system is a lightweight way to queue messages for given users. 消息系统会为给定的用户发送消息。 翻译
716#翻译 A message is associated with a <literal>User</literal> . There's no concept of expiration or timestamps. 每个消息都和一个 <literal>User</literal> 相关联。不存在过期和时间戳的概念。 翻译
718#翻译 Messages are used by the Django admin interface after successful actions. 在每个成功的操作以后,Django的admin管理接口就会使用消息机制。 翻译
719#翻译 For example, when you create an object, you'll notice a The object was created successfully message at the top of the admin page. 例如,当你创建了一个对象,你会在admin页面的顶上看到 <literal>The object was created successfully</literal> 的消息。 翻译
721#翻译 You can use the same API to queue and display messages in your own application. 你也可以使用相同的API在你自己的应用中排队接收和显示消息。 翻译
722#翻译 The API is simple: API非常地简单: 翻译
724#翻译 To create a new message, use <literal>user.message_set.create(message='message_text')</literal> . 要创建一条新的消息,使用 <literal>user.message_set.create(message='message_text')</literal> 。 翻译
726#翻译 To retrieve/delete messages, use <literal>user.get_and_delete_messages()</literal> , which returns a list of <literal>Message</literal> objects in the user's queue (if any) and deletes the messages from the queue. 要获得/删除消息,使用 <literal>user.get_and_delete_messages()</literal> ,这会返回一个 <literal>Message</literal> 对象的列表,并且从队列中删除返回的项。 翻译
728#翻译 In this example view, the system saves a message for the user after creating a playlist: 在例子视图中,系统在创建了播放列表(playlist)以后,为用户保存了一条消息。 翻译
731#翻译 When you use <literal>RequestContext</literal> , the current logged-in user and his or her messages are made available in the template context as the template variable <literal>{{ messages }}</literal> . Here's an example of template code that displays messages: 当使用 <literal>RequestContext</literal> ,当前登录的用户以及他(她)的消息,就会以模板变量 <literal>{{ messages }}</literal> 出现在模板的context中。 翻译
734#翻译 Note that <literal>RequestContext</literal> calls <literal>get_and_delete_messages</literal> behind the scenes, so any messages will be deleted even if you don't display them. 需要注意的是 <literal>RequestContext</literal> 会在后台调用 <literal>get_and_delete_messages</literal> ,因此即使你没有显示它们,它们也会被删除掉。 翻译
736#翻译 Finally, note that this messages framework only works with users in the user database. 最后注意,这个消息框架只能服务于在用户数据库中存在的用户。 翻译
737#翻译 To send messages to anonymous users, use the session framework directly. 如果要向匿名用户发送消息,请直接使用会话框架。 翻译
739#翻译 What's Next 下一章 翻译
741#翻译 The session and authorization system is a lot to absorb. 是的,会话和认证系统有太多的东西要学。 翻译
742#翻译 Most of the time, you won't need all the features described in this chapter, but when you need to allow complex interactions between users, it's good to have all that power available. 大多数情况下,你并不需要本章所提到的所有功能。但当你需要在用户间实现复杂交互时,最好能熟悉这些功能。 翻译
744#翻译 In the <reference name="next chapter" refuri="../chapter15/">next chapter</reference>, we'll take a look at Django's caching infrastructure, which is a convenient way to improve the performance of your application. 在<reference name="next chapter" refuri="../chapter15/"> 下一章</reference> ,我们会看一下Django的缓存机制,这是一个提高你的网页应用性能的便利的办法。 翻译