返回顶部

blog开发之注册功能

注册功能

先看代码:

modelform:

from django import forms
from django.core.exceptions import ValidationError
from blog import models

class UserModelForm(forms.ModelForm):
    confirm_password = forms.CharField(label='确认密码')

    class Meta:
        model = models.UserInfo
        fields = ['username', 'password', 'confirm_password','email']

    def __init__(self, *args, **kwargs):
        super(UserModelForm, self).__init__(*args, **kwargs)
        for name, field in self.fields.items(): 
            field.widget.attrs = {'class':'form-control'}

    def clean_username(self):
        val = self.cleaned_data.get('username')
        obj = models.UserInfo.objects.filter(username=val).first()
        if not obj:
            return val
        raise ValidationError('用户名已经存在!')

    def clean_email(self):
        val = self.cleaned_data.get('email')

        if not val:
            raise ValidationError('邮箱不能为空!')
        return val

    def clean(self):
        pwd = self.cleaned_data.get('password')
        re_pwd = self.cleaned_data.get('confirm_password')
        if re_pwd and pwd:
            if re_pwd != pwd:
                raise ValidationError('两次密码输入不一致!')
            return self.cleaned_data
        return self.cleaned_data
        

1.通过重写init方法,给每一个字段加上统一的字段。

2.局部钩子需要返回原数据,全局钩子记得返回cleaned_data。

 

视图函数:

def register(request):
    if request.method == 'GET':
        form = UserModelForm()
        return render(request, 'blog/register.html', {'form': form})
    form = UserModelForm(data=request.POST)
    if form.is_valid():
        clean_data = form.cleaned_data
        clean_data.pop('confirm_password')
        avatar = request.FILES.get('avatarimg')
        if avatar:
            clean_data['avatar'] = avatar
        models.UserInfo.objects.create_user(**clean_data)
        return redirect(reverse('blog:login'))
    all_error = form.errors.get('__all__')
    if all_error:
        all_error = form.errors.get('__all__')
    return render(request, 'blog/register.html', {'form': form, 'all_error': all_error})

注意:

1.cleaned_data里面存的是你定义的modelform的字段,把不需要的字段confirm_password弹出后,创建用户的时候直接就可以**clean_data了。

2.全局错误,需要在视图函数中先判断,获取到后再返回给页面。

注册页面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/blog/bs/css/bootstrap.css">
    <style>
        #avatar_img {
            margin-left: 20px;
        }

        #avatar {
            display: none;
        }
    </style>
</head>
<body>
<h3>注册页面</h3>
<div class="container">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <form method="post" enctype="multipart/form-data">
                {% csrf_token %}
                {% for item in form %}
                    <div class="form-group">
                        <label for="{{ item.auto_id }}">{{ item.label }}</label>
                        {{ item }} {{ item.errors.0 }}
                    </div>
                {% endfor %}
                <div class="form-group">
                    <label for="avatar">
                        头像
                        <img src="/static/blog/img/default.png" width="56" height="56" alt="" id="avatar_img">
                    </label>
                    <input type="file" id="avatar" name="avatarimg">
                </div>
                <input type="submit" class="btn btn-success" value="提交" id="register_btn">{% if all_error %}
                <span class="error">{{ all_error.0 }}</span>
            {% endif %}
            </form>

        </div>
    </div>
</div>

<script src="/static/jquery-3.3.1.js"></script>
<script>
    $("#avatar").change(function () {
        let file_obj = $(this)[0].files[0];
        let reader = new FileReader();
        reader.readAsDataURL(file_obj);  // 异步操作,不会等待文件读取完毕,直接下一步
        reader.onload = function () {
            $("#avatar_img").attr("src", reader.result)
        };

    });


    $('.error').text('{{ all_error.0 }}').css({"color": "red", "margin": "10px"});
    setTimeout(function () {
        $('.error').text('')
    }, 1500);


</script>
</body>
</html>

注意:

1.局部错误(每一个字段的错误),用{{ item.errors.0 }} 来显示。全局错误,通过{{ all_error.0 }} 来获取。

2.头像动态展示:通过一个FileReader()对象来读取图片,为了正确显示,使用onload来等待图片加载完毕后,再修改src属性来显示图片。

 

posted @ 2020-10-08 20:13  muguangrui  阅读(103)  评论(0编辑  收藏  举报