微司机带您拟: Django+Xadmin打造在线教育平台[Python2&3通用 ](三)-3&4&5时髦Django2.0.1在线教育零基础到上线教程(六)4-10

3-3 django orm介绍与model设计

上节课程完成后代码(来学习本节前置条件):

github仓库地址:https://github.com/mtianyan/DjangoGetStarted

  • 本着承诺commit: 留言板前端页面显示。本次内容了教程3-2竣工。

或是现在您还当经过手写sql语句来操作数据库,当我们发了orm,数据库操作变得慌简短。这同样聊节咱们来上学Django中的orm。

示范地址:
http://mxonline.mtianyan.cn

原生sql 与 orm

从来不orm 的状下message/views.py代码:

import MySQLdb

# 使用原生sql获取书的列表
def book_list(request):
    # 创建到数据库的连接: 指明用户名,数据库,密码
    db = MySQLdb.connect(user = 'me', db='mydb', passwd='secret', host='localhost')
    # 创建一个游标对象执行器
    cursor = db.cursor()
    # 书写我们需要的sql语句
    cursor.execute('SELECT name FROM books ORDER BY name')
    # 对于fetchall()的结果做遍历,将遍历回来的结果当做数组,取第0个值name。
    names = [row[0] for row in cursor.fetchall()]
    db.close()

同意可以叫数据库字段的查询以及采用类的一个特性一样简单?没错登登登:orm上场了

book:name

book.name
book.save()

Django的orm就是为给咱们不再写点那样的讲话,而是像要操作数据库像使用类和类属性一样。

课程仓库地址1:
https://github.com/mtianyan/DjangoGetStarted
学科仓库地址2:
https://github.com/mtianyan/Mxonline2
课仓库地址3:
https://github.com/mtianyan/Mxonline3

开创我们的models

verbose_name:对象的人类可读之号,单数:

verbose_name = "pizza"

class Meta,内嵌于 UserMessage 这个类的定义中
如果 class Publisher 是顶格的,那么 class Meta 在它之下要缩进4个空格--按 Python 的传统
你可以在任意一个 模型 类中使用 Meta 类,来设置一些与特定模型相关的选项。
如:设置ordering = ['name'],默认地都会按 name 字段排序

message/models.py:

# 继承于django.db.models.Model
class UserMessage(models.Model):
    # 设置最大长度,verbose_name在后台显示字段会用到
    name = models.CharField(max_length=20, verbose_name=u"用户名")
    # Django提供内置的邮箱字段会帮忙验证` default_validators = [validators.validate_email]`
    email = models.EmailField(verbose_name=u"邮箱")
    address = models.CharField(max_length=100, verbose_name=u"联系地址")
    message = models.CharField(max_length=500, verbose_name=u"留言信息")


    class Meta:
        verbose_name = u"用户留言信息"
        # db_table ,这里我们让它自动生成所以不用指定

这时候我们实施makemigrations messages会面发觉并没有改。

mark

盖setting中我们无登记我们的app: message

注意:新建的app都要在setting中注册

6-4 用form实现登录-1

地方我们的用户登录的方是基于函数来做的。本节咱们召开一个因类措施的本。
求对类的持续来了解。

基础教程中多还是因函数来做的,其实还推荐基于类来举行。基于类可以带许多补

# 基于类实现需要继承的view
from django.views.generic.base import View
class LoginView(View):
    # 直接调用get方法免去判断
    def get(self, request):
        # render就是渲染html返回用户
        # render三变量: request 模板名称 一个字典写明传给前端的值
        return render(request, "login.html", {})
    def post(self, request):
        # 取不到时为空,username,password为前端页面name值
        user_name = request.POST.get("username", "")
        pass_word = request.POST.get("password", "")

        # 成功返回user对象,失败返回null
        user = authenticate(username=user_name, password=pass_word)

        # 如果不是null说明验证成功
        if user is not None:
            # login_in 两参数:request, user
            # 实际是对request写了一部分东西进去,然后在render的时候:
            # request是要render回去的。这些信息也就随着返回浏览器。完成登录
            login(request, user)
            # 跳转到首页 user request会被带回到首页
            return render(request, "index.html")
        # 没有成功说明里面的值是None,并再次跳转回主页面
        else:
            return render(request, "login.html", {"msg": "用户名或密码错误! "})

