Django项目笔记——(用户系统的实现)

Posted 卷王2048

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django项目笔记——(用户系统的实现)相关的知识,希望对你有一定的参考价值。

Django上课笔记(四)——(用户系统的实现)

对于上节课对接acapp的过程由于不涉及知识性的内容,就不单独写一篇博客了。对接acapp及分配域名的内容请参考:

部署nginx与对接acapp - AcWing

也欢迎大家光临我另外项目课的其他博客:

Django上课笔记(一)——环境配置与项目创建(过程十分详细) - AcWing

(更新版)Django上课笔记(二)——菜单模块的实现, 含自动创建项目的脚本

pycharm连接服务器同步写代码(图文详细过程)

linux基础课thrift详细开发过程 - AcWing

项目地址

https://git.acwing.com/codeRokie/acapp

准备工作

1.为了在调试时能让报错信息能显示在浏览器上,需要在acapp/acapp/settings中将DEBUG = False改为DEBUG = True

2.为了查看后台数据管理系统,需要创建超级账户(之前讲过),创建的命令为:

#需要在项目的根目录acapp下执行
python3 manage.py createsuperuser 

3.进入后台的方式:你的域名后+/admin

docker run -p 20000:22 -p 8000:8000 -p 8001:80 -p 8002:443 --name acgame -itd django_lesson:2

扩充数据库

背景知识

1.django中默认的数据关系使用的的是sqlite3,

  • 他是一款轻型的数据库,遵守了ACID(原子性,一致性,隔离性,持久性)的关系型数据库管理系统
  • 零配置-无需安装和管理配置
  • 储存在单一磁盘文件中的一个完整的数据库
  • 支持数据库大小志2TB足够小,大概13万行C代码,4.43M,比一些流行的数据库在大部分数据库操作要快
  • 独立:没有额外的依赖
  • 源码完全的开源,你可以用于任何途径,你也可以出售他
  • 支持多种开发语言,C,C++,C#,php,Perl,Java,Python,Ruby等
  • 良好注释的源代码, 并且有着90%以上的测试覆盖率,且支持多种SQL语句

2.django当然也可以支持其他的数据库。

在实际的开发场景中,如y总课上所说,数据库一般是放在另一台专门存储数据库的服务器上的。对于我们现在这种轻量级想,则不用考虑用mysql作为数据库。直接用他默认给的数据库就可以。

3.django换用其他数据库的方法,请参考:

django 使用MySQL数据库 - 刘江的django教程 (liujiangblog.com)

Django详解之models操作 - 汪汪小喵咪 - 博客园 (cnblogs.com)

4.django的数据库管理模块是models.py,如果逻辑复杂就把这个文件变为models文件夹,并在里面创建一个__init__.py文件

添加自定义的数据表

因为账号信息可能有很多表,所以用文件夹进行管理

每用一个文件夹代替一个文件,都要在文件夹下创建一个__init__.py文件

创建表player

game/models下创建文件player,在player下创建一个文件player.py存储player表的信息

player.py内容如下:

#继承django数据库的基类
from django.db import models
from django.contrib.auth.models import User

#继承的类写在括号中
class Player(models.Model):
    #定义关联关系,每个player对应一个user
    #当user被删除,对应的player也被删除
    user = models.OneToOneField(User,on_delete=models.CASCADE)
    photo = models.URLField(max_length=256,blank=True)

    #显示每个player的数据在后台的名字
    def __str__(self):
        return str(self.user)

将player表注册到后台管理界面中

1.改动game/admin.py:

from django.contrib import admin
from game.models.player.player import Player
# Register your models here.

admin.site.register(Player)

2.运行2个命令,使后台更新数据库表

python3 manage.py makemigrations
python3 manage.py migrate

3.注意:

Nginx本身是一个静态资源的服务器,当只有静态资源的时候,就可以使用nginx来做服务器。

所以当静态资源更新时,客户端也会同步更新;但当后台资源更新时,客户端不会同步更新,需要重启ngnix服务,才能更新。

