Django学习笔记-用户名密码登录

news2024/11/16 3:17:50

笔记内容转载自 AcWing 的 Django 框架课讲义,课程链接:AcWing Django 框架课。

CONTENTS

    • 1. 扩充Django数据库
    • 2. 实现获取用户信息
    • 3. 渲染登录与注册界面
    • 4. 实现登录与登出功能
    • 5. 实现注册功能
    • 6. 修改获取用户信息

1. 扩充Django数据库

首先我们先在 settings.py 中修改:DEBUG = True,否则如果服务器端的代码报错时前端不会显示报错详细信息。

Django 自带一个账号系统,在网址后面添加后缀 /admin 即可访问管理员界面,登录之前的超级管理员账号,进入管理员界面后其中的 Users 界面就是自带的账号系统。

每个用户的信息如下图所示:

在这里插入图片描述

其中可以填写每个用户的姓名和邮箱,Active 表示用户是否被封,不勾选即无法登录;Staff status 表示用户是否能进入到后台管理页面;Superuser status 表示用户是否具有超级管理员的权限。

这个自带的账号系统不能满足我们的需求,例如需要存储用户的头像,该数据库就需要进行扩充。

我们要在 djangoapp/game/models 目录下创建我们所需的表,即创建类似之前提到的 Users,我们在该目录中新建一个 player 目录,然后进入该目录,记得需要先创建一个 __init__.py 文件。

接着我们创建 player.py 用来存储 player 这个数据表的信息,创建类时需要继承基类 django.db.models.Model(开发时有个小 Tips,如果忘记一些关键字怎么写可以在项目根目录执行 python3 manage.py shell,进入 IPython 交互功能,然后输入代码即具有补全功能):

from django.db import models
from django.contrib.auth.models import User

# Player有两个关键字,user表示是和哪个User对应的,avatar表示头像
class Player(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)  # 当删除User时也将其关联的Player一块删掉
    avatar = models.URLField(max_length=256, blank=True)  # 头像用链接存

    def __str__(self):  # 显示每个Player的数据
        return str(self.user)

创建好数据表后如果希望让我们的数据表出现在管理员界面,需要将它注册到管理员页面,在 game 目录下可以看到一个 admin.py 文件,对其进行修改:

from django.contrib import admin
from game.models.player.player import Player  # 将表导进来

# Register your models here.

admin.site.register(Player)

每次对数据表的定义更新后都需要执行以下两句指令(在项目根目录):

python3 manage.py makemigrations
python3 manage.py migrate

然后我们重启一下项目:uwsgi --ini scripts/uwsgi.ini,即可看到新创建的表:

在这里插入图片描述

在右上角的 ADD PLAYER 选项中即可添加 Player:

在这里插入图片描述

从这个例子即可看出数据库中的 Table 对应 Django 中的 Class,Table 中的每一条数据就对应 Class 中的每一个对象。

2. 实现获取用户信息

假设我们将网页刷新后,Clinet 先向后台服务器(Server)发送一个请求获得当前玩家的信息 getinfo,后台一种是返回用户名和头像,还有一种是返回未登录,现在我们先默认每次都返回玩家的用户名和头像,每次写一个函数时需要写三个部分:views 表示调用数据库的逻辑、urls 表示路由、js 实现调用。

由于有多个前端,因此后端在接收请求的时候需要知道是哪个前端,需要对 AcGame 类进行修改,让其多传入一个参数,如果在 AcWing 打开该项目则会传入该参数:

export class AcGame {
    constructor(id, acwingos) {
        this.id = id;
        this.$ac_game = $('#' + id);  // jQuery通过id找对象的方式
        this.acwingos = acwingos;  // 通过AcWing打开时会传入此参数

        this.menu = new AcGameMenu(this);
        this.playground = new AcGamePlayground(this);

        this.start();
    }

    start() {
    }
}

进入 views 目录,我们将所有用户的信息全部放到 settings 目录中,在 settings 目录创建一个 getinfo.py 文件,内容如下:

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