澳门1495娱乐 1

mark

持续的view中的办法。

django1.9.8 urls中之安排:

# 换用类实现
from users.views import LoginView
    # 基于类方法实现登录,这里是调用它的方法
    url('^login/$', LoginView.as_view(), name="login")

Django2.0.1 urls配置:

    # 基于类方法实现登录,这里是调用它的方法
    path('login/', LoginView.as_view(), name="login")

每当setting中登记我们的app

DjangoGetStarted/settings.py 大概36行INSTALLED_APPS:

`INSTALLED_APPS`
[
    前面的不用变,后面新增下一行
    'message'
]

这时候我们重运行Tools 菜单下 Run manage.py Task会提示:

比方提示:

SyntaxError: Non-ASCII character '\xe7' in file D:\CodeSpace\PythonProject\DjangoGetStarted\apps\message\models.py on line

告小心或而忘记在描写过中文的地方长:

#coding: utf-8

顾要加以在率先或者二行。

然后实施下发号施令:

makemigrations message

mark

migrate message 生成数据表

mark

前往Navicat验证:

mark

好望咱们的数据表已经创造成功。默认数据表名称为app名称_类名转换为小写
自动生成的id作为主键。

6-5 form字段验证

证实最深长,是否为空等一律层层。

users下新建forms文件。

# encoding: utf-8
__author__ = 'mtianyan'
__date__ = '2018/1/10 0010 04:44'
# 引入Django表单
from  django import forms

# 登录表单验证
class LoginForm(forms.Form):
    # 用户名密码不能为空
    username = forms.CharField(required=True)
    password = forms.CharField(required=True, min_length=5)

概念好forms之后咱们来采取它们做证。

def post(self, request):
        # 类实例化需要一个字典参数dict:request.POST就是一个QueryDict所以直接传入
        # POST中的usernamepassword,会对应到form中
        login_form = LoginForm(request.POST)
        #is_valid判断我们字段是否有错执行我们原有逻辑,验证失败跳回login页面
        if login_form.is_valid():
            # 取不到时为空,username,password为前端页面name值
            user_name = request.POST.get("username", "")
            pass_word = request.POST.get("password", "")

            # 成功返回user对象,失败返回null
            user = authenticate(username=user_name, password=pass_word)

            # 如果不是null说明验证成功
            if user is not None:
                # login_in 两参数:request, user
                # 实际是对request写了一部分东西进去,然后在render的时候:
                # request是要render回去的。这些信息也就随着返回浏览器。完成登录
                login(request, user)
                # 跳转到首页 user request会被带回到首页
                return render(request, "index.html")
        # 验证不成功跳回登录页面
        # 没有成功说明里面的值是None,并再次跳转回主页面
        else:
            return render(request, "login.html", {"msg": "用户名或密码错误! "})

Models讲解

除过普通的应和数据库的字段类型如CharField,还有很多高档项目。如EmailField提供email验证。

    models.ForeignKey     # 外键
    models.DateTimeField  # 时间字段
    models.IntegerField   # 整型
    models.IPAddressField # IP地址
    models.FileField      # 上传文件
    models.ImageField     # 图片

ctrl按停+左键点击models
进入后点击fields拖到文件开始好看到有着字段:

__all__ = [str(x) for x in (
    'AutoField', 'BLANK_CHOICE_DASH', 'BigIntegerField', 'BinaryField',
    'BooleanField', 'CharField', 'CommaSeparatedIntegerField', 'DateField',
    'DateTimeField', 'DecimalField', 'DurationField', 'EmailField', 'Empty',
    'Field', 'FieldDoesNotExist', 'FilePathField', 'FloatField',
    'GenericIPAddressField', 'IPAddressField', 'IntegerField', 'NOT_PROVIDED',
    'NullBooleanField', 'PositiveIntegerField', 'PositiveSmallIntegerField',
    'SlugField', 'SmallIntegerField', 'TextField', 'TimeField', 'URLField',
    'UUIDField',
)]

圆满错误提示

比如:既然表单都说明失败了,就不要显示密码出错了

澳门1495娱乐 2

mark

