Django-登录

任务

计划完成一款帮助学习计划管理的小程序,实现其中的登录功能。

难点:由于采用蓝鲸的开发平台,其中的登录模块已经经过设定,需要进行重建。

过程

Model

首先定义基于Django的用户模块User之上的应用基础用户模块baseUser,数据表如下:

from django.contrib.auth.models import User
#from blueapps.account.models import User

但在蓝鲸SaaS平台中已经被改写,因此引入被改写后的User

class baseUser(models.Model):
    user=models.OneToOneField(User,models.CASCADE)
    phone=models.CharField(max_length=50,null=True,blank=True)
    email=models.CharField(max_length=50,null=True,blank=True)
    avatar=models.CharField(max_length=50,null=True,blank=True)

其中user信息基于用户模块,可以完成密码的加密,另外加入电话、邮箱与头像信息。

View

用户登录主要包括注册与登录两部分,首页是登录界面,可以链接到注册界面,相反亦然:

这里主要利用文章Django中的Form组件中的方法,可以快捷进行数据交互,组件的特性有:

  • 生成页面的HTML标签及样式
  • 对用户提交的数据进行校验
  • 自动生成错误信息
  • 保留上次输入信息

一个表单实例

利用CBV(Class Base View)形式进行视图函数书写

url.py

	url(r'^form$',views.Form.as_view()),

view.py

继承Form组件
from django import forms
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
class TestForm(forms.Form):
    # 用户名
    username = forms.CharField(
        min_length=6,#设置最小长度
        max_length=12,#设置最大长度
        label="用户名",#设置标签名
        #错误信息提示设置
        error_messages={
            "min_length": "用户名不能少于6位",
            "max_length":'用户名不能超过12位',
            "required": "用户名不能为空"
        },
        #插件设置
        widget=forms.widgets.TextInput(
            attrs={"class": "form-control"}# 给生成的标签添加属性
        )
    )
类视图
class Form(views.View):
    def get(self,request):
        #实例化TestForm
        test_obj=TestForm()
        return render(request, 'mechat/form.html', {'test_obj': test_obj})
    def post(self,request):
        # 前后端交互信息
        res = {'code': 0}
        # 实例化form类,将前端得到的数据提交到实例中
        test_obj = TestForm(request.POST)
        # 利用form内置方法校验前端得到的数据
        if test_obj.is_valid():
            res['code']=1
            res['msg']='success'
        else:
            res['msg']=test_obj.errors
        return JsonResponse(res)

form.html

<body>
    <body>
        <form>
            {% csrf_token %}
            {% for field in test_obj %}
                <div class="form-group">
                    <label class="letleft" for="field.id_for_label">{{ field.label }}</label>
                    {{ field }}
                    <span class="err-msg"></span>
                </div>
            {% endfor %}
        </form>
        <button onclick="send_ajax()">提交</button>
    </body>
JS
<script>
    function send_ajax(){
    let formdata = new FormData();
            formdata.append('username', $('#id_username').val());
            //设置csrftoken来防止跨站csrf攻击
            formdata.append('csrfmiddlewaretoken', $("[name='csrfmiddlewaretoken']").val());
        $.ajax({
            url: '{{SITE_URL}}mechat/form',
            type: 'POST',
             processData: false,   //不让jQuery处理我的obj
            contentType: false,  // 不让jQuery设置请求的内容类型
            data: formdata,
            success: function(res){
                console.log(res)
                console.log(res['msg'])
                if (res.code === 0) {
                        $.each(res.msg, function (k, v) {
                            //添加错误提示样式
                            $("#id_" + k).next().text(v[[0]]).parent().addClass('err-msg')
                        })
                    }
            }
        });
    }
</script>

所做处理

  • 将蓝鲸SaaS的登录中间件注释掉
  • 增加验证backends的方式(默认方式)
AUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.ModelBackend',)

通过比对登录用户名与密码是否存在于数据库中,利用登录验证模块的authenticate()进行鉴权登录

登录函数

def login(request):
    if request.method =='POST':
        # post请求接受验证数据
        username = request.POST.get('username')
        password = request.POST.get('password')
        if(username==''):
            return JsonResponse({"result":False,"message":'请输入用户名'})
        elif(password==''):
            return JsonResponse({"result":False,"message":'请输入密码'})
        user=auth.authenticate(username=username,password=password)
        if user is not None and user.is_active:
            # 验证通过进行登录
            auth.login(request,user) # session cookie
            request.session['username'] = username
            return JsonResponse({"result":True,"message":'登录成功'})

知识点

Python中的*args和**kwargs- 百晓生的文章 – 知乎

  • args 是 arguments 的缩写,表示位置参数;
  • kwargs 是 keyword arguments 的缩写,表示关键字参数。
  • 这是 Python 中可变参数的两种形式,并且 *args 必须放在 **kwargs 的前面,因为位置参数在关键字参数的前面。
def test_kwargs(first, *args, **kwargs):
   print('Required argument: ', first)
   print(type(kwargs))
   for v in args:
      print ('Optional argument (args): ', v)
   for k, v in kwargs.items():
      print ('Optional argument %s (kwargs): %s' % (k, v))
test_kwargs(1, 2, 3, 4, k1=5, k2=6)

输出结果

Required argument: 1
<class 'dict'>
Optional argument (args): 2
Optional argument (args): 3
Optional argument (args): 4
Optional argument k1 (kwargs): 5
Optional argument k2 (kwargs): 6

参考文章

Leave a comment

Your email address will not be published. Required fields are marked *