def getinfo_acapp(request):
    player = Player.objects.all()[0]  # 先默认返回第一个玩家的信息
    return JsonResponse({
        'result': 'success',  # 查询结果
        'username': player.user.username,
        'avatar': player.avatar,
    })

def getinfo_web(request):
    player = Player.objects.all()[0]
    return JsonResponse({
        'result': 'success',
        'username': player.user.username,
        'avatar': player.avatar,
    })

def getinfo(request):
    platform = request.GET.get('platform')  # 是哪个平台发起的请求
    if platform == 'ACAPP':
        return getinfo_acapp(request)
    else:
        return getinfo_web(request)

然后进入 urls/settings 目录,修改 index.py 文件:

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

urlpatterns = [
    path('getinfo/', getinfo, name='settings_getinfo')
]

现在我们即可访问 https://<项目IP地址>/settings/getinfo/ 查看效果。

最后我们需要在游戏的菜单界面之前添加一个界面判断用户是否登录,先将 AcGameMenu 类在初始化操作中 hide,然后进入 /djangoapp/game/static/js/src/settings 目录中创建 zbase.js

class Settings {
    constructor(root) {
        this.root = root;
        this.platform = 'WEB';  // 默认为Web前端
        if (this.root.acwingos) this.platform = 'ACAPP';

        this.start();
    }

    start() {  // 在初始化时需要从服务器端获取用户信息
        this.getinfo();
    }

    register() {  // 打开注册界面
    }

    login() {  // 打开登录界面
    }

    getinfo() {
        let outer = this;
        $.ajax({
            url: 'https://app4007.acapp.acwing.com.cn/settings/getinfo/',  // 用AcWing部署
            // url: 'http://8.130.54.44:8000/settings/getinfo/',  // 用云服务器部署
            type: 'GET',
            data: {
                platform: outer.platform,
            },
            success: function(resp) {  // 调用成功的回调函数,返回的Json字典会传给resp
                console.log(resp);  // 控制台输出查看结果
                if (resp.result === 'success') {
                    outer.hide();
                    outer.root.menu.show();
                } else {  // 如果未登录则需要弹出登录界面
                    outer.login();
                }
            }
        });
    }

    hide() {
    }

    show() {
    }
}

然后在 AcGame 类中创建 Settings 对象:

export class AcGame {
    constructor(id, acwingos) {
        this.id = id;
        this.$ac_game = $('#' + id);  // jQuery通过id找对象的方式

        this.settings = new Settings(this);
        this.menu = new AcGameMenu(this);
        this.playground = new AcGamePlayground(this);

        this.acwingos = acwingos;

        this.start();
    }

    start() {
    }
}

此时访问网站即可看到控制台的输出信息:

在这里插入图片描述

