实验一 :简单Django项目的创建、调试和运行
一、实验目的
1、了解Django项目开发环境的搭建过程;
2、掌握在Django中创建项目和应用的两种方法;
3、学会简单的Django项目程序的调试技巧。
二、实验器材
微机 + windows操作系统 + Python + Django + Pycharm
二、实验内容
1、Django项目开发环境的搭建;
2、创建Django项目;
3、编译检查语法错误,调试,运行,获得输出结果;
4、独立完成上述内容,并提交书面报告。
四、实验步骤
①安装Python;
②安装Django;
③安装Pycharm(专业版)。
2、创建Django项目(两种方法)
方法一:使用内置指令创建项目
(1)首先选择一个目录用于承载MyDjango项目;
例如:D: \Django Programming
(2)以管理员身份打开Windows的命令提示符,进入上述目录;
(3)输入指令django-admin startproject MyDjango,创建MyDjango项目
(4)项目骨架创建之后,进入MyDjango项目,启动Django的内置服务器运行当前的项目验证是否创建成功,输入: python manage.py runserver
(5)按照提示,在浏览器中打开http://127.0.0.1:8000/,可以看到MyDjango项目第一次启动的界面,表示MyDjango项目骨架搭建完成。
☆ 可以使用命令python manage.py shell验证项目是否处于虚拟环境中。
方法二:使用Pycharm创建项目
(1)打开Pycharm,选择“Create New Project”或者选择Pycharm左上方单击FileàNew Project,创建新项目;
(2)在弹出的对话框中,选择“Django”,在“Location”处输入要保存的目录及项目名称;
(3)在“Project Interpreter”位置可选择创建虚拟环境,并指定虚拟环境的Python解释器;或者选择已有的Python解释器。
说明:在做应用程序开发的时候不可避免地会遇到不同的应用程序依赖不同的包版本情况,这就可能出现依赖冲突的问题,时间越长,这种情况越糟糕。
例如:假设之前开发的Django A应用依赖于Python 2.7,现在开发的Django B应用必须要使用Python 3.X版本,若简单地将系统中的Python升级到3.X版本,就会导致A应用不可用,因为Python 2与Python 3中的部分语法是不兼容的。
虚拟环境是指在特定目录中安装开发Python项目所需的所有软件包。不同虚拟环境之间是相互隔离的,避免了Python不同版本、软件包和第三方库之间的不兼容问题,同时方便软件部署。
(4)单击“create”,完成Django项目的创建。
(5)启动项目。(两种方法)
①直接单击“运行”按钮启动项目;
 
 
②Pycharm底部的“Terminal”界面中输入指令:python manage.py runserver,启动内置服务器,运行项目。
(6)在浏览器中打开http://127.0.0.1:8000/,可以看到MyDjango项目第一次启动的界面。
说明:Django内置的开发服务器默认监听本地8000端口,所以为项目设置的默认访问URL为:http://127.0.0.1:8000/,按【Ctrl+C】组合键可终止服务器运行。服务器成功启动后,在浏览器中访问http://127.0.0.1:8000/,显示项目默认首页。
若想使用其他端口,可在启动服务器时指定端口。
例如:python manage.py runserver 8080
五、上机作业
1、用上述方法创建HelloWord项目。
步骤:
①创建Django项目
②创建视图
在项目中新建视图文件views.py,在该文件中定义一个名为hello的函数。代码如下:
from django.http import HttpResponse
def hello(request):
return HttpResponse(“Hello Word!”)
☆ hello视图函数会在浏览器中显示一个字符串。
③配置项目URL
在urls.py文件中,添加URL配置,以访问hello视图函数。
代码如下:
from django.contrib import a'dmin
from django.urls import path
from . import views
urlpatterns = [
path(‘ ’,views.hello,name=’hello’),
path(‘admin/’,admin.site.urls),
]
④调试,运行,测试运行结果。
实验二:Django项目的功能配置
一、实验目的与要求:
1、熟练babys项目开发环境的搭建;
2、了解Django项目的功能配置,学会对babys项目进行功能配置。
二、实验内容:
1、babys项目开发环境的搭建;
2、babys项目的功能配置;
3、编译检查语法错误,调试,运行,获得输出结果;
4、独立完成上述内容,并提交书面报告。
三、实验器材:
微机 + windows操作系统 + Python + Django + Pycharm
1、babys项目开发环境的搭建
①创建babys项目;
②在babys中创建三个项目应用:
index:主要实现网站首页。
commodity:主要实现网站的商品列表页和商品详细页;
shopper:主要实现网站的购物车页面、个人中心页面、用户注册登录页面、在线支付功能等
③在babys项目中新建三个文件夹media、pstatic、templates:
l 在media文件夹中新建文件夹details和imgs,用于存放媒体资源,包括商品的主图和详细介绍图;
l 在pstatic文件夹中分别创建文件夹css、img、js、layui,用于存放网站的静态资源文件。文件夹css含有main.css文件;js中有car.js和mm.js文件。
l 在templates文件夹中存放6个HTML模板文件,即网站的网页文件。
2、配置babys项目
(1)在settings.py中添加新增的项目应用;
(2)在settings.py中配置模板信息;
(3)在settings.py中添加LocaleMiddleware中间件,使得Django内置的功能支持中文显示。
(4)配置MySQL数据库:
①安装MySQL数据库系统
②安装MySQL数据库的连接模块;
③在settings.py文件中配置MySQL数据库连接信息。
④迁移数据库,验证MySQL配置信息是否正确。
(5)配置静态资源。
(6)配置媒体资源。
实验三:Django项目的URL配置
一、实验目的与要求:
1、了解Django项目的URL分发机制,掌握path函数和re_path函数的用法,学会编写URL;
2、掌握为简单的Django项目增加导航链接的方法;
3、掌握URL参数的传递方法。
1、创建HelloWorld项目,实现如图1所示的结果:
 
 
 
 
为HelloWorld项目添加导航链接,使得单击图1页面中的“关于HelloWorld”链接,将打开about页面,如图2所示。单击图2页面中的“返回首页”链接,可返回项目首页。
 
 
 
 
2、编译检查语法错误,调试,运行,获得输出结果;
3、独立完成上述内容,并提交书面报告。
三、实验器材:
微机 + windows操作系统 + Python + Django + Pycharm
四、实验步骤
1、path函数和re_path函数用法回顾
2、创建HelloWorld项目
(1)为HelloWorld项目添加about应用。
 (2)打开HelloWorld项目,修改项目的views.py文件,定义项目首页的视图函数。