# 仅当用户真的密码出错时
            else:
                return render(request, "login.html",{"msg":"用户名或密码错误!"})
        # 验证不成功跳回登录页面
        # 没有成功说明里面的值是None,并再次跳转回主页面
        else:
            return render(
                request, "login.html", {
                    "login_form": login_form })

forms中之名目username和password必须和html中的相同。毕竟他是使用的request.POST
若request是由眼前传过来的。

实例化LoginView经常既对咱们的字段进行了求证。

从今上断点:

澳门1495娱乐 3

mark

debugf6运行到

澳门1495娱乐 4

mark

这时好见见errors(ErrorDict)遭受的错误

澳门1495娱乐 5

mark

以form传回前端:

澳门1495娱乐 6

mark

前者被取值:

澳门1495娱乐 7

mark

为这个class加上errorput会显示红色外框。

澳门1495娱乐 8

mark

注意:写在class里面

介绍字段参数

CharField必须指明默认最酷尺寸。null=True,blank=True指明字段可以吧空
defalut = " "借助于定默认值。

name = models.CharField(max_length=20,null=True,blank=True, verbose_name=u"用户名")

id是自动生成的,如果需要从定义主键,message/models.py中补充加字段:

object_id = models.CharField(primary_key=True, verbose_name="主键")

这时点击Tools 菜单下 Run manage.py Task输入makemigrations message

mark

知识点:CharField必须指明最要命尺寸

object_id改为:

    object_id = models.CharField(primary_key=True, max_length=50 ,verbose_name="主键")

此时点击Tools 菜单下 Run manage.py Task输入makemigrations message

You are trying to add a non-nullable field 'object_id' to usermessage without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
 1) Provide a one-off default now (will be set on all existing rows)
 2) Quit, and let me add a default in models.py

基于提示信息,我们要为object_id上加默认值:

    object_id = models.CharField(primary_key=True, max_length=50,default="", verbose_name="主键")

get新知识点:object_id必须有默认值

输入2 退出:然后输入makemigrations message

mark

又输入下面发号施令生成数据表

migrate message 

可观看上图过程被见面告诉我们举行了如何变化,如删减了默认系统生成的主键id
,变更了name。新增了咱们的object_id

通往Navicat验证右键设计表:

mark

可看看object_id既变成我们的初主键。

用forms错误信息显示出

<div class="error btns login-form-tips" id="jsLoginTips">
{% for key, error in login_form.errors.items %}
{{ error }}
{% endfor %}
{{ msg }}</div>

澳门1495娱乐 9

mark

  • 形容了一个类继承Django的view,然后写了get
    post方法(get/post的if是Django替我们就的)
  • 在url中调用Loginview的as_view方法需要丰富括号,进行调用。
  • Django的form进行表单验证并拿error值传到前台。
  • is_valid方法,验证表单

本小节终结对诺commit:

6-4 & 5 登录换用类继承view实现,使用Django
form进行表单验证并将错误信息提示到前台。

介绍Meta信息:

Meta信息中我们可指定常见的类:

db_table = "user_meassage"

自定义后生成表,表名会与我们的保持一致。而无会见前缀appname如:message_

此处以我们已死成了了,就不要开说明改变表名了。

ordering = '-object_id'

ordering指定默认排序字段,如:就会为object_id倒序

verbose_name_plural = u"用户留言信息"

verbose_name_plural:复数信息,便于人读书。否则会当后台显示用户留言信息s

现已修了了orm以数据表映射表。
github地址:https://github.com/mtianyan/DjangoGetStarted
此节结对承诺github commit:

留言板数据库orm映射成表完成。内容了教程3-3了。

6-6 session和cookie自动登录机制

咱们本节来讲session和cookie

User1如何落实登录的。

3-4 django model的增删改

github仓库地址:https://github.com/mtianyan/DjangoGetStarted

  • 齐小节完成代码对应commit:
    留言板数据库orm映射成表完成。内容了教程3-3了却。

message/views.py中:

from .models import UserMessage

用我们刚刚创建的model,import进来。.表示是同当前同级的目录。

比如下图所著添加相同修测试数据。

mark

接下来又我们的getform办法中添加底下代码:

def getform(request):
    # UserMessage默认的数据管理器objects。
    # 方法all()是将所有数据返回成一个queryset类型(django的内置类型)
    all_message = UserMessage.objects.all()

    #我们可以对于all_message进行遍历操作
    for message in all_message:
        # 每个message实际就是一个UserMessage对象(这时我们就可以使用对象的相关方法)。
        print message.name

    return render(request, 'message_form.html')

调节过程:

mark

  • 点击上图小红框位置,打及断点。

  • 点击Run -> debug后:在浏览器里打开:http://127.0.0.1:8000/form/

mark

  • 弹有高达图表示已上断点。

mark

  • 这时鼠标左键点击:all_message.可以见到就是一个{QuerySet}类型的对象,里面存放着[<UserMessage: UserMessage object>]

  • f6假若运行到下一样步。此时凡的值窗口内可以见见message的价值。说明我们遂获到了数据库的值。

mark

cookie的存储

cookie是浏览器支持的同一种本地存储方。以dict,键值对艺术囤。

{"sessionkey": "123"}

浏览器会自动对她进行分析。

filter取出指定要求值

all_message = UserMessage.objects.filter(name=' mtianyan', address='西安')

mark

照上面调试过程更调试好见见咱们一致取出了价值。

些微练:将名字改成呢同协调数据库存放值不同的。查看结果。

mark

改为了空列表,说明一切是。

http请求是同样栽无状态的请

用户向服务器发起的一定量蹩脚呼吁中是没状态的。也便是服务器并不知道这是同一个用户发的。

就记住用户:

浏览器a在向服务器发起呼吁,服务器会活动为浏览器a回复一个id,浏览器a把id放到cookie当中,在产同样破呼吁时带达这个cookie里的id值向浏览器请求,服务器就理解你是谁浏览器发过来的了。

将数据存入数据库

打听:django/db/models/base.py 源码中提供save方法

def save(self, force_insert=False, force_update=False, using=None,
             update_fields=None):

getform方法被补充加代码:

 # 存储部分

    # 首先实例化一个对象
    user_message = UserMessage()

    # 为对象增加属性
    user_message.name = "mtianyan2"
    user_message.message = "blog.mtianyan.cn"
    user_message.address = "西安"
    user_message.email = "1147727180@qq.com"
    user_message.object_id = "efgh"

    # 调用save方法进行保存
    user_message.save()
  • 由及断点:如下图。

mark

  • 直接惦记f6只有步调试,直到如下图:蓝色到return语句

mark

得以产方值窗口查到值

mark

出状态请求(cookie)

澳门1495娱乐 10

mark

服务器a犯回的id会放到服务器a的地区之下。非克跨域访问cookie。

运用浏览器随便打开一个网页,然后f12打开。

论自己以的Chrome浏览器

澳门1495娱乐 11

mark

会晤找到存储于浏览器本地的cookie值

澳门1495娱乐 12

mark

点击clear all清空所有的cookie
f5刷新页面,会意识而管这些cookie值进来。

假定以用户称和密码直接保存于cookie,可以兑现极端垃圾尽简便易行版本的机动登录。

Navicat进行验证

足见见成功之增补加了多少mtianyan2

mark

缓解cookie放在地面未安全的题材(session)

用户以率先差呼吁后,浏览器回复的id既可以是用户之user id。
啊堪同样段任意的字符串,我们管其称为session id

依据用户称以及密码,服务器会使用自己的条条框框变更session id。这个session id保存于当地cookie。浏览器请求服务器会携带。

  • 输入用户名 & 密码
  • 调用 login(), 后端程序会根据用户名密码生成session
    id。保存在数据库被。
  • 用户登录后,需要通过是session id取出这些骨干信息。

澳门1495娱乐 13

mark

Django的默认表中之session发明就记录了用户登录时,后端我们Django为用户生成的sessionid

澳门1495娱乐 14

mark

好望session key value 和过期日子。

咱俩可清空这张表的数码。运行品种进行登录。

澳门1495娱乐 15

mark

得看来咱们刚刚生成的session id。

此刻透过f12查浏览器在地面存储的session id。可以看如下图和咱们数据库中之等同。

澳门1495娱乐 16

mark

session_key 发到浏览器叫做session id