此时项目的执行顺序为:创建 Settings 类的对象时先执行构造函数,接着会执行 start 中的 getinfo 函数,会向后端(https://app4007.acapp.acwing.com.cn/settings/getinfo/)发一个请求,然后路由会找到 views.settings.getinfo 文件中的 getinfo 函数,然后判断 platformWEB,最后通过 getinfo_web 返回用户名和用户头像到 resp 中。

现在我们来判断用户是否登录,修改 views/settings 目录中的 getinfo.py

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

def getinfo_acapp(request):
    ...

def getinfo_web(request):
    user = request.user
    if not user.is_authenticated:
        return JsonResponse({
            'result': 'not login',
        })
    else:
        player = Player.objects.all()[0]
        return JsonResponse({
            'result': 'success',
            'username': player.user.username,
            'avatar': player.avatar,
        })

def getinfo(request):
    ...

然后我们需要将用户的信息存下来,将头像渲染到小球里,首先在 js/src/settings 目录中修改 zbase.js

class Settings {
    constructor(root) {
        ...
        this.username = '';  // 初始用户信息为空
        this.avatar = '';

        this.start();
    }

    start() {  // 在初始化时需要从服务器端获取用户信息
        this.getinfo();
    }

    register() {  // 打开注册界面
    }

    login() {  // 打开登录界面
    }

    getinfo() {
        let outer = this;
        $.ajax({
            url: 'https://app4007.acapp.acwing.com.cn/settings/getinfo/',  // 用AcWing部署
            // url: 'http://8.130.54.44:8000/settings/getinfo/',  // 用云服务器部署
            type: 'GET',
            data: {
                platform: outer.platform,
            },
            success: function(resp) {  // 调用成功的回调函数,返回的Json字典会传给resp
                console.log(resp);  // 控制台输出查看结果
                if (resp.result === 'success') {
                    outer.username = resp.username;
                    outer.avatar = resp.avatar;
                    ...
                } else {  // 如果未登录则需要弹出登录界面
                    outer.login();
                }
            }
        });
    }

    hide() {
    }

    show() {
    }
}

然后在 Player 类中渲染用户的头像:

class Player extends AcGameObject {
    constructor(playground, x, y, radius, color, speed, is_me) {
        ...
        if (this.is_me) {  // 用户自己的头像从服务器端获取
            this.img = new Image();
            this.img.src = this.playground.root.settings.avatar;
        }
    }

    start() {
        ...
    }

    add_listening_events() {
        ...
    }

    // 计算两点之间的欧几里得距离
    get_dist(x1, y1, x2, y2) {
        ...
    }

    // 向(tx, ty)位置发射火球
    shoot_fireball(tx, ty) {
        ...
    }

    move_to(tx, ty) {
        ...
    }

    is_attacked(theta, damage) {  // 被攻击到
        ...
    }

    update() {
        ...
    }

    render() {
        if (this.is_me) {
            this.ctx.save();
            this.ctx.beginPath();
            this.ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
            this.ctx.stroke();
            this.ctx.clip();
            this.ctx.drawImage(this.img, this.x - this.radius, this.y - this.radius, this.radius * 2, this.radius * 2);
            this.ctx.restore();
        } else {
            this.ctx.beginPath();
            // 角度从0画到2PI,是否逆时针为false
            this.ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
            this.ctx.fillStyle = this.color;
            this.ctx.fill();
        }
    }
}

3. 渲染登录与注册界面

首先我们下载所需要的图标资源,进入 static/image/settings 目录执行以下指令:

wget https://cdn.acwing.com/media/article/image/2021/11/18/1_ea3d5e7448-logo64x64_2.png
mv 1_ea3d5e7448-logo64x64_2.png acwing_logo.png

然后完善 Settings 类渲染登录与注册界面并且实现两个界面的跳转功能:

class Settings {
    constructor(root) {
        this.root = root;
        this.platform = 'WEB';  // 默认为Web前端
        if (this.root.acwingos) this.platform = 'ACAPP';
        this.username = '';  // 初始用户信息为空
        this.avatar = '';

        this.$settings = $(`
            <div class='ac_game_settings'>
                <div class='ac_game_settings_login'>
                    <div class='ac_game_settings_title'>
                        Login
                    </div>
                    <div class='ac_game_settings_username'>
                        <div class='ac_game_settings_item'>
                            <input type='text' placeholder='Username'>
                        </div>
                    </div>
                    <div class='ac_game_settings_password'>
                        <div class='ac_game_settings_item'>
                            <input type='password' placeholder='Password'>
                        </div>
                    </div>
                    <div class='ac_game_settings_submit'>
                        <div class='ac_game_settings_item'>
                            <button>Login</button>
                        </div>
                    </div>
                    <div class='ac_game_settings_errormessage'>
                    </div>
                    <div class='ac_game_settings_option'>
                        Register
                    </div>
                    <br>  <!-- inline格式可能有bug,需要加一行回车 -->
                    <div class='ac_game_settings_acwingoption'>
                        <img width='30' src='https://app4007.acapp.acwing.com.cn/static/image/settings/acwing_logo.png'>
                        <br>
                        <div>AcWing Login</div>
                    </div>
                </div>
                <div class='ac_game_settings_register'>
                    <div class='ac_game_settings_title'>
                        Register
                    </div>
                    <div class='ac_game_settings_username'>
                        <div class='ac_game_settings_item'>
                            <input type='text' placeholder='Username'>
                        </div>
                    </div>
                    <div class='ac_game_settings_password ac_game_settings_password_first'>
                        <div class='ac_game_settings_item'>
                            <input type='password' placeholder='Password'>
                        </div>
                    </div>
                    <div class='ac_game_settings_password ac_game_settings_password_second'>
                        <div class='ac_game_settings_item'>
                            <input type='password' placeholder='Confirm Password'>
                        </div>
                    </div>
                    <div class='ac_game_settings_submit'>
                        <div class='ac_game_settings_item'>
                            <button>Register</button>
                        </div>
                    </div>
                    <div class='ac_game_settings_errormessage'>
                    </div>
                    <div class='ac_game_settings_option'>
                        Login
                    </div>
                </div>
            </div>
        `);

        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 button');
        this.$login_errormessage = this.$login.find('.ac_game_settings_errormessage');
        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_confirm_password = this.$register.find('.ac_game_settings_password_second input');
        this.$register_submit = this.$register.find('.ac_game_settings_submit button');
        this.$register_errormessage = this.$register.find('.ac_game_settings_errormessage');
        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();
    }

    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() {
            outer.register();
        });
    }

    add_listening_events_register() {
        let outer = this;
        this.$register_login.click(function() {
            outer.login();
        });
    }

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

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

    getinfo() {
        let outer = this;
        $.ajax({
            url: 'https://app4007.acapp.acwing.com.cn/settings/getinfo/',  // 用AcWing部署
            // url: 'http://8.130.54.44:8000/settings/getinfo/',  // 用云服务器部署
            type: 'GET',
            data: {
                platform: outer.platform,
            },
            success: function(resp) {  // 调用成功的回调函数,返回的Json字典会传给resp
                console.log(resp);  // 控制台输出查看结果
                if (resp.result === 'success') {
                    outer.username = resp.username;
                    outer.avatar = resp.avatar;
                    outer.hide();
                    outer.root.menu.show();
                } else {  // 如果未登录则需要弹出登录界面
                    outer.login();
                }
            }
        });
    }

    hide() {
        this.$settings.hide();
    }

    show() {
        this.$settings.show();
    }
}