(2)打开HelloWorld项目,修改项目的views.py文件,定义项目首页的视图函数。 
 (3)修改项目应用about的views.py文件,定义视图函数以返回about页面。
(3)修改项目应用about的views.py文件,定义视图函数以返回about页面。
(4)修改项目的urls.py文件,添加项目的URl配置。
(5)运行开发服务器,测试项目运行情况。
五、上机作业
1、创建MyDjango项目,并定义如下视图函数:
 
 
(1)修改项目的urls.py文件,使得在浏览器中输入http://127.0.0.1:8000/data1/123abc时,访问该视图函数。
(2)修改项目的url.py文件,使得在浏览器中输入http://127.0.0.1:8000/data2/123_abc时,访问该视图函数。
(3)修改项目的url.py文件,使得在浏览器中输入http://127.0.0.1:8000/data3/1349710959@qq.com时,访问该视图函数。
实验四:Django项目用户模型的定义
一、实验目的与要求:
1、了解模型基础,熟练掌握数据模型的搭建方法,包括数据模型的定义和数据迁移操作;
2、熟练掌握数据操作的方法,包括数据的新增、更新、删除和查询等方法;
3、掌握有关联关系的多表之间的数据操作方法;
4、学会为简单的Django项目定义相关数据模型,创建相应的数据表。
二、实验内容
1、一般的系统都会建立用户表来保存用户名、密码和权限等信息。因此,本实验综合第四章讲解的知识,根据下表信息,为Django项目定义一个用户模型。
2、编译检查语法错误,调试,运行,获得输出结果;
3、独立完成上述内容,并提交书面报告。
三、实验器材
微机 + windows操作系统 + Python + Django + Pycharm
四、实验步骤
1、数据模型搭建与使用的相关知识点回顾
(1)数据模型的定义
(2)数据迁移创建数据表
(3)数据的新增、更新、删除、查询
2、创建一个Django项目,如SysuserModel项目,打开项目文件夹。
(1)在SysuserModel项目中创建一个Sysuser应用。
(2)打开Sysuser应用的models.py文件,根据以下表格给定的用户信息,在models.py文件中定义系统用户模型。
from django.db import models
class sysuser(models.Model):
…… # 定义用户名字段
…… # 定义密码字段
(3)执行数据迁移操作,创建相应的数据表。
(4)进入当前项目的Python交互环境,用新增数据的两种方法将下表中两个用户的信息写入数据库。
| 用户名 | 密码 | 
| admins | 123456 | 
| adminstrator | 123321 | 
(5)将用户admins的密码修改为“123abc”。
(6)打印出数据库中的所有用户数据。
五、上机作业
1、请定义模型,通过模型将表4-4和表4-5中的数据写入MySQL数据库。(注意两个表中的数据关联)
表格 4-4专业信息
| 招生代码 | 专业名称 | 层次 | 收费标准 | 
| 101 | 初等教育 | 高起专 | 1850 | 
| 102 | 会计 | 高起专 | 1850 | 
| 501 | 财务管理 | 专升本 | 1850 | 
| 502 | 土木工程 | 专升本 | 2050 | 
表格 4-5录取信息
| 准考证号 | 姓名 | 录取专业 | 
| 010150516 | 徐豪碧 | 101 | 
| 010150919 | 段茜 | 102 | 
| 010350508 | 范绿平 | 501 | 
| 010550225 | 黄俊 | 502 | 
基本步骤:
(1)创建一个Django项目,并添加一个应用;
(2)打开应用的models.py文件,确定两表的关系后,定义相应的数据模型;
(提示:学生与专业之间属于多对一关系,应定义两个模型:学生模型和专业模型,学生模型中应包含外键字段,用models.ForeignKey字段进行定义。)
(3)执行数据迁移操作;
(4)往数据库中添加上述两个表的数据。
实验五:实现图形验证码
一、实验目的
1、学会编写数据业务逻辑,熟练掌握视图的定义过程以及请求和响应的处理;
2、学会使用基于类的视图来处理业务逻辑;
3、掌握为简单的Django项目定义视图,来处理相应的业务逻辑。
二、实验内容
1、本实验综合第五章讲解的知识,实现图形验证码功能。
基本思路:使用PIL库动态创建验证码图片,用FileResponse将验证码图片返回客户端。用session对象保存验证码,用于验证用户输入的验证码是否正确。
 输入图片中显示的验证码后,单击提交按钮。验证结果如图所示:
输入图片中显示的验证码后,单击提交按钮。验证结果如图所示:
2、编译检查语法错误,调试,运行,获得输出结果;
3、独立完成上述内容,并提交书面报告。
三、实验器材
微机 + windows操作系统 + Python + Django + Pycharm
四、实验步骤
(1)视图函数的定义
(2)视图的请求和响应
(3)视图类
2、创建一个Django项目,如MyDjango项目,
(1)打开项目文件夹,创建一个视图文件views.py。
 
 
 
 
 定义视图函数,创建验证码图片。
定义视图函数,创建验证码图片。
(2)执行数据迁移操作,创建数据表。
(3)项目的urls.py文件,配置URL访问createImg视图。
(4)在浏览器中访问http://127.0.0.1:8000/getpng,可以直接查看验证码图片,如图所示:
 
 
 (5)定义视图函数使用验证码图片。
(5)定义视图函数使用验证码图片。
说明:
a、代码中表达action的属性设置为“/docheck”,该URL访问的视图验证码用户提交的验证码是否正确。
b、超级链接的href属性设置为“/getcheck”,该URL访问验证码输入页面,用于执行页面刷新操作,以便显示新的验证码。
c、图片的src属性设置为“/getpng”,该URl返回验证码图片。
(6)添加访问视图imgCheckCode的URL配置。
 (7)定义视图函数,验证用户输入的验证码。
(7)定义视图函数,验证用户输入的验证码。
(8)添加访问视图verifyCode的URL配置。
 因为视图verifyCode要接收表单数据,所以用csrf_exempt( )设置例外,不执行CSRF安全验证。