透过session id 用户访问任何一个页面还见面携带,服务器就见面认得。

Setting.py中,

澳门1495娱乐 17

mark

以此app会拦截我们每次的request请求,在request遭受找到session
id,然后去数据表中进行询问。
接下来经过session key 去找到session data。此时一直为我们取出了user。

于服务器返回浏览器的response受吗会见直接长session id

cookie是浏览器本地存储机制,存在域名之下,存储不安全。
服务器在返id时通过规则不行成一串字符,并安装了过时。存储于劳务器端(数据库)

文章:
http://projectsedu.com/2016/10/17/django%E4%BB%8E%E8%AF%B7%E6%B1%82%E5%88%B0%E8%BF%94%E5%9B%9E%E9%83%BD%E7%BB%8F%E5%8E%86%E4%BA%86%E4%BB%80%E4%B9%88/

怎样自html的交由中收获到数码并保存进数据库

templates/message_form.html:

mark

method是post。action就是依为我们在urls.py中布局的/form/
前面必须加以斜杠指根路径下form
中的input会自动把价值传递给后台:这时我们便可以当getform中赢得到刚刚传递过来的价值。

运行品种:然后输入需要填的值。点击提交:出现403错误

Forbidden (403)
CSRF verification failed. Request aborted.

冲提示:我们的页面没有进展crsf的验证,这时django的安体制,不同意任意form都朝着后台提交。

知识点:所以我们需要以html页面中投入csrf_token

    {% csrf_token %}

mark

原始那行删除掉。打及断点

mark

刷新页面并交付。这时候在值窗口可看到request对象下的POST中存放着咱交的数据。内容如下

<QueryDict: {u'message': [u'\u54c8\u54c8'], u'address': [
u'\u897f\u5b89\u5e02'], u'csrfmiddlewaretoken': [
u'uIYSMOTWPJBPOPucRwd3uDaWtCzeEaem'], u'name': [
u'\u5929\u6daf\u660e\u6708\u7b19'], u'email': [u'1147727180@qq.com']}>

mark

数据以dict:key-value 形式储存 key是由于如下图html中之name所主宰对应之。

mark

6-7 用户注册

数据库新增。

request.POST遭逢数取出,存入user_message对象

 # html表单部分

    # 此处对应html中的method="post",表示我们只处理post请求
    if request.method == "POST":
        # 就是取字典里key对应value值而已。取name,取不到默认空
        name = request.POST.get('name', '')
        message = request.POST.get('message', '')
        address = request.POST.get('address', '')
        email = request.POST.get('email', '')

        # 实例化对象
        user_message = UserMessage()

        # 将html的值传入我们实例化的对象.
        user_message.name = name
        user_message.message = message
        user_message.address = address
        user_message.email = email
        user_message.object_id = "ijkl"

        # 调用save方法进行保存
        user_message.save()
  • 打断点在生图位置:

mark

  • 跻身调剂:点击点击method:是get请求。因为咱们并无按照提交按钮,而是get这个网页

mark

  • 点击f8后续运行我们的类 浏览器被填入表单内容点提交。

mark

盖这次是表单提交,已经改成了post方式。按f6展开单步调试。

直接单步到如下图蓝色

mark

这时候候值浏览窗口可看出

mark

反省我们的user_message对象的性是否早已尽增长进去,

行使f8 继续路并通往Navicat验证

mark

可以看咱们的数据库中已经新增,标志在我们曾经打响存入数据。

拷贝注册页面上template目录

除去数据。

对此查询及之数码做去:

# 方法2 :filter取出指定条件值,逗号代表and 必须同时满足两个条件才返回。
all_message = UserMessage.objects.filter(name='mtianyan', address='西安')

# 我的数据库里保存着可以匹配到该条数据的一行。

# 删除操作:使用delete方法删除all_message

all_message.delete()

    for message in all_message:
        # 删除取到的message对象
        message.detele()
        # print message.name

点击run并访问:http://127.0.0.1:8000/form/
入Navicat进行验证。

mark

好看来我们的那么条mtianyan + 西安之数据现已深受删去。

至此:我们已经学会了增产,删除,查询。

本节竣工github对承诺commit:

django model的增删改数据库。本次内容了教程3-4。