game.css 内容如下:

.ac_game_menu {
    width: 100%;
    height: 100%;
    background-image: url('/static/image/menu/background.png');  /* 注意不用带公网IP */
    background-size: 100% 100%;
    user-select: none;
}

.ac_game_menu_btgroup {
    width: 20vw;
    position: relative;
    top: 30%;
    left: 20%;
}

.ac_game_menu_btgroup_bt {
    height: 7vh;
    width: 15vw;
    color: white;
    font-size: 3vh;
    line-height: 7vh;
    font-style: italic;
    cursor: pointer;
    text-align: center;
    background-color: rgba(39, 21, 28, 0.6);
    border-radius: 10px;
    letter-spacing: 0.5vw;
}

.ac_game_menu_btgroup_bt:hover {
    transform: scale(1.2);
    transition: 100ms;
}

.ac_game_playground {
    height: 100%;
    width: 100%;
    user-select: none;
}

.ac_game_settings {
    width: 100%;
    height: 100%;
    background-image: url('/static/image/menu/background.png');
    background-size: 100% 100%;
    user-select: none;
}

.ac_game_settings_login {
    height: 41vh;
    width: 20vw;
    position: relative;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background-color: rgba(0, 0, 0, 0.7);
    border-radius: 5px;
}

.ac_game_settings_register {
    height: 39vh;
    width: 20vw;
    position: relative;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background-color: rgba(0, 0, 0, 0.7);
    border-radius: 5px;
}

.ac_game_settings_title {
    color: white;
    font-size: 3.5vh;
    text-align: center;
    height: 7vh;
    line-height: 7vh;
}

.ac_game_settings_username {
    display: block;
    height: 7vh;
}

.ac_game_settings_password {
    display: block;
    height: 7vh;
}

.ac_game_settings_submit {
    display: block;
    height: 7vh;
}

.ac_game_settings_errormessage {
    color: red;
    font-size: 1.5vh;
    display: inline;
    float: left;
    padding-left: 1vw;
}

.ac_game_settings_option {
    color: white;
    font-size: 1.5vh;
    display: inline;
    float: right;
    padding-right: 1vw;
    cursor: pointer;
}