因为视图verifyCode要接收表单数据,所以用csrf_exempt( )设置例外,不执行CSRF安全验证。
(9)在浏览器中访问http://127.0.0.1:8000/getcheck,验证是否能正确显示验证码并完成验证。
实验六:用模板实现数据分页
一、实验目的与要求:
1、了解Django的模板系统,熟练掌握模板引擎的配置;
2、学会使用Django模板语言(DTL),包括变量、for标签、if标签、过滤器等。
3、学会编写模板,定义模板文件,熟练掌握在视图中使用模板文件的方法。
二、实验内容:
 1、本实验综合第六章讲解的知识,用模板实现数据分页,如图所示:
1、本实验综合第六章讲解的知识,用模板实现数据分页,如图所示:
2、编译检查语法错误,调试,运行,获得输出结果;
3、独立完成上述内容,并提交书面报告。
三、实验器材:
微机 + windows操作系统 + Python + Django + Pycharm
四、实验步骤:
1、模板的相关知识点回顾
(1)模板引擎的配置
(2)模板变量:{{ 变量名 }}
(3)模板标签:{{% 标签名 %}}
常用标签包括:if标签、for标签、include标签、自定义标签等。
(4)过滤器:{{ 变量 | 过滤器 }}
常用过滤器包括:length、lower/upper、first/last、truncatewords、自定
义过滤器等。
(5)模板继承
2、创建一个Django项目,如HelloDjango项目,
 (1)打开项目文件夹,定义一个模型。
(1)打开项目文件夹,定义一个模型。
(2)打开pycharm的Terminal界面进入项目目录,执行数据迁移操作,创建数据表。
à python manage.py makemigrations HelloDjango
à python manage.py migrate
(3)打开数据库,将scores.csv文件中的数据导入数据表。
(4)定义模板。
<center>
    <b>学生成绩表</b>
    {% if scores %}
    <table border="1">
        <tr><td>id</td><td>考号</td><td>姓名</td><td>语文</td><td>数学</td><td>英语</td></tr>
        {% for s in scores %}
        <tr style="background-color: {% cycle 'white' 'lavender' %}">
            <td>{{ s.id }}</td>
            <td>{{ s.kh }}</td>
            <td>{{ s.xm }}</td>
            <td>{{ s.yw }}</td>
            <td>{{ s.sx }}</td>
            <td>{{ s.yy }}</td>
        </tr>
        {% endfor %}
    </table>
    {% if scores.has_previous %}
        <a href="?page=1">|<;第一页</a>
        <a href="?page={{ scores.previous_page_number }}">前一页</a>
    {% endif %}
    Page {{ scores.number }} of {{ scores.paginator.num_pages }}
    {% if scores.has_next %}
        <a href="?page={{ scores.next_page_number }}">下一页</a>
        <a href="?page={{ scores.paginator.num_pages }}">最末页>;|</a>
    {% endif %}
    {% else %}
        未提供成绩数据!
    {% endif %}
</center>
 (5)定义视图。
(5)定义视图。
(6)配置URL访问视图。
(7)启动开发服务器,测试视图。在浏览器中访问http://127.0.0.1:8000/scores?page=1,输出第1页数据,单击表格下方各个超链接可切换页面。
实验七:实现用户注册
一、实验目的与要求:
1、了解Django的表单系统,熟练掌握表单的基础知识;
2、掌握Django模型表单的相关知识,学会定义模型表单以及使用模型表单为数数据库添加和修改数据;
3、学会在Django项目中使用资源以及使用Ajax。
二、实验内容:
 1、本实验综合第七章讲解的知识,实现用户注册功能,如图所示:
1、本实验综合第七章讲解的知识,实现用户注册功能,如图所示:
页面主要功能包括:
2、编译检查语法错误,调试,运行,获得输出结果;
3、独立完成上述内容,并提交书面报告。
三、实验器材:
微机 + windows操作系统 + Python + Django + Pycharm
四、实验步骤:
1、表单的相关知识点回顾
2、创建一个Django项目,如HelloDjango项目。
(1)打开pycharm的Terminal界面进入项目目录,执行下面的命令创建应用newuser。
à python manage.py startapp newuser
(2)打开应用的models.py模型文件,定义用户模型,代码如下:
from django.db import models
class userinfo(models.Model):
    uid=models.CharField(max_length=10) 
    password=models.CharField(max_length=8) 
    email=models.CharField(max_length=20) 
