云笔记项目

第一节: 项目描述

第二节: 设计用户模模型类,并初步完成用户注册功能

create_time:是创建时间,我们要知道网站每天新增了多少用户,公司可能每天都要看这个数据,因为这通常会关系到项目之后的融资。参数auto_now_add=True表示我们在创建这个字段时Django可以自动帮我们自动添加当前时间 。

update_time:是更新时间,其参数auto_now=True表示一旦这个表中的某一条数据有更新,它就会自动把更新时的时间写到该数据的“更新时间”字段中。用来记录这条数据最近的一次更新是什么时候。这个也很有用,因为有时我们会根据这个分析一下用户的行为,比如这人什么时候干嘛了,更新了某个表中的某个数据。。。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>User Register</title>
</head>
<body>
<form action="/user/register/" method="post">
    <p>
        User Name: <input type="text" name="username">
    </p>

    <p>
        Enter Password: <input type="password" name="password_1">
    </p>

    <p>
        Re-enter Password: <input type="password" name="password_2">
    </p>

    <input type="submit" value="register">
</form>
</body>
</html>
from django.http import HttpResponse
from django.shortcuts import render
from .models import User

# Create your views here.

def register_view(request):
    # register
    # get:
    if request.method == 'GET':
        #   return the web page
        return render(request, 'user/register.html')
    # post:
    elif request.method == 'POST':
        # get the entered data from web page
        username = request.POST.get('username')
        password_1 = request.POST.get('password_1')
        password_2 = request.POST.get('password_2')
    #   1. if two times of input password are same
        if password_1 != password_2:
            return HttpResponse("the two entered passwords are inconsistent")
    #   2. if the username has been registered (check if username available)
        old_users = User.objects.filter(username=username)
        if old_users:
            return HttpResponse("User name has been existed.")
    #   3. insert data (we currently use plaintext password)
        User.objects.create(username=username, password=password_1)
        return HttpResponse("account registered successfully.")

第三节: 用户注册功能的优化

1、为什么做密码加密处理?

        答:因为一旦数据库外泄,用户的密码也将会泄露 

    注:密码的加密处理使用哈希算法

 

 2、插入问题

假设一个场景:我们有三四台设备都跑着这个项目代码,恰好同一时间一波人同时来注册同一个用户名,那么大家都请求可能会分散在这几台机器上,并且同一时间他们都走到了如下代码,并且大家拿到的结果都是当前用户名还没被注册,那么if语句判断之后,大家就继续走到了下面第三行代码User.objects.create(username=username, password=password)这里,那么谁的的sql语句最先操作了mysql,用户明就归谁了,那其他人就会收到报错信息,因为用户名是unique的(见下面第二张图)。

        if old_users:
            return HttpResponse("User name has been existed.")
        User.objects.create(username=username, password=password)
        return HttpResponse("account registered successfully.")

上面这个问题,是一个并发写入的问题。如何解决呢?

首先,这个错误报出来是一个正常的现象,我们只要用try把错误隐藏起来就可以了 (当然,前提是你要保证你的正常插入数据都没问题,套一个try,如果有错误,一定是数据库唯一索引这块报错了)

代码如下:

3、新用户注册后可以免登录一天

user/views.py中: 

cloud_note/cloud_note/settings.py中:在代码的最后一行,为session设置一天的生命周期(默认是14天)

 第四节:用户登录功能

 勾选“记住用户名”则有3天有效期,如果不勾选,则只有1天有效期。有效期结束后,就需要重新登录。

代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>User Login</title>
</head>
<body>
<form action="/user/login/" method="post">
    <p>
        User Name: <input type="text" name="username">
    </p>

    <p>
        Enter Password: <input type="password" name="password">
    </p>
    <p>
        <input type="checkbox" name="remember"> remember me
    </p>

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

</form>
</body>
</html>
def login_view(request):
    if request.method == 'GET':
        return render(request, 'user/login.html')
    elif request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        try:
            user = User.objects.get(username=username)
        except Exception as e:
            print('--login user error %s'%(e))
            return HttpResponse('Username or password incorrect.')
        m = hashlib.md5()
        m.update(password.encode())
        password = m.hexdigest()
        if password != user.password:
            return HttpResponse('Username or password incorrect.')
        # record session status(将会话状态信息存到相应的session里,因为用户登录后会在session中保持一天时间的登录状态
        request.session['username'] = username
        request.session['uid'] = user.id
        return HttpResponse('Login successful.')