.ac_game_settings_acwingoption {
    display: block;
    height: 8vh;
}

.ac_game_settings_acwingoption > img {
    display: block;
    position: relative;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    cursor: pointer;
}

.ac_game_settings_acwingoption > div {
    display: block;
    color: white;
    font-size: 1.2vh;
    text-align: center;
    padding-top: 1vh;
}

.ac_game_settings_item {
    width: 100%;
    height: 100%;
}

.ac_game_settings_item > input {
    width: 90%;
    line-height: 3vh;
    position: relative;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

.ac_game_settings_item > button {
    color: black;
    width: 30%;
    line-height: 3vh;
    font-size: 2vh;
    position: relative;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background-color: rgb(199, 237, 204);
    border-radius: 7px;
    cursor: pointer;
}

4. 实现登录与登出功能

实现登录与登出功能我们同样要编写 viewsurls 以及 js 文件,首先在 game/views/settings 目录下创建 login.py 文件:

from django.contrib.auth import authenticate, login
from django.http import JsonResponse

def mylogin(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/urls/settings 目录修改 index.py

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

urlpatterns = [
    path('getinfo/', getinfo, name='settings_getinfo'),
    path('login/', mylogin, name='settings_login'),
]

此时重启一下项目后访问 https://<公网IP>/settings/login/ 即可看到返回结果。

现在我们实现一下登出函数,在 game/views/settings 目录下创建 logout.py 文件:

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

def mylogout(request):
    user = request.user
    if not user.is_authenticated:
        return JsonResponse({
            'result': 'success',
        })
    logout(request)
    return JsonResponse({
        'result': 'success',
    })

然后进入 game/urls/settings 目录修改 index.py

from django.urls import path
from game.views.settings.getinfo import getinfo
from game.views.settings.login import mylogin
from game.views.settings.logout import mylogout

urlpatterns = [
    path('getinfo/', getinfo, name='settings_getinfo'),
    path('login/', mylogin, name='settings_login'),
    path('logout/', mylogout, name='settings_logout'),
]

此时重启一下项目后在登录状态下访问 https://<公网IP>/settings/logout/ 即可登出。

然后我们在 Settings 类中实现登录登出:

class Settings {
    constructor(root) {
        ...
    }

    start() {  // 在初始化时需要从服务器端获取用户信息
        ...
    }

    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() {
            outer.register();
        });
        this.$login_submit.click(function() {
            outer.login_on_remote();
        });
    }

    add_listening_events_register() {
        let outer = this;
        this.$register_login.click(function() {
            outer.login();
        });
    }

    login_on_remote() {  // 在远程服务器上登录
        let outer = this;
        let username = this.$login_username.val();
        let password = this.$login_password.val();
        this.$login_errormessage.empty();  // 先清空报错信息

        $.ajax({
            url: 'https://app4007.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_errormessage.html(resp.result);  // 显示报错信息
                }
            }
        });
    }

    register_on_remote() {  // 在远程服务器上注册
    }

    logout_on_remote() {  // 在远程服务器上登出
        if (this.platform === 'ACAPP') return false;  // AcApp应该是直接关闭窗口退出

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

    register() {  // 打开注册界面
        ...
    }

    login() {  // 打开登录界面
        ...
    }

    getinfo() {
        ...
    }

    hide() {
        ...
    }

    show() {
        ...
    }
}

其中登出函数 logout_on_remote 需要在 AcGameMenu 类中调用:

class AcGameMenu {
    constructor(root) {  // root用来传AcGame对象
        this.root = root;
        this.$menu = $(`
            <div class='ac_game_menu'>
                <div class='ac_game_menu_btgroup'>
                    ...
                    <div class='ac_game_menu_btgroup_bt ac_game_menu_btgroup_bt_settings'>
                        登出
                    </div>
                </div>
            </div>
        `);
        ...
        this.$settings = this.$menu.find('.ac_game_menu_btgroup_bt_settings');

        this.start();
    }

    start() {
        ...
    }