挥洒我们本着承诺要拍卖的view(RegisterView)

users/views.py

# 注册功能的view
class RegisterView(View):
    # get方法直接返回页面
    def get(self, request):
        return render(request, "register.html", {})

3-5 django url templates配置

项目Github地址:https://github.com/mtianyan/DjangoGetStarted
本节开头对应相应Github的commit:django
model的增删改数据库。本次内容了教程3-4。

本节拿介绍url的安排,以及哪些将数据库数据填充回前台html页面。

场面:只同意用户改mtianyan,如果无就长,如果发就揣使用户可以修改。

布相应之url

Django1.9.8 url配置如下:

from users.views import RegisterView
    # 注册url
    url("^register/", RegisterView.as_view(), name="register"),

Django2.0.1 url配置如下

from users.views import RegisterView
    # 注册url
    path("register/", RegisterView.as_view(), name = "register" )

取出数据

message/views.py中的getform方法中

    message = None
    all_message = UserMessage.objects.filter(name='mtianyan', address='西安')

    # if 判断是否存在数据
    if all_message:
        # all_message是一个list,可以使用切片。
        message = all_message[0]

这边注意把前几乎节省写的去除掉

修改index页面被注册url

澳门1495娱乐 18

mark

此刻看首页发现可成功超越反到注册页面

用数据填至html中

修改静态文件被static目录引用

修改return render

return render(request, 'message_form.html',{
        "my_message" : message
})   

此间前面的”my_meassage”是咱好自行命名的。会起一个my_message对象就返回前端页面。

关键步骤load staticfile

澳门1495娱乐 19

mark

于前者页面被推广入值。

否input系列标签添加value:
使用my_message.name抱到我们传递过来的my_message靶的属性值。

        <input id="name" type="text" name="name"  
        value="{{ my_message.name }}" class="error" placeholder="请输入您的姓名"/>

要自行完成姓名,邮箱,联系地址三只input标签。

textarea标签添加值

mark

        <textarea id="message" name="message"  
        placeholder="请输入你的建议">{{ my_message.message }}</textarea>

运作项目,访问:http://127.0.0.1:8000/form/

mark

事业有成!!我们已以后台数据库数据成功展示暨前台。

然后修改路径为一个相对于static的相对路径

澳门1495娱乐 20

mark

他见面自行根据setting中布局,为咱添加前缀

澳门1495娱乐 21

mark

若我们拿目录在setting中改至mystatic。url中见面自动抬高指定的前缀

足见见好拜成功。

澳门1495娱乐 22

mark

template模板渲染着之片用法。

以咱们的template模板被为就算是form.html中,不允我们写Python的语法,
它提供了一如既往套自己之内建标签。

官文档中template内修标签从而法传送门

以目前的老三单html中之静态文件全部改动目录

干燥而倘若发耐心。

这访问三单页面,查看样式是否完好。

常用之几乎种植模板标签介绍:

验证码库实现验证码

https://github.com/mbi/django-simple-captcha

if - else

官方提供模板如下:

mark

村办执行:

mark

满足if运行结果:

mark

不满足if:如改为my_message.name == "mtianyan1"运行结果:

mark

装配备

workon mxonline3
pip install  django-simple-captcha
workon mxonline2
pip install  django-simple-captcha==0.4.6
  • Add captcha to the INSTALLED_APPS in your settings.py

  • Add an entry to your urls.py:

django1.9.8如下:

from django.conf.urls import url, include
urlpatterns += [
    url(r'^captcha/', include('captcha.urls')),
]

django2.0.1如下;

    # 验证码url
    path("captcha/", include('captcha.urls'))

makemigrations
migrate

澳门1495娱乐 23

mark

上数据库查看转的表明

澳门1495娱乐 24

mark

澳门1495娱乐 25

mark

ifequal & ifnotequal

mark

合法文档解释:ifequal a b
相当于f a == b.ifnotequal虽说一定给if a != b

村办执行:

mark

结果也:未找到中文昵称

以验证码显示及页面

users/forms.py:

slice

mark

法定文档解释:其实就算是片操作。从头开始切到第n个。

个人执行:

mark

本来mtianyanmtianyan1凡是殊之,但是片后前八各相同。
运行结果显示 :对应中文昵称:天涯明月笙