启动ngnix:

sudo /etc/init.d/nginx start
uwsgi --ini scripts/uwsgi.ini 

用户系统的建立

1.为了支持多端操作,需要在AcGame类中传入参数,用来支持和判断不同的端

2.每写一个函数(前后端交互的任务)的时候需要实现:

  • views层实现调用数据库的逻辑
  • url层中实现路由
  • js中实现对后端返回参数的调用

逻辑图:

实现view

在业务上,我们把视图层用户设置菜单与用户相关操作的逻辑放在game/views/settings文件夹下,与用户登录相关的操作,放在game/views/settings/getinfo.py中:

from django.http import JsonResponse
from game.models.player.player import Player


#在acapp端的请求函数
def getinfo_acapp(request):
    #表中的第一条数据
    player = Player.objects.all()[0]
    return JsonResponse(
        'result': "success",
        'username': player.user.username,
        'photo': player.photo,
    )


#在web端的请求函数
def getinfo_web(request):
    user = request.user
    if not user.is_authenticated:
        return JsonResponse(
            'result': "未登录"
        )
    else:
        player = Player.objects.all()[0]
        return JsonResponse(
            'result': "success",
            'username': player.user.username,
            'photo': player.photo,
        )


#分类处理不同端发来的请求
def getinfo(request):
    #通过get请求从前端获取一个参数
    platform = request.GET.get('platform')
    #判断是哪个端发来的请求
    if platform == "ACAPP":
        return getinfo_acapp(request)
    elif platform == "WEB":
        return getinfo_web(request)
    else:
        return JsonResponse(
            'result': "其他"
        )

实现url

game/urls/settings/index.py中,引入刚才实现的view层中的函数:

from django.urls import path
from game.views.settings.getinfo import getinfo


urlpatterns = [
    path("getinfo/", getinfo, name="settings_getinfo"),

]

实现js

修改game/static/js/src/menu/zbase.js:

这里由于代码过长,就不在此展示,请移步:

整个用户系统的访问流程

请参考我的另一篇详细博客

用户注册登录系统的实现

注意:在执行多端操作的时候,web端的登录状态和后台的登录状态同步,如果要调试,一定要注意登出后台账号

js

由于过于冗长且非重点,htmlcss部分大家可以自行查询源码

前端信息发送和接收的逻辑实现

  1. 从网页表单中获取用户填入的信息。在dom树中将对应表单的元素"抠"出来,保存在constructor()
  2. 实现鼠标点击后向后端发送信息的函数

game/static/src/menu/settings/zbase.js

