其实本教程以展示基本概念为已任,对于一些高级的话题我也在不停地学习中,希望能有所展示。让我们一起学习吧。

在了解了基本的 django 开发的过程及 django 的一些基本特性之后,越来越多的东西在等着我们。现在我们就学习一下 session 吧。session可以翻译为“会话”,做过web的可能都知道。它就是为了实现页面间的数据交换而产生的东西,一般有一个session_id,它会保存在浏览器的 cookie 中,因此如果你的浏览器禁止了 cookie ,下面的试验是做不了的。

django 中的 session 也非常简单,它就存在于 request 对象的session属性中。你可以把它看成一个字典就可以了。

下面我们做一个非常简单的功能:首先当用户进入某个页面,这个页面会显示一个登录页面,上面有一个文本框用来输入用户名,还有一个提交按钮用来提交数据。当用户输入用户名,然后点提交,则显示显示用户已经登录,并且打印出用户的姓名来,同时还提供一个“注销”按钮。然后如果用户再次进入这个页面,则显示同登录成功后的页面。如果点击注销则重新进入未登录的页面。

1. 在newtest下创建 login.py

from django.core.extensions import render_to_response
from django.utils.httpwrappers import HttpResponseRedirect

def login(request):
    username = request.POST.get(‘username’, None)
    if username:
        request.session['username'] = username
    username = request.session.get(‘username’, None)
    if username:
        return render_to_response(‘login’, {’username’:username})
    else:
        return render_to_response(‘login’)
   
def logout(request):
    try:
        del request.session['username']
    except KeyError:
        pass
    return HttpResponseRedirect("/login/")

有些复杂了吗?没关系,让我解释一下。这里有两个方法:login 和 logout。login用来提供初始页面、处理提供数据和判断用户是否登录。而 logout 只是用来从session中删除用户名,同时将页面重定向到 login 画面。这里我仍然使用了模板,并且根据传入不同的字典来控制模板的生成。是的,因为 django 的模块支持 if 判断,所以可以做到。

在 login 中的判断逻辑是:

先从 POST 中取 username (这样username需要由模板的form来提供),如果存在则加入到session中去。加入session很简单,就是一个字典的key赋值。

然后再从session中取 username,有两种可能:一种是上一步实现的。还有一种可能是直接从以前的session中取出来的,它不是新产生的。而这里并没有细分这两种情况。因此这个判断其实对应两种页面请求的处理:一种是提交了用户姓名,而另一种则是处理完用户提交姓名之后,用户再次进入的情况。而用户再次进入时,由于我们在前面已经将他的名字保存在 session 里面了,因此可以直接取出来。如果session中存在,则表示用户已经登录过,则输出login.html模板,同时传入了username字典值。而如果session中不存在,说明用户从来没有登录过,则输出login.html模板,这次不带值。

因此对于同一个login.html模板传入的不同值,后面我们会看到模板是如何区分的。

在 logout 中很简单。先试着删除session,然后重定向页面到 login 页面。这里使用了 HttpResponseRedirect 方法,它是从以前我们看到的 HttpResponse 派生来的子类。更多的派生子类和关于 response 的内容要参考 django 自带的 requese_response 文档。

2. 创建templates/login.html

{% if not username %}
<form method="post" action="/login/">
    用户名:<input type="text" name="username" value=""><br/>
    <input type="submit" value="登录">
</form>
{% else %}
你已经登录了!{{ username }}<br/>
<form method="post" action="/logout/">
    <input type="submit" value="注销">
</form>
{% endif %}

整个是一个if语句。在 django 模板中的 if 可以象 Python 一样使用,如使用 not , and , or。象 if not username 表示什么呢?它表示如果 usernmae 不存在,或为空,或是假值等等。而此时我们利用了 username 不存在这种判断。

上面的逻辑表示,如果 username 不存在,则显示一个表单,显示用户名输入文本框。如果存在,则显示已经登录信息,同时显示用户名和注销按钮。而这个注销铵钮对应于 logout 方法。

3. 修改 urls.py

from django.conf.urls.defaults import *

urlpatterns = patterns(”,
    # Example:
#    (r’^helloworld/’, ‘newtest.apps.helloworld.views.index’),
    (r’^$’, ‘newtest.helloworld.index’),
    (r’^add/$’, ‘newtest.add.index’),
    (r’^list/$’, ‘newtest.list.index’),
    (r’^csv/(?P<type>\w+)/$’, ‘newtest.csv.output’),
    (r’^login/$’, ‘newtest.login.login’),
    (r’^logout/$’, ‘newtest.login.logout’),

    # Uncomment this for admin:
#     (r’^admin/’, include(‘django.contrib.admin.urls.admin’)),
)