概念我们的register form:

# 引入验证码field
from captcha.fields import CaptchaField

# 验证码form & 注册表单form
class RegisterForm(forms.Form):
    # 此处email与前端name需保持一致。
    email = forms.EmailField(required=True)
    # 密码不能小于5位
    password = forms.CharField(required=True, min_length=5)
    # 应用验证码
    captcha = CaptchaField()

users/views.py

URl的别名设置技巧

DjangoGetStarted/urls.py:

r'^form/$'补偿加别名:

    url(r'^form/$', getform, name = "form_new")

赴html中修改action地址也底所示:

<form action="{% url "form_new" %}" method="post" class="smart-green">

这儿我们而改变urls.py中的r'^form/$'切莫需再修改前端代码中值。

于咱们的registerform中实例化并传递到前端:

# form表单验证 & 验证码
from .forms import LoginForm, RegisterForm

# 注册功能的view
class RegisterView(View):
    # get方法直接返回页面
    def get(self, request):
        # 添加验证码
        register_form = RegisterForm()
        return render(request, "register.html", {'register_form':register_form})

url先后顺序问题

注意url匹配规则遭必定毫无忘记/$号代表以form/得了的才见面使得。不会见朝后连续配合。比如没有/$

    url(r'^form', getform, name="form_new")

此时我们上浏览器访问时输入http://127.0.0.1:8000/formemmm都可于响应。

mark

特意是设下还部署来让这规则包含的条条框框,会来被形容在再度因前之阻碍停得无交正确处理的Bug。

mark

上图我们是想念如果被formtest响应admin.site.urls。但是会叫form提前拦截停。

故而我们得要留意加上/$符号。

从那之后我们就了留言板项目:学习及了Django必备的基础知识。
生一样章节我们将启幕我们的进阶学习:开发在线教育平台网站。

本章结束:

本着承诺Commit: 留言板项目上得,本次内容了教程3-5。完结,撒花。
项目Github地址:https://github.com/mtianyan/DjangoGetStarted

前者获取验证码值

澳门1495娱乐 26

mark

澳门1495娱乐 27

mark

找到上图验证码部分。修改也产图

澳门1495娱乐 28

mark

Forms中的field会变不同之律。

澳门1495娱乐 29

mark

我们只有label但是前端可以翻到input框等,也就是是Registerform会为我们转变输入框+验证码。

隐蔽的字符串的框会被拉动至后台,由Django为咱进行验证。验证该验证码是否保存了。

澳门1495娱乐 30

mark

可看得我们数据库中将这个hashkey进行了保留。这个key与验证码内容对应。

后台会将验证码值 和 hashkey进行协同查询。

修register view的后台逻辑(RegisterView)

users/views.py的RegisterView中添加post方法:

    def post(self, request):
        # 实例化form
        register_form = RegisterForm(request.POST)
        if register_form.is_valid():
            pass

澳门1495娱乐 31

mark

澳门1495娱乐 32

mark

修改form表单提交方式和提交至哪个url

澳门1495娱乐 33

mark

前者的form提交加上对应的crsf token

刷新验证码是前者帮我们得的:

//刷新验证码
function refresh_captcha(event){
    $.get("/captcha/refresh/?"+Math.random(), function(result){
        $('#'+event.data.form_id+' .captcha').attr("src",result.image_url);
        $('#id_captcha_0').attr("value",result.key);
    });
    return false;
}

收获前端页面值并封装成一个user_profile对象,保存至数据库。

from django.contrib.auth.hashers import make_password

        if register_form.is_valid():
            user_name = request.POST.get("email", "")
            pass_word = request.POST.get("password", "")

            # 实例化一个user_profile对象,将前台值存入
            user_profile = UserProfile()
            user_profile.username = user_name
            user_profile.email = user_name

            # 加密password进行保存
            user_profile.password = make_password(pass_word)
            user_profile.save()
            pass

发送邮件实现

setting中配置;

# 发送邮件的setting设置

EMAIL_HOST = "smtp.qq.com"
EMAIL_PORT = 25
EMAIL_HOST_USER = "mxonline.mtianyan.cn"
EMAIL_HOST_PASSWORD = " "
EMAIL_USE_TLS= True
EMAIL_FROM = "mxonline.mtianyan.cn"