class Settings 
    constructor(root) 
        this.root = root;
        //表明在哪个端的参数
        this.platform = "WEB";
        if (this.root.AcWingOS) this.platform = "ACAPP";
        //接收后端参数
        this.username = "";
        this.photo = "";

        this.$settings = $(`
            <div class="ac-game-settings">
    <div class="ac-game-settings-login">
        <div class="ac-game-settings-title">
            登录
        </div>
        <div class="ac-game-settings-username">
            <div class="ac-game-settings-item">
                <input type="text" placeholder="用户名">
            </div>
        </div>
        <div class="ac-game-settings-password">
            <div class="ac-game-settings-item">
                <input type="password" placeholder="密码">
            </div>
        </div>
        <div class="ac-game-settings-submit">
            <div class="ac-game-settings-item">
                <input type="button" value="登录">
            </div>
        </div>
        <div class="ac-game-settings-error-message">
        </div>
        <div class="ac-game-settings-option">
            注册
        </div>
        <br>
        <div class="ac-game-settings-quick-login">
            <div class="ac-game-settings-quick-login-acwing">
                <img width="30" src="https://app165.acapp.acwing.com.cn/static/image/settings/acwing_logo.png">
                <br>
                <div>
                    AcWing一键登录
                </div>
            </div>

        </div>
    </div>
    <div class="ac-game-settings-register">
        <div class="ac-game-settings-title">
            注册
        </div>
        <div class="ac-game-settings-username">
            <div class="ac-game-settings-item">
                <input type="text" placeholder="用户名">
            </div>
        </div>
        <div class="ac-game-settings-password ac-game-settings-password-first">
            <div class="ac-game-settings-item">
                <input type="password" placeholder="密码">
            </div>
        </div>
        <div class="ac-game-settings-password ac-game-settings-password-second">
            <div class="ac-game-settings-item">
                <input type="password" placeholder="确认密码">
            </div>
        </div>
        <div class="ac-game-settings-submit">
            <div class="ac-game-settings-item">
                <input type="button" value="注册">
            </div>
        </div>
        <div class="ac-game-settings-error-message">
        </div>
        <div class="ac-game-settings-option">
            登录
        </div>
        <br>
        <div class="ac-game-settings-quick-login">
            <div class="ac-game-settings-quick-login-acwing">
                <img width="30" src="https://app165.acapp.acwing.com.cn/static/image/settings/acwing_logo.png" >
                <div>
                    AcWing一键登录
                </div>
            </div>
            <br>

        </div>
    </div>
</div>
        `);
        //把登录界面加载到DOM树中
        // this.root.$ac_game.append(this.$settings);
        //找到登录窗口节点及其子树
        this.$login = this.$settings.find(".ac-game-settings-login");
        //找到登录窗口的输入用户名表单
        this.$login_username = this.$login.find(".ac-game-settings-username input");
        //找到登录窗口的输入密码表单
        this.$login_password = this.$login.find(".ac-game-settings-password input");
        //找到登录窗口的登录按钮
        this.$login_submit = this.$login.find(".ac-game-settings-submit>div>input");
        //显示错误信息
        this.$login_error_message = this.$login.find(".ac-game-settings-error-message");
        找到登录窗口的注册按钮
        this.$login_register = this.$login.find(".ac-game-settings-option");

        this.$login.hide();

        this.$register = this.$settings.find(".ac-game-settings-register");
        this.$register_username = this.$register.find(".ac-game-settings-username input");
        this.$register_password = this.$register.find(".ac-game-settings-password-first input");
        this.$register_password_confirm = this.$register.find(".ac-game-settings-password-second input");
        this.$register_submit = this.$register.find(".ac-game-settings-submit>div>input");
        this.$register_error_message = this.$register.find(".ac-game-settings-error-message");
        this.$register_login = this.$register.find(".ac-game-settings-option");

        this.$register.hide();

        this.root.$ac_game.append(this.$settings);

        this.start();
    

    /**
     * 在对象创建时执行的函数
     */
    start() 
        this.getinfo();
        this.add_listening_events();
    

    /**
     * 获得后端信息的函数
     */
    getinfo() 
        let outer = this;

        $.ajax(
            url: "https://app220.acapp.acwing.com.cn/settings/getinfo/",
            type: "GET",
            data: 
                platform: outer.platform,
            ,
            //得到后端参数后执行的函数
            success: function (resp) 
                console.log(resp);
                if (resp.result === "success") 
                    outer.username = resp.username;
                    outer.photo = resp.photo;
                    //登录界面隐藏
                    outer.hide();
                    //显示菜单界面
                    outer.root.menu.show();
                 else 
                    //获取信息失败(即用户未登录),则继续显示登录界面
                    outer.open_login();
                
            
        );
    

    /**
     * 打开登录界面
     */
    open_login() 
        this.$register.hide();
        this.$login.show();
    

    /**
     * 打开注册界面
     */
    open_register() 
        this.$login.hide();
        this.$register.show();
    

    /**
     * 隐藏注册/登录界面
     */
    hide() 
        this.$settings.hide();
    

    /**
     * 显示注册/登录界面
     */
    show() 
        this.$settings.show();
    

    /**
     * 鼠标点击后触发的函数
     */
    add_listening_events() 
        this.add_listening_events_login();
        this.add_listening_events_register();
    

    /**
     * 点击登录按钮后触发的函数
     */
    add_listening_events_login() 
        let outer = this;

        this.$login_register.click(function () 
            console.log("666")
            outer.open_register();
        );
        this.$login_submit.click(function () 
            outer.login_on_remote();
        );
    

    /**
     * 点击注册按钮后触发的函数
     */
    add_listening_events_register() 
        let outer = this;
        this.$register_login.click(function () 
            console.log('666')
            outer.open_login();
        );
        this.$register_submit.click(function () 
            outer.register_on_remote();
        );
    

    /**
     * 向后端发送填写的账号密码,验证并返回信息
     */
    login_on_remote()   // 在远程服务器上登录
        let outer = this;
        let username = this.$login_username.val();
        let password = this.$login_password.val();
        this.$login_error_message.empty();

        $.ajax(
            url: "https://app220.acapp.acwing.com.cn/settings/login/",
            type: "GET",
            data: 
                username: username,
                password: password,
            ,
            success: function (resp) 
                console.log(resp);
                if (resp.result === "success") 
                    location.reload();
                 else 
                    outer.$login_error_message.html(resp.result);
                
            
        );
    

    /**
     * 注册用户
     */
    register_on_remote()   // 在远程服务器上注册
        let outer = this;
        let username = this.$register_username.val();
        let password = this.$register_password.val();
        let password_confirm = this.$register_password_confirm.val();
        this.$register_error_message.empty();

        $.ajax(
            url: "https://app220.acapp.acwing.com.cn/settings/register/",
            type: "GET",
            data: 
                username: username,
                password: password,
                password_confirm: password_confirm,
            ,
            success: function (resp) 
                console.log(resp);
                if (resp.result === "success") 
                    location.reload();  // 刷新页面
                 else 
                    outer.$register_error_message.html(resp.result);
                
            
        );
    

    /**
     * 在远程服务器上登出
     * @returns boolean
     */
    logout_on_remote() 
        if (this.platform === "ACAPP") return false;

        $.ajax(
            url: "https://app165.acapp.acwing.com.cn/settings/logout/",
            type: "GET",
            success: function (resp) 
                console.log(resp);
                if (resp.result === "success") 
                    location.reload();
                
            
        );
    

