1

day 77 基于form组件的注册功能

Form 表单 py文件

 

from django  import  forms

#定义一个form类注册用
class RegForm (forms.Form):
    username =forms.CharField(
        max_length=16,
        label='用户名',
        error_messages={
            " max_length":"用户名长度最长为16位",
            'required':'用户名不能为空',
        },
        widget=forms.widgets.TextInput(
            attrs={'class': 'form-control'},
        )
    )

    password =forms.CharField(
        min_length=6,
        label='密码',
        widget=forms.widgets.PasswordInput(
            attrs={"class": "form-control"},
            render_value=True,
        ),
        error_messages = {
            "min_length": "密码至少要6位!",
            "required": "密码不能为空",
        }
    )
    re_password= forms.CharField(
        min_length=6,
        label='密码',
        widget=forms.widgets.PasswordInput(
            attrs={ 'class': 'form-control'},
            render_value=True,
        ),
        error_messages= {
            'min_length':'密码至少要6位',
            'required':'密码不能为空',
            }
    )
    email =forms.EmailField(
        label='邮箱',
        widget=forms.widgets.EmailInput(
            attrs={'class':'form-control'},
        ),
        error_messages= {
            'invalid': '邮箱格式不正确!',
            'required':'邮箱不能为空',
        }
     )

  

settings文件

 