    // 给按钮绑定监听函数
    add_listening_events() {
        let outer = this;
        ...
        this.$settings.click(function() {
            outer.root.settings.logout_on_remote();
        });
    }

    // 显示menu界面
    show() {
        ...
    }

    // 关闭menu界面
    hide() {
        ...
    }
}

5. 实现注册功能

首先在 game/views/settings 目录下创建 register.py 文件:

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

def register(request):
    data = request.GET
    username = data.get('username', '').strip()  # 如果没有的话返回空,且过滤掉空格
    password = data.get('password', '').strip()
    confirm_password = data.get('confirm_password', '').strip()
    if not username or not password:  # 用户名或密码为空
        return JsonResponse({
            'result': 'Username or password can\'t be empty!',
        })
    elif password != confirm_password:  # 两次密码不一致
        return JsonResponse({
            'result': 'Password inconsistency!'
        })
    elif User.objects.filter(username=username).exists():  # 用户名已存在
        return JsonResponse({
            'result': 'Username has existed!'
        })
    user = User(username=username)
    user.set_password(password)
    user.save()
    Player.objects.create(user=user, avatar='https://cdn.acwing.com/media/article/image/2021/11/18/1_ea3d5e7448-logo64x64_2.png')
    login(request, user)
    return JsonResponse({
        'result': 'success',
    })

然后进入 game/urls/settings 目录修改 index.py

from django.urls import path
from game.views.settings.getinfo import getinfo
from game.views.settings.login import mylogin
from game.views.settings.logout import mylogout
from game.views.settings.register import register

urlpatterns = [
    path('getinfo/', getinfo, name='settings_getinfo'),
    path('login/', mylogin, name='settings_login'),
    path('logout/', mylogout, name='settings_logout'),
    path('register/', register, name='settings_register'),
]

此时重启一下项目后访问 https://<公网IP>/settings/register/ 即可看到返回结果。

最后修改前端 Settings 类:

class Settings {
    constructor(root) {
        ...
    }

    start() {  // 在初始化时需要从服务器端获取用户信息
        ...
    }

    add_listening_events() {  // 绑定监听函数
        ...
    }

    add_listening_events_login() {
        ...
    }

    add_listening_events_register() {
        let outer = this;
        this.$register_login.click(function() {
            outer.login();
        });
        this.$register_submit.click(function() {
            outer.register_on_remote();
        });
    }

    login_on_remote() {  // 在远程服务器上登录
        ...
    }

    register_on_remote() {  // 在远程服务器上注册
        let outer = this;
        let username = this.$register_username.val();
        let password = this.$register_password.val();
        let confirm_password = this.$register_confirm_password.val();
        this.$register_errormessage.empty();

        $.ajax({
            url: 'https://app4007.acapp.acwing.com.cn/settings/register/',
            type: 'GET',
            data: {
                username: username,
                password: password,
                confirm_password: confirm_password,
            },
            success: function(resp) {
                console.log(resp);
                if (resp.result === 'success') {
                    location.reload();
                } else {
                    outer.$register_errormessage.html(resp.result);
                }
            }
        });
    }

    logout_on_remote() {  // 在远程服务器上登出
        ...
    }

    register() {  // 打开注册界面
        ...
    }

    login() {  // 打开登录界面
        ...
    }

    getinfo() {
        ...
    }

    hide() {
        ...
    }

    show() {
        ...
    }
}

6. 修改获取用户信息

之前我们是默认返回第一个用户的信息,我们对 game/views/settings 目录下的 getinfo.py 文件进行修改:

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

def getinfo_acapp(request):
    ...

def getinfo_web(request):
    user = request.user
    if not user.is_authenticated:
        return JsonResponse({
            'result': 'not login',
        })
    else:
        player = Player.objects.get(user=user)  # 获取user的player信息
        return JsonResponse({
            'result': 'success',
            'username': player.user.username,
            'avatar': player.avatar,
        })

def getinfo(request):
    platform = request.GET.get('platform')  # 是哪个平台发起的请求
    if platform == 'ACAPP':
        return getinfo_acapp(request)
    # elif platform == 'WEB':
    else:
        return getinfo_web(request)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/693036.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaWeb学习路线(7)——文件上传