增加了 login 和 logout 两个url映射。

4. 启动 server 运行

但我要说,你一定会报错。因为我的也在报错。为什么,因此从这一刻起,我们就要进入有数据库的环境了。因为在 django 中 session 是存在数据库中的。因此在这里要进行数据库的初始化了。

5. 修改 settings.py

主要修改以下地方:

DATABASE_ENGINE = ’sqlite3′
DATABASE_NAME = ‘./data.db’
DATABASE_USER = ”
DATABASE_PASSWORD = ”
DATABASE_HOST = ”
DATABASE_PORT = ”

这里我使用 sqlite3。在使用数据库时,你同时需要自已去安装相应的数据库处理模块。对于 sqlite3 只需要修改两项:DATABASE_ENGINE和DATABASE_NAME。这里数据文件名我使用了相对路径,我想在实际情况下可能使用绝对路径为好。

6. 初始化数据库

改了配置还不够,还要执行相应的建库、建表的操作,使用django-admin.py 或 manage.py 都可以。

manage.py init

7. 启动 server

这次再进入试吧

http://localhost:8000/login/

从此我们要进入数据库的世界了,当然目前还没有用到,而 django 提从的许多自动化的高级功能都是需要数据库支持的。

注意,为了发贴所有半角大括号都改成了全角大括号,因此如果想运行的话,要进行替换处理。


7条评论

  1. I can’t get any params from "request.Post",but I don’t know why?I wanna help.

    Here are the codes(form django document):

    html:

    <form action="test" method="post">

    <input type="text" name="your_name" />

    <select multiple="multiple" name="bands">

    <option value="beatles">The Beatles</option>

    <option value="who">The Who</option>

    <option value="zombies">The Zombies</option>

    </select>

    <input type="submit" />

    </form>

    python:

    print request.GET

    print request.POST

    the result is:

    {}

    {}

    While I change the form method to "post",I can get the value from the form.

    {‘bands’: ['beatles', 'who', 'zombies'], ‘your_name’: ['teatgafgaga']}

    {}

    Can you give me some advises?

  2. Sorry,that’s a mistake, I change the form method to "get".

  3. 今天回顾教程,有点小的改进意见,交流一下:

    1、如果把index/login/logout分开来,逻辑上能更清晰一些;

    2、如果form action不带最前面的斜线,而是采用相对地址,能方便以后修改,比如作为app分发时include url patterns;

    3、相对于以上两点,把login和logout划分在index的下一层,更便于管理。

    修改之后大致是这个样子:

    #user.py

    def index(request):

    username = request.POST.get(‘username’, None)

    if username:

    request.session['username'] = username

    username = request.session.get(‘username’, None)

    if username:

    return render_to_response(‘user’, {‘username’: username})

    else:

    return render_to_response(‘user’)

    def login(request):

    username = request.POST.get(‘username’, None)

    if username:

    request.session['username'] = username

    return HttpResponseRedirect(‘../’)

    def logout(request):

    try:

    del request.session['username']

    except KeyError:

    pass

    return HttpResponseRedirect(‘../’)

    #templates/user.html

    {% if not username %}

    <form method="POST" action="login/">

    user name:

    <input type="text" name="username" value=""><br />

    <input type="submit" value="login">

    </form>

    {% else %}

    welcome, {{ username }}.<br />

    <form method="POST" action="logout/">

    <input type="submit" value="logout">

    </form>

    {% endif %}

    # part of url patterns



    (r’^user/$’, ‘my.user.index’),

    (r’^user/login/$’, ‘my.user.login’),

    (r’^user/logout/$’, ‘my.user.logout’),

  4. 这是风格问题。而且本例主要为了演示session,不是为了演示用户管理。因为是教程不是实际的东西,没有想太多,只是为了展示功能。

    url的设计的确有许多要注意的,不过还是留给大家自行把握好了。教程能不改就不改了,还是麻烦啊。

    谢谢建议。

  5. 写个文章确实挺累的,一个系列的教程就更不容易了,我能体会其中的辛苦。谢谢你的文章。

发表评论

评论也有版权!

click to change验证码