"""
Django settings for day77 project.

Generated by 'django-admin startproject' using Django 1.11.12.

For more information on this file, see
https://docs.djangoproject.com/en/1.11/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.11/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '@qbulznqai1k%twz$(m)76#ztkt6%^+k2airzl5-pt@lu2v)oz'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01.apps.App01Config',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'day77.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')]
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'day77.wsgi.application'


# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases

DATABASES = {
    # 'default': {
    #     'ENGINE': 'django.db.backends.sqlite3',
    #     'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    # },

    'default':{
        'ENGINE':'django.db.backends.mysql',
        'NAME':'day77',
        'USER':'root',
        'PASSWORD':'123456',
        'HOST':'127.0.0.1',
        'PORT':3306,

    }
}


# Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/

STATIC_URL = '/static/'
STATICFILES_DIRS=[
    os.path.join(BASE_DIR,'static')
]

# 告诉Djanog 项目用哪张表做认证
AUTH_USER_MODEL='app01.UserInfo'

  

 

modules文件 

 

from django.db import models

# Create your models here.
from django.contrib.auth.models import AbstractUser

class UserInfo(AbstractUser):
    '''
    用户表
    '''
    nid  =models.AutoField(primary_key=True)
    phone  =models.CharField(max_length=11,null=True,unique=True)
    avatar = models.FileField(upload_to='avatars/',default='avatars/default.png',verbose_name='头像')
    create_time =models.DateTimeField(auto_now_add=True)
    blog =models.OneToOneField(to='Blog',to_field='nid',null=True)
    def __str__(self):
        return self.username

class Blog(models.Model):
    '''
    博客信息
    '''
    nid =models.AutoField(primary_key=True)
    title =models.CharField(max_length=64)
    site =models.CharField(max_length=32,unique=True)
    theme =models.CharField(max_length=32)

    def __str__(self):
        return self.title
#

class  Category(models.Model):
    '''
    个人博客文章分类
    '''
    nid =models.AutoField(primary_key=True)
    title =models.CharField(max_length=32)#分类标题
    blog = models.ForeignKey(to ='Blog',to_field='nid')#外键关联博客,一个博客站点可以有多个分类

    def __str__(self):
        return self.title

class Tag(models.Model):
    ''''
    标签
    '''
    nid =models.AutoField(primary_key=True)
    title =models.CharField(max_length=32)
    blog =models.ForeignKey(to='Blog',to_field='nid') #所属博客

    def __str__(self):
        return self.title

class Article(models.Model):
    '''
    文章
    '''
    nid =models.AutoField(primary_key=True)
    title = models.CharField(max_length=50) #文章标题描述
    desc =models.CharField(max_length=255) #文章描述
    create_time =models.DateTimeField()#创建时间

    category = models.ForeignKey(to ='Category',to_field='nid',null=True)
    user = models.ForeignKey(to='UserInfo',to_field='nid')
    tags =models.ManyToManyField( # 中介模型
        to ='Tag',
        through='Article2Tag',
        through_fields=('article','tag')#注意顺序

    )

    def __str__(self):
        return self.title

class ArticleDetail(models.Model):
    '''
    文章详情
    '''
    nid =models.AutoField(primary_key=True)
    content = models.TextField()
    article =models.OneToOneField(to ='Article',to_field='nid')

class Article2Tag(models.Model):
    '''
    文章和标签的多对多关系表
    '''
    nid =models.AutoField(primary_key=True)
    article =models.ForeignKey(to='Article',to_field='nid')
    tag =models.ForeignKey(to ='Tag',to_field='nid')

    class Meta:
        unique_together = (('article','tag'),)

class ArticleUpDown(models.Model):
    '''
    点赞
    '''
    nid= models.AutoField(primary_key=True)
    user =models.ForeignKey(to ='UserInfo',null=True)
    article = models.BooleanField(default=True)

    class  Meta:
        unique_together = (('article','user'),)

class Comment(models.Model):
    '''
    评论表
    '''
    nid = models.AutoField(primary_key=True)
    article =models.ForeignKey(to ='Article',to_field='nid')
    user =models.ForeignKey(to ='UserInfo',to_field='nid')
    content =models.CharField(max_length=255)#评论内容
    create_time =models.DateTimeField(auto_now_add=True)
    parent_comment =models.ForeignKey('self',null=True)

    def __str__(self):
        return self.content

views文件 

 

from app01 import  form,models
from django.db import models
def reg(request):
    if request.method=='POST':
        ret={'status':0,'msg':''}
        form_obj =form.RegForm(request.POST)
        #帮我做校验
        if form_obj.is_valid():
            #校验通过,去数据库创建一个新的用户
            form_obj.cleaned_data.pop('re_password')
            avatar_img =request.FILES.get('avatar')
            models.UserInfo.objects.create_user(**form_obj.cleaned_data,avatar =avatar_img)
            ret['msg']= '/index/'
            return JsonResponse(ret)
以上代码代表注册成功的情况
以下代码是注册失败的代码 else: print(form_obj.errors) ret['status']=1 ret['msg']= form_obj.errors
       print(ret) return JsonResponse(form_obj.errors) # return render(request,'ret.html',{'form_obj': form_obj})
#生成一个form对象
form_obj = form.RegForm()
print(form_obj)
print("== "*120)
return render(request,'reg.html',{'form_obj': form_obj})

  输入 web地址 

 

 

 

 

 

前端代码 

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>欢迎注册</title>
<link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="/static/mystyle.css">
</head>
<body>

<div class="container">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<form novalidate autocomplete="off" action="/reg/" method="post" class="form-horizontal reg-form" enctype="multipart/form-data">
{% csrf_token %}

<div class="form-group">
<label for="{{ form_obj.username.id_for_label }}"
class="col-sm-2 control-label">{{ form_obj.username.label }}</label>
<div class="col-sm-8">
{{ form_obj.username }}
<span class="help-block">{{ form_obj.username.errors.0 }}</span>
</div>
</div>

<div class="form-group">
<label for="{{ form_obj.password.id_for_label }}"
class="col-sm-2 control-label">{{ form_obj.password.label }}</label>
<div class="col-sm-8">
{{ form_obj.password }}
<span class="help-block">{{ form_obj.password.errors.0 }}</span>
</div>
</div>

<div class="form-group">
<label for="{{ form_obj.re_password.id_for_label }}"
class="col-sm-2 control-label">{{ form_obj.re_password.label }}</label>
<div class="col-sm-8">
{{ form_obj.re_password }}
<span class="help-block">{{ form_obj.re_password.errors.0 }}</span>
</div>
</div>

<div class="form-group">
<label for="{{ form_obj.email.id_for_label }}"
class="col-sm-2 control-label">{{ form_obj.email.label }}</label>
<div class="col-sm-8">
{{ form_obj.email }}
<span class="help-block">{{ form_obj.email.errors.0 }}</span>
</div>
</div>

<div class="form-group">
<label
class="col-sm-2 control-label">头像</label>
<div class="col-sm-8">
<label for="id_avatar"><img id="avatar-img" src="/static/img/default.png" alt=""></label>
<input accept="image/*" type="file" name="avatar" id="id_avatar" style="display: none">
<span class="help-block"></span>
</div>
</div>

<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="button" class="btn btn-success" id="reg-submit">注册</button>
</div>
</div>
</form>
</div>
</div>
</div>


<script src="/static/jquery-3.3.1.js"></script>
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
<script>
// 找到头像的input标签绑定change事件
$("#id_avatar").change(function () {
// 1. 创建一个读取文件的对象
var fileReader = new FileReader();
// 取到当前选中的头像文件
// console.log(this.files[0]);
// 读取你选中的那个文件
fileReader.readAsDataURL(this.files[0]); // 读取文件是需要时间的
fileReader.onload = function () {
// 2. 等上一步读完文件之后才 把图片加载到img标签中
$("#avatar-img").attr("src", fileReader.result);
};
});
// AJAX提交注册的数据
$("#reg-submit").click(function () {
// 取到用户填写的注册数据,向后端发送AJAX请求
var formData = new FormData();
formData.append("username", $("#id_username").val());
formData.append("password", $("#id_password").val());
formData.append("re_password", $("#id_re_password").val());
formData.append("email", $("#id_email").val());
formData.append("avatar", $("#id_avatar")[0].files[0]);
formData.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val());

$.ajax({
url: "/reg/",
type: "post",
processData: false, // 告诉jQuery不要处理我的数据
contentType: false, // 告诉jQuery不要设置content类型
data: formData,
success:function (data) {
if (data.status){
// 有错误就展示错误
// console.log(data.msg);
// 将报错信息填写到页面上
$.each(data.msg, function (k,v) {
// console.log("id_"+k, v[0]);
// console.log($("#id_"+k));
$("#id_"+k).next("span").text(v[0]).parent().parent().addClass("has-error");
})

}else {
// 没有错误就跳转到指定页面
location.href = data.msg;
}
}
})
});

// 将所有的input框绑定获取焦点的事件,将所有的错误信息清空
$("form input").focus(function () {
$(this).next().text("").parent().parent().removeClass("has-error");
});

// 给username input框绑定一个失去焦点的事件,失去焦点之后就校验用户名是否已被注册
{#$("#id_username").blur(function () {#}
$("#id_username").on("input", function () {
// 取到用户填写的值
var username = $(this).val();
// 发请求
$.ajax({
url: "/check_username_exist/",
type: "get",
data: {"username": username},
success: function (data) {
if (data.status){
// 用户名已被注册
$("#id_username").next().text(data.msg).parent().parent().addClass("has-error");
}
}
})
})
</script>
</body>
</html>

 

密码输入错误的案例 

  

 

打印结果

 

传到前端的 代码 

 

 

 

登录 views

 

def logout(request):
    auth.logout(request)
    return redirect('/index/')


def login(request):
    # if request.is_ajax():  # 如果是AJAX请求
    if request.method == "POST":
        # 初始化一个给AJAX返回的数据
        ret = {"status": 0, "msg": ""}
        # 从提交过来的数据中 取到用户名和密码
        username = request.POST.get("username")
        pwd = request.POST.get("password")
        # 获取极验 滑动验证码相关的参数
        gt = GeetestLib(pc_geetest_id, pc_geetest_key)
        challenge = request.POST.get(gt.FN_CHALLENGE, '')
        validate = request.POST.get(gt.FN_VALIDATE, '')
        seccode = request.POST.get(gt.FN_SECCODE, '')
        status = request.session[gt.GT_STATUS_SESSION_KEY]
        user_id = request.session["user_id"]

        if status:
            result = gt.success_validate(challenge, validate, seccode, user_id)
        else:
            result = gt.failback_validate(challenge, validate, seccode)
        if result:
            # 验证码正确
            # 利用auth模块做用户名和密码的校验
            user = auth.authenticate(username=username, password=pwd)
            if user:
                # 用户名密码正确
                # 给用户做登录
                auth.login(request, user)  # 将登录用户赋值给 request.user
                ret["msg"] = "/index/"
            else:
                # 用户名密码错误
                ret["status"] = 1
                ret["msg"] = "用户名或密码错误!"
        else:
            ret["status"] = 1
            ret["msg"] = "验证码错误"

        return JsonResponse(ret)
    return render(request, "login.html")

  

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</title>
    <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
    <link rel="stylesheet" href="/static/mystyle.css">
</head>
<body>

<nav class="navbar navbar-inverse">
    <div class="container-fluid">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                    data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="#">The Blog</a>
        </div>

        <!-- Collect the nav links, forms, and other content for toggling -->
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav">
                <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
                <li><a href="#">Link</a></li>
            </ul>
            <ul class="nav navbar-nav navbar-right">
                {% if request.user.username %}
                    <li><a href="#">{{ request.user.username }}</a></li>
                    <li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
                           aria-expanded="false">个人中心<span class="caret"></span></a>
                        <ul class="dropdown-menu">
                            <li><a href="#">Action</a></li>
                            <li><a href="#">Another action</a></li>
                            <li><a href="#">Something else here</a></li>
                            <li role="separator" class="divider"></li>
                            <li><a href="/logout/">注销</a></li>
                        </ul>
                    </li>
                {% else %}
                    <li><a href="/login/">登录</a></li>
                    <li><a href="/reg/">注册</a></li>
                {% endif %}
            </ul>
        </div><!-- /.navbar-collapse -->
    </div><!-- /.container-fluid -->
</nav>

<!-- 主页面 开始-->
<div class="container">
    <div class="row">
        <div class="col-md-2">
            <div class="panel panel-primary">
                <div class="panel-heading">左侧广告位一</div>
                <div class="panel-body">
                    Panel content
                </div>
            </div>
            <div class="panel panel-info">
                <div class="panel-heading">左侧广告位二</div>
                <div class="panel-body">
                    Panel content
                </div>
            </div>
        </div>
        <div class="col-md-8">
            <!-- 文章列表 开始 -->
            <div class="article-list">
                {% for article in article_list %}
                    <div class="article">
                        <h3><a href="">{{ article.title }}</a></h3>
                        <div class="media">
                            <div class="media-left">
                                <a href="#">
                                    <img class="media-object author-img" src="/media/{{ article.user.avatar }}" alt="...">
                                </a>
                            </div>
                            <div class="media-body">
                                <p>{{ article.desc }}</p>
                            </div>
                        </div>
                        <div class="article-footer">
                            <span><a href="">{{ article.user.username }}</a></span>发布于
                            <span>{{ article.create_time|date:'Y-m-d H:i:s' }}</span>
                            <span class="glyphicon glyphicon-comment">评论({{ article.comment_count }})</span>
                            <span class="glyphicon glyphicon-thumbs-up">点赞({{ article.up_count }})</span>
                        </div>
                    </div>
                {% endfor %}

            </div>
            <!-- 文章列表 结束-->

        </div>
        <div class="col-md-2">
            <div class="panel panel-primary">
                <div class="panel-heading">右侧广告位一</div>
                <div class="panel-body">
                    Panel content
                </div>
            </div>
            <div class="panel panel-info">
                <div class="panel-heading">右侧广告位二</div>
                <div class="panel-body">
                    Panel content
                </div>
            </div>
        </div>
    </div>
</div>
<!-- 主页面 结束-->

<script src="/static/jquery-3.3.1.js"></script>
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
</body>
</html>

 

 

 

基于object查询 于基于queryset查询.

 

 

posted @ 2018-05-31 16:58  萌哥-爱学习  阅读(225)  评论(0编辑  收藏  举报