一、概念 &#xff08;一&#xff09;文件上传概念&#xff1a; 指将本地的图片、视频、音频等文件上传到服务器&#xff0c;供其他用户浏览或下载的过程。 &#xff08;二&#xff09;前端文件上传三元素 method“post”&#xff08;form&#xff09;enctype“multipart/for…

四、Bean 的作用域,Bean 的自动装配以及通过注解实现 Bean 的自动装配

文章目录 一、Bean 的作用域二、Bean 的自动装配三、通过注解实现 Bean 的自动装配 一、Bean 的作用域 Spring 官网 Bean 的作用域讲解 单例(Singleton)作用域&#xff1a;在这种作用域下&#xff0c;容器只会创建一个Bean实例对象&#xff0c;无论该Bean被注入到多少个其它B…

Unity使用MySQL

效果&#xff1a; 问题记录&#xff1a; unity mysql “The given key ‘utf8mb4‘ was not present in the dictionary” – 我这里数据库字符集没有utf8&#xff0c;改选utf8mb4 – 这个改了&#xff0c;那么MySQL配置文件也得改了。如下&#xff1a; – 然后还报错&…

字符、字符集、编码

一、基本概念 在计算机中&#xff0c;所有的内容都是以二进制数据存储的&#xff0c;而我们在屏幕上看到的字和符号以及看不到的字符都是二进制数据转换后的结果。将字符按照某种规则转成对应的二进制数据&#xff0c;这个过程称为编码&#xff1b;而相对应的&#xff0c;将二…

Azure获取linux服务器磁盘和控制台disk的对应关系

从Azure控制台上删除/卸载服务器上不用的磁盘时&#xff0c;需要确定服务器上磁盘和控制台上显示的磁盘的对应关系。以免当有多块磁盘时&#xff0c;卸载了错误的磁盘&#xff0c;引起生产事故。 通过LUN确定磁盘对应关系 什么是LUN&#xff1f; 逻辑单元号 (LUN) 是用于标识…

Vue之事件处理(v-on)

文章目录 前言一、v-on基本使用二、使用举例1.传参和不传参使用2.$event占位代表事件对象3.函数用箭头函数时this作用域4.正常未用箭头函数的this指向&#xff08;与未用箭头函数作比较&#xff09; 总结 前言 v-on&#xff1a;事件绑定 一、v-on基本使用 格式&#xff1a;&l…

Linux安装ElasticSearch和Kibana

es官网下载地址&#xff1a;https://www.elastic.co/cn/downloads/past-releases#elasticsearch 可以去官网下载包然后放到服务器 也可以使用wget进行下载安装 如果使用wget方式下载的话需要先安装 安装wget yum install -y wgetwget下载es&#xff1a;wget https://artifacts…

B+树的设计步骤

1.节点的结构&#xff08;如下图&#xff09; &#xff08;1&#xff09;键值对--key是标识&#xff1b;value是存储的具体数据 &#xff08;2&#xff09;节点的子节点--存储的是具体的子节点 &#xff08;3&#xff09;节点的后节点--标记后一个节点 &#xff08;4&#xff0…

JSP实现自定义标签【上】

目录 一、基础概念 1、标签语言的形式或结构 2、分类 二、自定义标签的开发及步骤 三、标签生命周期 1、返回值 四、案例 1、if 2、out 一、基础概念 JSP自定义标签是一种扩展JSP标记语言的方法。通过自定义标签&#xff0c;我们可以将自定义功能封装在一个独立的标签…

# rust abc(6): 字符串的简单使用

文章目录 1. 目的2. 数据类型2.1 str 类型2.2 标准库 String 类型 3. 常用 API3.1 len() 方法3.2 is_empty() 方法3.3 starts_with() 方法3.4 find() 方法 4. References 1. 目的 学习 Rust 语言中的字符串&#xff0c; 包括数据类型&#xff0c; 常用 API。 2. 数据类型 Ru…

新手入门:从零搭建vue3+webpack实战项目模板