view

背景知识

Django 用户认证(Auth)组件 | 菜鸟教程 (runoob.com)

Django中authenticate和login模块 - ccorz - 博客园 (cnblogs.com)

实现

登录

game/views/settings下创建login.py

from django.http import JsonResponse

from django.contrib.auth import authenticate, login


def signin(request):
    data = request.GET
    username = data.get('username')
    password = data.get('password')
    user = authenticate(username=username, password=password)
    if not user:
        return JsonResponse(
            'result': "用户名或密码不正确"
        )
    login(request, user)
    return JsonResponse(
        'result': "success"
    )

登出

game/views/settings下创建logout.py

from django.http import JsonResponse
from django.contrib.auth import logout

def signout(request):
    user = request.user
    if not user.is_authenticated:
        return JsonResponse(
            'result':'success',

        )
    logout(request)
    return JsonResponse(
        'result': 'success',
    )
注册

game/views/settings下创建register.py

from django.http import JsonResponse
from django.contrib.auth import login
from django.contrib.auth.models import User
from game.models.player.player import Player



def register(request):
    data = request.GET
    username = data.get("username", "").strip()
    password = data.get("password", "").strip()
    password_confirm = data.get("password_confirm", ""

以上是关于Django项目笔记——(用户系统的实现)的主要内容,如果未能解决你的问题,请参考以下文章

Django项目笔记——联机对战的实现

基于Django Web框架(Python)实现简单的学生管理系统 -------学习笔记

django项目 设置session 实现用户登入登出

Django: 项目实战从0开始---实现登录注册系统。

Django: 项目实战从0开始---实现登录注册系统。

Django: 项目实战从0开始---实现登录注册系统。