(3)在pycharm的Terminal界面进入项目目录,执行下面的命令完成数据迁移。
à python manage.py makemigrations
à python manage.py migrate
(4)创建模板文件newuser.html,用静态HTML文件实现用户信息输入表单,通过Ajax脚本提交数据。
<!DOCTYPE html>
<html>
<head><script src="/static/jquery-3.4.1.min.js"></script></head>
<body>
    <center>
        新用户注册<hr>
        <table>
            <tr><td align="right"> 用户ID:</td>
                <td><input type="text" id="uid" maxlength="10">
                    <span id="ruid"></span>
                </td></tr>
            <tr><td align="right">密码:</td>
                <td><input type="password" id="pwd1" maxlength="8"></td></tr>
            <tr><td align="right">再次输入密码:</td>
                <td><input type="password" id="pwd2" maxlength="8"></td></tr>            
            <tr><td align="right">Email:</td>
                <td><input type="email" id="email" maxlength="20"></td></tr>
            <tr><td align="right">验证码:</td>
                <td><img src="/getpng/" id="icode" />单击刷新<br />
                    <input type="text" id="code" maxlength="10"></td></tr>
            <tr><td colspan="2" align="center"><input type="button" value="提交" id="submit" /></td></tr>
        </table>
        <hr><span id="result"></span>
    </center>
    <script>
        var codeok = false
        var idok = false
        $(document).ready(function () {
            $('input').keyup(function () {//在输入数据时,清除上次的验证信息
                $('#result').html('')    });
            $('#uid').keyup(function () {//在输入数据时,检查用户用户名是否可用
                var uid = $("#uid").val();
                $.get("/checkuid/", { 'uid': uid }, function (r) {
                    if (r == 'ID可用') { idok = true } else { idok = false }
                    $('#ruid').html(r)   })
            });
            $('#icode').click(function () {//单击时更改图片src,
                var a = (new Date()).toTimeString()
                $('#icode').attr('src', '/getpng/?t=' + a) //加上不同的参数,以便刷新图片
                codeok = false   });
            $('#code').blur(function () {//结束输入验证码时验证是否正确
                var code = $("#code").val();
                $.get("/checkcode/", {}, function (r) {
                    if (r.toLowerCase() == code.toLowerCase()) { codeok = true } else { codeok = false }
                })
            });
            $('#submit').click(function () {//单击提交按钮时,先检查数据,通过后提交服务器
                if (!idok) {
                    $('#result').html('<span style="color:red">你输入的用户ID已被占用!</span>')
                    return 1  }
                var pwd1 = $("#pwd1").val();
                var pwd2 = $("#pwd2").val();
                pwdok = false
                if (pwd1 != pwd2) {
                    $('#result').html('<span style="color:red">两次输入的密码不一致!</span>')
                    return 1}
                var reg = /^\w+@[a-zA-Z0-9]{2,10}(?:\.[a-z]{2,4}){1,3}$/;
                if (!reg.test($("#email").val())) {
                    $('#result').html('<span style="color:red">你输入的Email地址无效!</span>')
                    return 1}
                if (!codeok) {
                    $('#result').html('<span style="color:red">验证码输入错误!</span>')
                    return 1}
                var uid = $("#uid").val();
                var pwd = $("#pwd1").val();
                var email = $("#email").val();
                var data = { 'uid': uid, 'pwd': pwd, 'email': email }
                $.get("/addnew/", { 'uid': uid, 'pwd': pwd, 'email': email }, function (r) { $('#result').html(r) })
            });
        });
    </script>
</body>
</html>
(5)定义视图函数,使用用户信息输入模板newuser.html。
def toAddNew(request):    
    return render(request,'newuser.html')
(6)配置URL访问toAddNew视图函数。
from django.urls import path
from newuser import views
urlpatterns = [
    path('newfirst/', views.toAddNew),
]
(7)定义视图函数检查数据库中是否已存入输入的用户ID。
def doCheckUid(request):
    ps=userinfo.objects.filter(uid=request.GET['uid'])
    if ps.count()==0:
        msg='ID可用'
    else:
        msg='ID已占用'
    return HttpResponse(msg, content_type="text/text;charset=utf-8")