搭建一个 vue3 webpack5 element-plus 基本模板 &#xff08;vue3 webpack5 从零配置项目&#xff09;。 本项目结构可以作为实战项目的基本结构搭建学习&#xff0c;作为刚学习完vue还没有实战项目经验的小伙伴练习比较合适。 项目地址&#xff1a; GitHub&#xff1a;ht…

如何将手写笔记转换成电子版格式?

记笔记是一种非常有效的学习方法。它不仅可以帮助我们加深对所学内容的理解&#xff0c;还能让我们收集更多有用的信息&#xff0c;以方便后续的查看和复习。不过&#xff0c;用传统的纸质笔记本记录笔记存在一定的弊端&#xff0c;比如说不易保存、不易携带等等。所以&#xf…

Mac下的java.io.FileNotFoundException: ~/Desktop/a.sql (No such file or directory)

【问题】&#xff1a; 今天在运行一个文件读取的Demo时&#xff0c;报如下错误: java.io.FileNotFoundException: ~/Desktop/a.sql (No such file or directory)如下图所示 &#xff1a; 可是这个文件命名可以通过终端窗口访问到啊&#xff1f; 【解决方案】&#xff…

STM32外设系列—HC-SR04(超声波)

文章目录 一、超声波测距基本原理二、超声波传感器简介三、HC-SR04测距实现思路四、超声波测距程序实现4.1 HC-SR04初始化程序4.3 TIM开关程序4.4 获取定时时间4.5 计算测量距离4.6 宏定义 五、应用实例六、拓展应用 一、超声波测距基本原理 超声波测距的原理非常简单&#xf…

高压放大器在压电陶瓷驱动器中的应用

高压放大器是一种将低电压信号放大成高电压信号的电子设备。它广泛运用于各种领域&#xff0c;如医疗、工业、军事以及科学研究。压电陶瓷驱动器是一种利用压电效应来驱动机械运动的装置。这两种设备经常被用于控制和操作许多不同类型的系统。 压电陶瓷是一种能够将电能转化为机…

监控摄像头的像素200万,400万,800万都是什么意思,200万像素、400万像素、800万像素是如何换算出来的?

一、像素 像素&#xff08;Pixel&#xff09;是用来表示图像分辨率的单位&#xff0c;数字越大&#xff0c;表示图像中的细节可以更精细地展现。当我们谈论监控摄像头的像素时&#xff0c;通常指的是摄像头图像传感器上的像素数量。像素的数量可以通过传感器上的横向像素数乘以…

win如何使用OpenSSL生成自签名证书,使 http 升级为 https

win如何使用OpenSSL生成自签名证书&#xff0c;使 http 升级为 https 前言 HTTPS其实就是HTTP over SSL&#xff0c;也就是让HTTP连接建立在SSL安全连接之上。 创建自签名证书需要安装openssl。参考本文安装OpenSSL部分。 使用OpenSSL生成自签名证书的步骤&#xff1a;参考…

python spider 爬虫 之 Selenium 系列 (-) Selenium

京东的 seckill 秒杀 专区 用 urllib 是获取不到的 回顾一下urllib 爬虫 # urllib 爬虫 from urllib import request headers {} url # 请求定制 req request(urlurl, headers headers) # 模拟请求 response request(req) content response.read().decode(utf-…

windows下安装Visual Studio + CMake+OpenCV + OpenCV contrib

目录 1 安装visual studio 2 安装CMake 3 OpenCV源码安装 3.1 OpenCV源码下载 3.2 OpenCV contrib源码下载 3.3 安装OpenCV 3.4 安装OpenCV-crontrib 3.5 VS生成代码 4 环境配置 最近在研究windows系统上部署安装目标检测算法&#xff0c;需要用到OpenCV软件&#xff…

智能指针+拷贝构造+vector容器+多态引起的bug

今天在调试一段代码的时候&#xff0c;VC编译提示&#xff1a; error C2280: “T485CommCtrlPara::T485CommCtrlPara(const T485CommCtrlPara &)”: 尝试引用已删除的函数 函数执行部分如下&#xff1a; 看意思是这个pComm485Pro已经消亡了&#xff0c;后续push_back到ve…