注意:如果用户输入的密码错误或用户名不存在,都提示‘用户明或密码有误’,不要给出太明确的提示信息,以免一些别有用心的人搞事情(比如暴力的去试),加大了账户密码的破解难度,提高了安全性。

接下来,我们考虑勾选remember的问题:如果remember勾选,则有3天免登录,否则只有1天。但是我们之前已经在settings.py中设置了session只有1天的生命周期,那么该如何把会话状态的时间拉长?这里我们就要用到cookie了。

众所周知,cookie是把会话状态数据存储在浏览器中,这种方式在一定程度上减轻了服务器的压力。试想一下,假设勾选remember可以有一个月的免登录,并且会话信息存储在session中的话,那服务器就要存储会话信息至少一个月。如果有很多用户都勾选了,那服务器的存储压力就会比较大了。解决的方法是:如果用户勾选remember,则在cookie也存储一份该用户的会话信息,这样,并且把cookie的生命周期设置为我们希望的remember免登录的天数,而session只存储1天,这样服务器的压力就减轻了。

如果没有勾选remember,就只提交username和password,不提交remember,如下图所示:

如果勾选了remember,则会提交username,password和remember,如下图所示: 

所以我们判断用户是否勾选remember me,只要判断提交的内容是否有remember就可以了 

代码如下:
 

def login_view(request):
    if request.method == 'GET':
        return render(request, 'user/login.html')
    elif request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        try:
            user = User.objects.get(username=username)
        except Exception as e:
            print('--login user error %s'%(e))
            return HttpResponse('Username or password incorrect.')
        m = hashlib.md5()
        m.update(password.encode())
        password = m.hexdigest()
        if password != user.password:
            return HttpResponse('Username or password incorrect.')

        # record session status
        request.session['username'] = username
        request.session['uid'] = user.id

        # check if 'remember me' was selected
        resp = HttpResponse('Login successful.')
        if 'remember' in request.POST:
            # cookie store username and uid for 3 days if "remember me" is selected
            resp.set_cookie(key='username', value=username, max_age=3600 * 24 * 3)
            resp.set_cookie(key='uid', value=user.id, max_age=3600 * 24 * 3)

        return resp

第五节: 登录校验功能与网站首页

1、新增“登录校验”功能

在登录这块,要校验一下当前浏览器有没有登录的用户,如果之前登录过并且还在有效期内,那用户就不用再看到登录界面了,直接跳转到已登录。如果没登录过或过了有效期,则显示登录界面。即:要在user/login这个页面做登录状态的检查。

 代码如下:

2、网站首页

index/templates/index.html: 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{#    {{ request.session }}#}
{#    {{ request.COOKIES }}#}
{% if request.session.username and request.session.uid %}
    <p>
        Welcome {{ request.session.username }}
    </p>

    <p>
        <a href="">Logout</a>
    </p>
    <p>
        <a href="">My notes</a>
    </p>
{% elif request.COOKIES.username and request.COOKIES.uid %}
    <p>
        Welcome {{ request.COOKIES.username }}
    </p>

    <p>
        <a href="">Logout</a>
    </p>
    <p>
        <a href="">My notes</a>
    </p>
{% else %}
    <a href="/user/login/">Login</a>
    <a href="/user/register/">Register</a>
{% endif %}


</body>
</html>

 index/views.py:

from django.shortcuts import render

# Create your views here.
def index_view(request):

    return render(request, 'index/index.html')

 3、小作业:退出登录功能

 

4、小结

第六节:实现笔记功能

1、创建笔记模型类

2、笔记模块——列表页

独立完成。

需要注意的细节:用户能看到该页面的前提是已经登录了 

3、笔记模块——新增笔记功能

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Add Note</title>
</head>
<body>
<form action="/note/add_note/" method="post">
    <p>
        Title: <input type="text" name="title">
    </p>
    <p>
        <textarea name="content" cols="30" rows="10"></textarea>
        <input type="submit" value="save">
    </p>
</form>
</body>
</html>

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值