(8)配置URL访问doCheckUid视图函数。
path('checkuid/', views.doCheckUid)
(9)定义视图函数,实现图形验证码(参照实验五)。
def getRandomChar():        #获取随机字符
    num =str(randint(0,9))         #获得随机数字
    lower=chr(randint(97,122))    #获得随机小写字母
    upper=chr(randint(65,90))     #获得随机大写字母
    char=choice([num,lower,upper]) #选择要使用的随机字符
    return char
def createImg(request):    #创建验证码图片返回
    img=Image.new(mode="RGB",size=(160,30),color=(100,100,100))    #创建图片
    draw=ImageDraw.Draw(img)    #获取图片画笔,用于描绘字
    #设置字体,字体文件在项目同名子文件夹中
    font=ImageFont.truetype(font="arial.ttf",size=24)
    code=''
    for i in range(5):
        c=getRandomChar()                   #获得随机字符
        draw.text((10+30*i,2),text=c,fill=(255,255,255),font=font)#根据坐标填充文字
        code+=c                             #记录验证码字符
    request.session['randomcode']=code      #将验证码存入session
    f=open("temp.png",'wb')
    img.save(f, format="png")
    f.close()
    return FileResponse(open("temp.png",'rb'))
(10)客户端获取图形验证码的URL配置如下:
path('getpng/', views.createImg),
(11)通过客户端脚本检查用户输入的验证码是否正确,脚本通过Ajax请求存放在session中的图形验证码字符串,用于与用户输入比对。向客户端返回图形验证码字符串的视图函数代码如下:
def returnCheckCode(request):
    return HttpResponse(request.session['randomcode'], content_type="text/text;charset=utf-8")
(12)配置URL访问returnCheckCode视图函数。
path('checkcode/', views.returnCheckCode),
(13)用户提交数据时,如果数据均有效,则通过Ajax请求将数据提交给服务器。服务器端在视图中将数据存入数据库,视图函数代码如下:
def doAddNew(request):
    try:
        nuid = request.GET['uid']
        pwd = request.GET['pwd']
        nemail = request.GET['email']
        user=userinfo(uid=nuid,password=pwd,email=nemail)
        user.save()
        msg="已成功完成注册!"
        return HttpResponse(msg, content_type="text/text;charset=utf-8")
    except Exception as e:
        msg="意外出错:%s" % e
        return HttpResponse(msg, content_type="text/text;charset=utf-8")