新建package后新建文件。

apps:utils/email_send.py:

# encoding: utf-8
from random import Random

__author__ = 'mtianyan'
__date__ = '2018/1/10 0010 20:47'
from  users.models import EmailVerifyRecord
# 导入Django自带的邮件模块
from django.core.mail import send_mail
# 导入setting中发送邮件的配置
from Mxonline2.settings import EMAIL_FROM

# 生成随机字符串
def random_str(random_length=8):
    str = ''
    # 生成字符串的可选字符串
    chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789'
    length = len(chars) - 1
    random = Random()
    for i in range(random_length):
        str += chars[random.randint(0, length)]
    return str

# 发送注册邮件
def send_register_eamil(email, send_type="register"):
    # 发送之前先保存到数据库,到时候查询链接是否存在

    # 实例化一个EmailVerifyRecord对象
    email_record = EmailVerifyRecord()
    # 生成随机的code放入链接
    code = random_str(16)
    email_record.code = code
    email_record.email = email
    email_record.send_type = send_type

    email_record.save()

    # 定义邮件内容:
    email_title = ""
    email_body = ""

    if send_type == "register":
        email_title = "mtianyan慕课小站 注册激活链接"
        email_body = "请点击下面的链接激活你的账号: http://127.0.0.1:8000/active/{0}".format(code)

        # 使用Django内置函数完成邮件发送。四个参数:主题,邮件内容,从哪里发,接受者list
        send_status = send_mail(email_title, email_body, EMAIL_FROM, [email])
        # 如果发送成功
        if send_status:
            pass

澳门1495娱乐 34

mark

达到图也qq邮箱开启smtp服务

点击生成授权码

澳门1495娱乐 35

mark

def post中增长发送邮件

users/views.py

# 发送邮件
from utils.email_send import send_register_eamil
            # 发送注册激活邮件
            send_register_eamil(user_name, "register")

点击注册提交,因为我们从不return。一直于转圈圈。

可是数据库被就上加了字段。

澳门1495娱乐 36

mark

足见见我们的邮件就给发送至邮箱中。

如果注册成功返回login页面:不成事,返回register页面并报错。

一应俱全错误提示。

寻找猫画虎:将login中的谬误提示搬运到register中来。

  • register_form的报错信息。

澳门1495娱乐 37

mark

澳门1495娱乐 38

mark

  • 邮箱 & 密码 form验证

澳门1495娱乐 39

mark

到用户价值回填逻辑

澳门1495娱乐 40

mark

假使污染回之发生值则,显示传回来值。

密码为举行相同操作

改默认的激活状态为false

post方法中

            # 默认激活状态为false
            user_profile.is_active = False

书写处理激活的view。

# 激活用户的view
class ActiveUserView(View):
    def get(self, request, active_code):
        # 查询邮箱验证记录是否存在
        all_record = EmailVerifyRecord.objects.filter(code = active_code)
        # 激活form负责给激活跳转进来的人加验证码
        active_form = ActiveForm(request.GET)
        # 如果不为空也就是有用户
        if all_record:
            for record in all_record:
                # 获取到对应的邮箱
                email = record.email
                # 查找到邮箱对应的user
                user = UserProfile.objects.get(email=email)
                user.is_active = True
                user.save()
                # 激活成功跳转到登录页面
                return render(request, "login.html", )
        # 自己瞎输的验证码
        else:
            return render(request, "register.html", {"msg": "您的激活链接无效","active_form": active_form})

布置用户激活的url并经过url提取及变量:

django1.9.8:

    # 激活用户url
    url(r'^active/(?P<active_code>.*)/$',ActiveUserView.as_view(), name= "user_active")

django2.0.1:

    # 激活用户url
    re_path('active/(?P<active_code>.*)/', ActiveUserView.as_view(), name= "user_active")

此间通过?p将后面.*代表全领到的正则,符合的始末传入参数active_code中/$代表以/$为结尾

澳门1495娱乐 41

mark

其他细节根据自己要开展优化。

报功能做完。对许commit:

登记功能实现得了,流程:注册,发邮件,激活,登录。对许6-6,7,8,9,10

相关文章