(14)配置URL访问视图函数doAddNew。
path('addnew/', views.doAddNew),
(15)运行开发服务器,测试运行效果。如图所示:
 
 
实验八:自定义User模型
一、实验目的
1、熟练掌握Django工具的相关理论知识,包括:Admin站点、用户认证、发送E-mail、会话控制等;
2、学会在实际的网站开发中使用Django提供的Admin站点和用户认证功能,学会发送E-mail以及使用会话控制。
二、实验器材
微机 + windows操作系统 + Python + Django + Pycharm
二、实验内容
1、本实验综合第八章讲解的知识,创建一个myUser模型,模型除了包含Django默认User模型的所有字段外,还包含QQ号和手机号字段。在项目中使用myUser模型替换默认User模型。在视图中使用myUser模型实现用户登录和新用户注册功能。
2、编译检查语法错误,调试,运行,获得输出结果;
3、独立完成上述内容,并提交书面报告。
四、实验步骤
1、表单的相关知识点回顾
2、创建一个Django项目,如UserDjango项目。
(1)打开pycharm的Terminal界面进入项目目录,执行下面的命令创建应用userdiy。
à python manage.py startapp userdiy
(2)修改userdiy应用中的models.py文件,通过扩展AbstractUser模型来创建自定义的myUser模型,代码如下:
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.core.exceptions import ValidationError
import re
def validate_qq(value):#判断QQ号是否为[5,11]位数字
s=re.match(r"^[1-9]\d{4,10}",value)
if not( s and s.end()==len(value) and len(value)>4):
raise ValidationError('QQ号不正确:%s' % value)
def validate_phone(value):#判断手机号是否正确
s=re.match(r"1[3458]\d{9}",value)
if not( s and s.end()==len(value) and len(value)==11):
raise ValidationError('手机号不正确:%s' % value)
class myUser(AbstractUser):
qq=models.CharField(max_length=11,verbose_name='QQ号',validators=[validate_qq])
phone=models.CharField(max_length=11,verbose_name='手机号',validators=[validate_phone])
(3)修改userdiy应用中的admin.py文件,在Admin站点中注册模型,代码如下:
from django.contrib import admin
from .models import myUser
admin.site.register(myUser) #在Admin站点中注册模型
(4)修改settings.py项目配置文件,添加userdiy应用,并设置AUTH_USER_MODEL变量以使用自定义模型替换默认的User模型,代码如下:
INSTALLED_APPS = [
……
'userdiy',
]
AUTH_USER_MODEL = 'userdiy.myUser'
(5)执行数据迁移操作。
(6)执行以下命令,创建Admin站点的超级用户。
à python manage.py createsuperuser
(7)启动开发服务器,在浏览器中访问http://127.0.0.1:8000/admin,用步骤(6)中创建的超级用户登录,进入Admin站点首页。
页面中的USERDIY代表了项目中的userdiy应用,其下的Users为用户模型。虽然已经使用myUser模型替换了默认的User模型,但Admin站点页面中显示的用户模型名称为默认的User(单数,复数为Users)。
(8)单击Users行中的“Add”链接,进入添加用户页面。在页面下方可看到在模型myUser中添加的QQ号和手机号字段。
(9)输入各个字段数据,创建一个新用户,测试QQ号和手机号字段的自定义校验函数是否正确。
(10)设计登录模板login.html,代码如下:
<center>
使用自定义模型实现的用户登录页面
{% if form.errors %}
<p style="color:red">用户名或密码有错,请重新登录!</p>
{% endif %}
<form method="post" action="{% url 'login' %}">
{% csrf_token %}
<table>
<tr>
<td align="right">用户名:</td>
<td>{{ form.username }}</td>
</tr>
<tr>
<td align="right">密码:</td>
<td>{{ form.password }}</td>
</tr>
</table>
<input type="submit" value="登录">
<input type="hidden" name="next" value="{% url 'change_user' %}">
</form>
<p><a href="{% url 'add_new' %}">新用户注册</a></p>
</center>
(11)定义模型表单myUserForm,用于处理myUser模型的访问数据。
from .models import myUser
from django.forms import ModelForm
class myUserForm(ModelForm): #定义模型表单,用于处理myUser模型
class Meta:
model = myUser
fields = ['username', 'password','email','qq','phone']
#其他字段用默认label
labels = {'username':'用户名', 'password':'密码','email':'Email'}
(12)定义错误列表,用于替代模型表单默认的错误列表,代码如下:
from django.forms.utils import ErrorList
class myErrorList(ErrorList):#自定义错误列表格式
def __str__(self):
return self.todivs()
def todivs(self):
if not self: return ''
return '<div class="errorlist">%s</div>' \
% ''.join(['<div class="error">%s</div>' % e for e in self])
(13)定义添加用户视图。当请求方法为POST时,说明用户从客户端提交数据,此时视图执行保存操作;否则返回空白表单。视图代码如下:
from django.shortcuts import render,redirect
from django.urls import reverse
def add_new(request): #处理添加新用户
msg=''
if request.method == 'POST':
#在用户提交新用户数据时,用数据创建模型表单
mform = myUserForm(request.POST,auto_id=False,error_class=myErrorList)
if mform.is_valid():
#在表单通过验证时执行数据处理
user_name=mform.cleaned_data['username']
password=mform.cleaned_data['password']
u=myUser.objects.filter(username=user_name) #用表单数据查询
mform.save() #将数据存入数据库
#保存模型表单时,密码已明文的方式存入password字段,应通过set_password()方法设置密码
u=myUser.objects.get(username=user_name) #用表单数据查询
u.set_password(password) #正确处理密码字段
u.save() #保存对密码的修改
msg='数据已保存!'
else:
msg='数据有错,请修改后重新提交!'
else:
mform = myUserForm() #创建空白表单
msg='请输入数据添加注册新用户!'
title='新用户注册,<a href="%s">登录</a>'%reverse('login')
return render(request, 'edit_user.html', {'form': mform,'msg':msg,'title':title})
(14)定义修改用户数据视图。当请求方法为POST时,说明用户从客户端提交数据,此时视图使用提交的数据修改用户;否则使用request对象中保存的已登录用户数据创建表单并将其返回给用户。视图代码如下:
from django.contrib.auth.decorators import login_required
@login_required #必须登录后才能修改个人数据
def change_user(request): #处理修改用户数据
if request.method == 'POST':
#提交表单时采用POST方法,用提交的数据修改当前用户
mform=myUserForm(request.POST,auto_id=False,error_class=myErrorList)#创建表单
data_ok=mform.is_valid() #执行表单验证,检查数据是否正确
user_name=request.POST.get('username') #获得提交的用户名
if not data_ok:
#在没有修改用户名时,模型表单会报错,认为已存在相同的用户名
#此时也应使用提交的数据修改用户,下面的语句用于检测这种情况
error_msg='username already exists'
username_error='%s'%mform.errors.get('username')
if username_error.find(error_msg)>-1 and user_name==request.user.username:
name_ok= True #在未修改用户名时,忽略表单报告的用户名重复错误
else:name_ok= False
if data_ok or (name_ok and not data_ok):#数据通过校验时,用其修改当前用户
u=myUser.objects.get(username=request.user.username) #获得要修改的模型对象
#本例中将修改和未修改用户名统一处理,所以在此更改了用户名
u.username=user_name
u.set_password(request.POST.get('password')) #注意密码字段的修改方式
u.email=request.POST.get('email')
u.qq=request.POST.get('qq')
u.phone=request.POST.get('phone')
u.save() #将模型对象数据写入数据库
return redirect(reverse('login')) #完成数据修改后,重定向到登录页面
else:msg='数据有错,请修改后重新提交!'
else:
#请求方法不是POST,说明是通过URL请求,
#此时用request中的已登录用户数据创建表单
username=request.user.username
email=request.user.email
qq=request.user.qq
phone=request.user.phone
data={'username':username, 'password':'','email':email,'qq':qq,'phone':phone}
mform = myUserForm(data,auto_id=False,error_class=myErrorList)#创建表单
mform.errors.clear() #表单会报告已存在同名用户错误,所以在此清楚错误信息
msg='修改当前用户数据'
title='修改用户数据,当前用户名:%s,<a href="%s">登录</a>'\
%(request.user.username,reverse('login'))
return render(request, 'edit_user.html', {'form': mform,'msg':msg,'title':title})
(15)添加用户和修改用户使用同一个模板edit_user.html,模板向用户展示现有数据,并接收用户输入的新数据。模板edit_user.html的代码如下:
<style>
.error {
color: red
}
</style>
{{ title|safe}}<hr>
<form action="" method="post">
{% csrf_token %}
<table>
{{form}}
<tr>
<td colspan="3">
<input type="submit" value="提交" id="submit" />
</td>
</tr>
</table>
</form>
<hr>
<span style="color:red">{{msg|safe}}</span>
(16)配置URL。
from django.contrib import admin
from django.urls import path
from django.contrib.auth import views as auth_views
from userdiy import views as diy_views
urlpatterns = [
path('admin/', admin.site.urls),
path('login/', auth_views.LoginView.as_view(template_name='login.html'),name='login'),
path('add/', diy_views.add_new,name='add_new'),
path('change/', diy_views.change_user,name='change_user'),
]
(17)在浏览器中访问http://127.0.0.1:8000/login/,打开登录页面。
在页面中单击“新用户注册”链接,打开新用户注册页面。
在页面中输入数据,单击“提交”按钮提交数据。当数据有错误时,页面会显示各个字段的错误信息;当输入的数据正确时,数据会被保存进数据库,浏览器会跳转到登录页面。
成功登录后,跳转到用户数据修改页面。页面默认显示了当前用户的数据。数据修改页面和新用户注册页面使用的是同一个模板,所以页面操作完全相同,只是完成数据处理的视图不同。