0


2.Django 前后端数据交互

文章目录

1. 注册登入项目

项目需求:1.127.0.0.1:8080/regisert进入注册页面2.127.0.0.0:8080/login进入登入页面

2. 项目准备

2.1 新建项目

image-20220302001416163

2.2 结果路径报错问题

修改Templates模板文件的路径拼接文件-->将/改为,

image-20220302001829663

2.3 创建app应用

一个程序必须有一个应用.
在pycharm底部打开终端,输入:pythonmanage.pystartappapp01

image-20220302002007645

2.4 注册app引用

创建的app必须要注册,在settings配置文件中添加注册.setting.py的第33行
INSTALLED_APPS =['django.contrib.admin',
 ····························
    'app02'# 添加app应用名称]

image-20220302002207051

3. 登入功能

需求:在地址栏输入127.0.0.1/login/返回一个登入页面

3.1 路由层

路由层中写路由与视图函数的对应关系.
# urls.pyfrom django.conf.urls import url
from django.contrib import admin

# 0.导入视图模块from app01 import views     

urlpatterns =[
    url(r'^admin/', admin.site.urls),# 1. 路由与视图函数的关系
    url(r'^login/', views.login)]

3.2 视图层

打开app01应用的views.py的视图层,写登入函数.*所有视图函数都需要接收request形参.*使用render函数必须返回request形参.
# views.py# 0. Django 自动导入 render 函数from django.shortcuts import render

# 1.接收request参数deflogin(request):# 2.返回request, 返回登入界面return render(request,'login.html')

3.3 静态文件

1.介绍
静态文件:不会改变的文件.项目中的CSS文件,JavaScript文件,图片,音频文件,第三方框架...都是静态文件.
2. 存放位置
html文件都放在templates目录下.静态文件都放在static目录下.*需要自己手动在项目下创建文件static目录.可以是别的名字,但是别人都使用这个名称,就约定俗成了.
3. 创建目录划分子目录
0.在项目目录下创建static目录1.对静态文件进一步的划分,不同类型的文件存在在不同的子目录当中.
static(需要的时候在创建子目录,可以先不创建子目录)|-js|-css|-img|-其他
4.项目需要的静态文件
前端需要使用到bootstrap框架和jquery库文件.bootstrap是基于jquery使用的,引入bootstrap相关文件前必须先引入jquery库文件.
0.在static下创建js目录.1.将jquery-3.6.6.min.js复制到static的子目录js下.2.将前端框架bootstrap-3.3.7-dist复制到static目录下.
jquery库文件下载地址:https://code.jquery.com/jquery-3.6.0.min.jsbootstrap框架下载地址:https://v3.bootcss.com/getting-started/#downloadbootstrap下载后需要解压

image-20220302153836749

image-20220302172754540

3.4 登入页面

*前端页面代码存放在templates目录中.0.templates下创建login.html文件.1.html中引入jQuery库文件2.html中引入bootstrapcss文件3.html中引入bootstrapjs文件4.写一个简单的登入页面
<!DOCTYPE html><htmllang="en"><head><metacharset="UTF-8"><title>登入页面</title><!--0. 引入jQuery 库文件--><scriptsrc="/static/js/jquery-3.6.0.min.js"></script><!--1. 引入bootstrap css文件--><linkrel="stylesheet"href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css"><!--2. 引入bootstrap js文件--><scriptsrc="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script><style>/* 网页背景 */body{background-image:url("../static/img/3.jpg");/*  不缩放  */background-size: cover;/*  不平铺  */background-repeat: no-repeat;}</style></head><body><divclass="container"><!--标题--><h1class="text-center">登入</h1><!--表单内容--><divclass="row"><divclass="col-md-8 col-md-offset-2"><formaction=""><p><labelfor="d1">用户名称:</label><inputtype="text"id='d1'name="username"class="form-control"></p><p><labelfor="d2">用户密码:</label><inputtype="text"id='d2'name="password"class="form-control"></p><p>性别:
                    <inputtype="radio"name="gender"value="male"> 男
                    <inputtype="radio"name="gender"value="female"> 女
                </p><inputtype="submit"class="btn btn-success btn-block"></form></div></div></div></body></html>

3.5 静态路径开放

静态文件都放在static目录下,后端服务器正常运行下:如果能够看到对应的静态资源,那么就是后端开设了静态文件资源的接口.
0.启动程序后,浏览器输入127.0.0.1:8000/login1.在后端查看信息结论:静态资源无法访问.

image-20220302204546145

1. 令牌
Django的settings.py文件下第122行:#静态urlSTATIC_URL='/static/'STATIC_URL设置的值相当于令牌,访问的路径必须以这个令牌的名称开始.*令牌名字更改了,所有相关的路径都需要改.前端

image-20220302163458198

2. 开放
STATICFILES_DIRS设置静态文件的路径,设置之后便能正常访问静态文件.格式:(在令牌后面设置)STATICFILES_DIRS=[路径1,路径2,...]从前玩后依次从列表中取值,取到则返回,都没有则报错.
# 令牌
STATIC_URL ='/static/'# 设置静态文件的路径
STATICFILES_DIRS =[
os.path.join(BASE_DIR,'static'),]

image-20220302204840173

3. 动态修改
使用模板语法,获取令牌名字,当名字更改了,所有相关的路径都自动改.
{%loadstatic%}<scriptsrc="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js'%}"></script>
<!DOCTYPE html><htmllang="en"><head><metacharset="UTF-8"><title>登入页面</title>
    {% load static %}
    <!--0. 引入jQuery 文件--><scriptsrc="{% static 'js/jquery-3.6.0.min.js' %}"></script><!--1. 引入bootstrap css文件--><linkrel="stylesheet"href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}"><!--2. 引入bootstrap js文件--><scriptsrc="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script></head><body><divclass="container"><!--标题--><h1class="text-center">登入</h1><!--表单内容--><divclass="row"><divclass="col-md-8 col-md-offset-2"><formaction=""><p><labelfor="d1">用户名称:</label><inputtype="text"id='d1'name="username"class="form-control"></p><p><labelfor="d2">用户密码:</label><inputtype="text"id='d2'name="password"class="form-control"></p><p>性别:
                    <inputtype="radio"name="gender"value="male"> 男
                    <inputtype="radio"name="gender"value="female"> 女
                </p><inputtype="submit"class="btn btn-success btn-block"></form></div></div></div></body></html>

image-20220302205934783

测试之后将名字改回来.
# 令牌
STATIC_URL ='/static/'# 设置静态文件的路径
STATICFILES_DIRS =[
    os.path.join(BASE_DIR,'static'),]

3.6 浏览器缓存

在写django项目的时候可能会出现后端代码修改了,前端页面没有变化.常见的情况:1.在用一个端口开了好几个django项目,一直运行的还是第一个gjango项目2.浏览器缓存的问题按下F12进入开发者模式点击设置图片找到netword勾选disablexxxxx禁用缓存刷新页面3.代码有问题.

image-20220302205958581

4. 请求方式

请求方式有两种:1.GET2.POST区别:1.get请求携带数据有大小的限制,大概4kb左右.2.post请求携带数据没有限制.
request对象中存放了请求头的数据.request.method方法获取http请求方式

4.1 GET请求访问服务端

app01/views.ps中添加获取请求方式的代码.
from django.shortcuts import render

# Create your views here.# 1.接收request参数deflogin(request):# 1.1 获取客户端的请求方式print(request.method)# 2.返回request, 返回登入界面return render(request,'login.html')

image-20220302211327391

客户端访问服务端是GET请求.

4.2 GET请求提交表单数据

form表单的action属性值可以指定提交的地址.action值的三种情况:1.不写,默认朝当前所有url提交数据.2.全写,指定详细位置.3.指定后缀/login/
现在不设置action属性的值,在浏览器输入:127.0.0.1:8000/login*当前的url就是我们输入的.

image-20220302212618410

在表单填数据姓名:kid密码:123性别:男写好后点提交.

image-20220302212940728

from表单默认是get方式提交.

4.3 POST请求提交表单

form表单的method属性可以设置请求方式.不设置默认是GET请求.0.修改from表单的提交方式为post,1.浏览器输入:127.0.0.1:8000/login2.写好表单信息后提交数据.
<!--login.html 第21行--><formaction=""method="post">

4.4 Csrf中间件问题

Django提交post请求的时候需要在配置中注释掉Csrf中间键,否则报错403.settings中第MIDDLEWARE=[···#'django.middleware.csrf.CsrfViewMiddleware'···]
没有注释前.

image-20220302214508719

注释掉之后.

image-20220302214753698

post提交表单,表单的数据不会跟当前页面的url后面展示.

4.5 获取POST请求数据

request.POST获取用户提交的post请求中除文件外所有数据数据,字典类型.request.POST.get('xxx')通过get键取值,如果有多个值,优先取最后一个值.request.POST.getlist('xx')如果键对应有多个值则取多个值,返回一个列表.
<!--login.html 第35行 增加一个多选框--><p>爱好:
    <inputtype="checkbox"name="hobby"value="reading"> 看书
    <inputtype="checkbox"name="hobby"value="learning"> 学习
</p>
app01/views.ps中添加代码
from django.shortcuts import render

# Create your views here.# 1.接收request参数deflogin(request):# 1.1 获取客户端的请求方式print(request.method)# 1.2判断请求是否为POSTif request.method =='POST':# 1.3 获取post除文件外所有数据 -->dictprint(request.POST)# 1.4 获取print(request.POST.getlist('gender'))# 2.返回request, 返回登入界面return render(request,'login.html')

image-20220302222410112

image-20220302222540458

GET[02/Mar/202222:24:40]"GET /login/ HTTP/1.1"2001584POST<QueryDict:{'username':['kid'],'password':['123'],'gender':['male'],'hobby':['reading','learning']}>kid['reading','learning'][02/Mar/202222:24:47]"POST /login/ HTTP/1.1"2001584

4.6 获取GET请求数据

request.GET获取用户提交的post请求中除文件外所有数据数据,字典类型.request.GET.get('xxx')通过get键取值,如果有多个值,优先取最后一个值.request.GET.getlist('xx')如果键对应有多个值则取多个值,返回一个列表.
<!--login.html 第21行--><formaction=""method="get">
from django.shortcuts import render

# Create your views here.# 1.接收request参数deflogin(request):# 1.1 获取客户端的请求方式print(request.method)# 1.2判断请求是否为POSTif request.method =='POST':# 1.3 获取post除文件外所有数据 -->dictprint(request.POST)# 1.4 获取数据print(request.POST.get('username'))print(request.POST.getlist('hobby'))# 1.6第一次get请求是没有值的,点击按钮提交from表单,填了则有值否则就空字符串.iflen(request.GET)!=0:# 1.7获取数据print(request.GET)print(request.GET.get('username'))print(request.GET.getlist('hobby'))# 2.返回request, 返回登入界面return render(request,'login.html')

image-20220302223744832

#第一次获取登入页面GET[02/Mar/202222:36:04]"GET /login/ HTTP/1.1"2001583
#第二次提交数据[02/Mar/202222:36:11]"GET /login/?username=kid&password=123&gender=male&hobby=reading&hobby=learning HTTP/1.1"2001583GET<QueryDict:{'username':['kid'],'password':['123'],'gender':['male'],'hobby':['reading','learning']}>kid['reading','learning']

4.7 获取POST后面的数据

deflogin(request):# 1.1 获取客户端的请求方式print(request.method)print(request.GET.get('uuid'))

image-20220304024705744

只要是路径后面有值就能通过GET.get()取到.

5. 连接数据库

image-20220302224558710

如过没有则去plugins插件搜索darabase安装.
Pycharm可以充当很多款数据库软件的客户端.第一次选择数据库后记得下载驱动.

5.1 选择数据库

image-20210811181907356

5.2 安装驱动

点DOwnload

image-20210810222340598

5.3 通信配置

填好了先点Test**测试先是否能成功连通,连接的库必须是提前建立好的.
创建库使用Navicat创建https://blog.csdn.net/qq_46137324/article/details/119303398命令行创建https://blog.csdn.net/qq_46137324/article/details/119150449

image-20210811182447807

5.4 测试成功点ok

image-20210811183104172

5.5 查看数据库

image-20210811183744282

6. Django连接数据库

6.1 数据库配置文件

Django自带一个sqkite3数据库,兼容性不好
Django的数据库配置在settings.py75行
DATABASES={'default':{'ENGINE':'django.db.backends.sqlite3','NAME':os.path.join(BASE_DIR,'db.sqlite3'),}}

6.2 自定义配置

将默认的库修改为MySQL.第一步:settings配置文件修改:
DATABASES ={'default':{'ENGINE':'django.db.backends.mysql','NAME':'db1','USER':'root','PASSWORD':123,'HOST':'127.0.0.1','POST':3306,'CHARSET':'utf8'# 不能使用-}}
第二步:代码声明django默认是使用mysqldb模块连接sqkite3,需要手动改为pymysql模块链接pymysql.安装pip3installpymysql在app01应用下有个__init__,或者任何应用名下书写以下代码
# 0.安装pymysql模块 pip3 install pymysqlimport pymysql
pymysql.install_as_MySQLdb()

image-20220303014611597

7. ORM 操作数据库

ORM的作用能够通过Python面向对象的代码简单快捷的操作数据路.不足之处:封装程度太高,有时候效率低,需要自己写sql语句.
ORM对象关系映射:类--->表对象--->记录对象属性--->记录中的某个字段

7.1 表操作

1.创建表
app应用下面的models.py中创建表.models.py中书写一个类就是创建一个表,这个类必须继承models.Modeld.
from django.db import models

# Create your models here.# 0.创建用户表classUser(models.Model):# 1.创建字段# 1.1 id字段 自增 主键id= models.AutoField(primary_key=True, verbose_name='主键')# 1.2 用户名称字段 char类型 长度32
    username = models.CharField(max_length=32, verbose_name='用户名称')# 1.3 用户密码字段 integer 类型
    password = models.IntegerField(verbose_name='用户密码')
verbose_name字段注释
id=models.AutoField(primary_key=True,verbose_name="主键")等同于idintprimary_keyauto_incrementusername=models.CharField(max_length=32,verbose_name="用户名")等同于usernamechar(32)password=models.IntegerField()等同于passwordint
varchar字段必须指定max_length参数不指定就会直接报错.

image-20220303123452257

2.数据库迁移
创建好表后,需要迁移数据库文件才能生效.
1.pythonmanage.pymakemigrations(简写,运行task的runmanagetask,直接输入makemigrations)2.pythonmanage.pymigrate将操作真正的同步到数据库中.*只要修改了models.py中的更数据库相关的代码就必须重新执行数据库迁移命令*无法迁移的话,检查app是否注册.
pythonmanage.pymakemigrations命令是记录对models.py的所有改动,并且将并记录保存到migrations文件下生成一个文件(默认只有一个__init__.py)

image-20220303114738873

python manage.py migrate 
命令执行migrations里面改动的迁移文件作用到数据库,比如创建数据表,或者增加字段...

image-20220303115007778

orm创建表,会自动加上一个前缀,避免Django项目开发多个应用时,出现表名冲突.
3. id字段
每个表中都需要有一个主键字段,并在一般情况下都叫id字段,在没有定义id字段时,且没有其他的主键,orm会自动创建一个名为id的主键字段.*后续在创建模型表的时候如果主键字段名就叫id,那么主键字段可以省略不写.
classAuthor(models.Model):username=models.CharField(max_length=32)password=models.IntegerField()

7.2 字段操作

1. 增加字段
后续增加的字典要设置值*1.41.51.6一个一个的添加看效果
from django.db import models

# Create your models here.# 0.创建用户表classUser(models.Model):# 1.创建字段# 1.1 id字段 自增 主键id= models.AutoField(primary_key=True, verbose_name='主键')# 1.2 用户名称字段 char类型 长度32
    username = models.CharField(max_length=32, verbose_name='用户名称')# 1.3 用户密码字段 integer 类型
    password = models.IntegerField(verbose_name='用户密码')# 1.4 用户等级
    lv = models.IntegerField(validators='1', verbose_name='用户等级')# 1.5 用户信息
    info = models.CharField(max_length=32, null=True, verbose_name='用户信息')# 1.6 用户等级
    hobby = models.CharField(max_length=32, default='reading', verbose_name='爱好')
每次修改了models.py的信息都要,执行数据库迁移迁移命令.0.pythonmanage.pymakemigrations1.pythonmanage.pymigrate
# 第一钟情况,在终端输入值 1, 添加的字段的值都为1
lv = models.IntegerField(validators='1', verbose_name='用户等级')

image-20220303115600891

您试图在没有默认值的情况下向用户添加不可为空的字段“年龄”;我们不能这样做(数据库需要一些东西来填充现有的行)。请选择修复程序:1)现在提供一个一次性默认值(将在所有现有行上设置此列的空值)2)退出,让我在模型中添加一个默认值。(设置default)0.选择1回车1.输入值
# 第二种情况 设置null=True字段可以为空,不需要提供值,添加的字段全部为空
info = models.CharField(max_length=32, null=True, verbose_name='用户信息')

image-20220303120336081

在检测到为空的时候会有一个警告.
第三情况,设置default默认值,添加的字段全部为默认的值hobby=models.CharField(max_length=32,default='reading',verbose_name='爱好')

image-20220303120753319

image-20220303122944949

后续新增字段执行pythonmanage.pymakemigrations都会增加一个文件.第一次创建的在第一个文件中.

image-20220303122439018

2. 更改字段
# 直接修改代码,后执行数据迁移命令
password = models.CharField(max_length=30, validators='密码')

image-20220303123631583

3. 删除字段
*字段的删除只需要将对应的字段注释掉,(在不写入数据的数据原来的数据还存在,如果写了数据,被注释字段的数据一样被删除,看下的7.4.2)*直接删除字段,对应的数据会全部丢失.(不要轻易的操作删除字段)*操作迁移命令的时候一定要检查自己写的代码,代码搞错了数据会丢失.
#将lv和info注释掉#lv...#info...

image-20220303124216083

image-20220303125917384

字段还存在无法写值
4.字段的查拿眼看
...

7.3 制作脚本

脚本可以是应用下的test.py,可以单独开设的别的py文件.测试环境取manage.py中拷贝前四行代码,然后补上需要的代码.

image-20220303150111798

# 测试模板from django.test import TestCase

import os
import sys

if __name__ =="__main__":# 如果要复制这个模板 django2.settings 改成当前项目名称
    os.environ.setdefault("DJANGO_SETTINGS_MODULE","django2.settings")import django

    django.setup()# 所有代码必须等待环境准备完毕之后才能书写# 0.导入应用下的models模块 这行代码是不允许在配置文件外面from app01 import models
    # ↓ 1.从这开始就是需要测试的代码
先搭建好,等下要测试从数据库中获取数据.

7.4 数据操作

先在Navicat为app01_user添加数据:idusernamepassword1kid1232qz456

image-20220303130033063

*查增都有一个对象.当对象是一条数据的时候可以使用.点方法的方式取值.*改删返回影响的行数.
1. 查看数据
models.表名.objects获取一个表的对象models.表名.objects.all()获取表中所有的信息可以看成是一个列表.models.表名.objects.all()first()获取表中第一条数据models.表名.objects.all()[索引]获取表中第n条数据models.表名.objects.filter(查询条件)获取表中符合条件的所有的信息models.表名.objects.filter(查询条件).first()获取表中符合条件的第一条数据
对象只有一个值的时候使用.方法取值.
from django.test import TestCase

import os
import sys

if __name__ =="__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE","django2.settings")import django

    django.setup()# 所有代码必须等待环境准备完毕之后才能书写# 0.导入应用下的models模块 这行代码是不允许在配置文件外面from app01 import models

    # 获取表数据操作# 1.获取对象
    user_obj = models.User.objects
    print(user_obj)# app01.User.objects# 2.对象的方法# 2.1 对象所有的值print(user_obj.all())"""
    <QuerySet [<User: User object>, <User: User object>, <User: User object>]>
    查询对象  列表套对象     一个<> 代表一天数据
    User: 表名
    User object --> 数据现在是看不见的.
    """

image-20220303152309141

Userobject是获取的数据,无法显示是以为没有对数据进行输出.在应用下的models.py为创建的User类设置__str__魔方反法__srt__在输入时自动触发self.xxxxxx是前面定义过的字段
def__str__(self):return'%s %s'%(self.username, self.password)

image-20220303152251621

# 2.2 获取单个值print(user_obj.all().first())# kid 123print(user_obj.all()[0])# kid 123print(user_obj.all()[1])# qz 456

image-20220303153311516

# 2.3 按条件查询表中信息等到一个对象
    user_obj2 = models.User.objects.filter(username='kid')# 等于 select * from User where username = 'kid';print(user_obj2)# <QuerySet [<User: kid 123>]>print(user_obj2.all())print(user_obj2.first())print(user_obj2[0])

image-20220303154405518

    res = models.User.objects.first()print(res)# kid 123print(res.username)# kidprint(res.password)# 123

image-20220303212338893

2. 增加数据
*被删除的字段信息和信息被删除models.表名.objects.create(字段=值,字段=值)添加数据
# 3.增加数据
    models.User.objects.create(username='hh', password='000')

image-20220303155921889

3. 修改数据
models.表名.objects.filter(查询条件).update(更改的字段=值,更改的字段=值)
models.表名.objects.update(更改的字段=值,更改的字段=值)修改符合添加的数据models.表名.objects.filter(查询条件).update(更改的字段=值,更改的字段=值)修改整张表
# 4.修改数据 # 修改整张表
    models.User.objects.update(username='qq', password=123)

image-20220303192847242

# 修改符合添加的数据
    models.User.objects.filter(id=1).update(username='kid')

image-20220303193908322

4. 删除数据
models.表名.objects.delete()删除整张表的数据models.表名.objects.filter(删除的条件).delete()删除符合条件的数据
# 5.删除数据
    models.User.objects.filter(id=5).delete()

image-20220303194330486

5. 返回对象
*查增都有一个对象.当对象是一条数据的时候可以使用.点方法的方式取值.*改删返回影响的行数.
# 查第一条数据
    res = models.User.objects.first()print(res, res.id, res.username, res.password)

image-20220303214955483

# 添加一条数据
    res = models.User.objects.create(username='xx', password='111')print(res, res.id, res.username, res.password)

image-20220303215140343

# 返回被修改的行数
    res = models.User.objects.filter(id=2).update(username='qwe', password=456)print(res)

image-20220303215500964

# 删除一条数据
    res = models.User.objects.filter(id=2).delete()print(res)

image-20220303215630539

6. 单独更新数据
# 表中第一条数据
    obj = models.User.objects.first()# 对象可以使用方法取值也能改值# 修改值
    obj.username ='sb'
    obj.password =666# .save() 更新到数据库中
    obj.save()

image-20220304015335323

8.前后端数据校验

读取数据库中的值,与提交的数据进行比对.
0.前端POST请求提交数据.1.后端从数据库中读取数据&检验数据
<!--login.html 第21行 修改请求方式--><formaction=""method="post"><!--login.html 第31-38行 删除 -->

image-20220303135952710

8.1 登入页面

<!DOCTYPE html><htmllang="en"><head><metacharset="UTF-8"><title>登入页面</title>
    {% load static %}
    <!--0. 引入jQuery 文件--><scriptsrc="{% static 'js/jquery-3.6.0.min.js' %}"></script><!--1. 引入bootstrap css文件--><linkrel="stylesheet"href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}"><!--2. 引入bootstrap js文件--><scriptsrc="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script></head><body><divclass="container"><!--标题--><h1class="text-center">登入</h1><!--表单内容--><divclass="row"><divclass="col-md-8 col-md-offset-2"><formaction=""method="post"><p><labelfor="d1">用户名称:</label><inputtype="text"id='d1'name="username"class="form-control"></p><p><labelfor="d2">用户密码:</label><inputtype="text"id='d2'name="password"class="form-control"></p><inputtype="submit"class="btn btn-success btn-block"></form></div></div></div></body></html>

8.2 数据检验

视图函数中需要导入应用下的models模块,来获取数据库的数据.
1.获取前端的数据
# 前后端数据校验# 0.1 导入render函数from django.shortcuts import render
# 0.2 导入app应用的models模块from app01 import models

# 0.0 视图函数 -->  写逻辑deflogin(request):# 1.1 获取请求方式  --> GET & POSTprint(f'请求方式为{request.method}')# 1.2 判断请求方式:if request.method =='POST':# 2.0 获取POST请求的数据
        username = request.POST.get('username')
        password = request.POST.get('password')print(f'账户:{username}, 密码:{password}')return render(request,'login.html')

image-20220303140603981

第二次测试时遇到一个未知问题,前端页面反馈这行报错,无法展示网页.我想把这行这行注释,然后就正常了,我在接触注释之前的报错也没出现.

image-20220303201850401

2.获取后端数据&检验
# 3.0 获取后端所有的数据 (不推荐)
        user_obj = models.User.objects.filter()print(user_obj,type(user_obj))# 4.在User.py 类中添加 __str__ 方法 来展示 获取的数据

image-20220303200529090

# 3.0 获取后端的数据 以用户输入的数据作为查询数据库的依据 (推荐)
        user_obj = models.User.objects.filter(username=username, password=password)print(user_obj,type(user_obj))# 4.在User.py 类中添加 __str__ 方法 来展示 获取的数据

image-20220303200823484

# 前后端数据校验# 0.1 导入render函数from django.shortcuts import render
# 0.2 导入app应用的models模块from app01 import models

# 0.0 视图函数 -->  写逻辑deflogin(request):# 1.1 获取请求方式  --> GET & POSTprint(f'请求方式为{request.method}')# 1.2 判断请求方式:if request.method =='POST':# 2.0 获取POST请求的数据
        username = request.POST.get('username')
        password = request.POST.get('password')print(f'账户:{username}, 密码:{password}')# 3.0 获取后端的数据
        user_obj = models.User.objects.filter(username=username, password=password)print(user_obj,type(user_obj))# 4.0在User.py 类中添加 __str__ 方法 来展示 获取的数据# 5.判断 user_obj 是否为空, 在查询到值的时候,坑定不为空,只有在匹配不到值的时候才为空if user_obj:print('登入成功...')else:print('账户或密码错误...')return render(request,'login.html')
3.测试
第一次输入正确的账户密码.

image-20220303202139910

第二次输入错误的信息.

image-20220303202245431

可以放回一个页面就不弄了.

9. 注册功能

开设一个注册功输入127.0.0.1:8000/regisert进入一个注册页面0.form表单中需要获取用户名和密码.字段为id(自增的)usernamepassword*hobby字段不用管了.

9.1 路由成

路由层中写路由与视图函数的对应关系.
# 在urls.py中添加
url(r'^register/', views.reg),

9.2 视图层

打开app01应用的views.py的视图层,写注册函数.*所有视图函数都需要接收request形参.*使用render函数必须返回request形参.
# 注册defregister(request):return reder(request,'register.html')

9.3 注册页面

在templates创建register.html
复制登入页面的代码,简单的修改一下.(看图)
<!DOCTYPE html><htmllang="en"><head><metacharset="UTF-8"><title>注册页面</title>
    {% load static %}
    <!--0. 引入jQuery 文件--><scriptsrc="{% static 'js/jquery-3.6.0.min.js' %}"></script><!--1. 引入bootstrap css文件--><linkrel="stylesheet"href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}"><!--2. 引入bootstrap js文件--><scriptsrc="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script></head><body><divclass="container"><!--标题--><h1class="text-center">登入</h1><!--表单内容--><divclass="row"><divclass="col-md-8 col-md-offset-2"><formaction=""method="post"><p><labelfor="d1">用户名称:</label><inputtype="text"id='d1'name="username"class="form-control"></p><p><labelfor="d2">用户密码:</label><inputtype="text"id='d2'name="password"class="form-control"></p><inputtype="submit"class="btn btn-success btn-block"value="注册"></form></div></div></div></body></html>

image-20220303204058890

9.4 获取前端数据

0.获取post方式提交的数据.1.将信息写入数据库中.
# 注册defregister(request):# 6.1 获取请求方式  --> GET & POSTprint(request.method)# 6.2 判断请求方式:if request.method =='POST':# 7.0 获取前端数据
        in_username = request.POST.get('username')
        in_password = request.POST.get('password')
        in_hobby = request.POST.get('hobby')# 8.0 写入数据 
        models.User.objects.create(
            username=in_username, password=in_password, hobby=in_hobby)# 9.0 提示注册成功了 在前面导入HttpResponsereturn HttpResponse('注册成功!')return render(request,'register.html')

image-20220303211210067

image-20220303211141174

# 返回值就是当前被创建对象的本身,可以使用点的方式取值
res = models.User.objects.create(username=username, password=password)print(res, res.username, res.password)

image-20220303211310554

image-20220303211653199

10. 编辑功能

要求:0.展示所有的用户信息.1.点击修改按钮跳转到修改页面,页面中展示用户名和密码2.完成后写入数据库.
后端从数据库读取信息传递到前端.0.后端获取数据库所有的数据1.后端将数据传入locals()名称空间中2.前端使用模板语法获取名称空间中的数据

10.1 路由层

路由层中写路由与视图函数的对应关系.
# 在urls.py中添加路由与视图函数的关系.
url(r'^edit', views.edit),

10.2 视图层

# 编辑defedit(request):# 获取数据库中所有数据
    queryset = models.User.objects.all()return render(request,'edit.html',locals())
queryset中有所有的数据信息locals()获取当前名称空间所有变量render()可以将其他数据传给前端

10.3 编辑页面

在templates创建edit.html.

image-20220303222520087

模板语法的for循环{%forobjinqueryset%}obj.方法获取值(循环一次执行一次){%endfor%}
<!DOCTYPE html><htmllang="en"><head><metacharset="UTF-8"><title>编辑页面</title><!-- 导入需要的文件  动态获取令牌 -->
    {% load static %}
    <!--0. 引入jQuery 文件--><scriptsrc="{% static 'js/jquery-3.6.0.min.js' %}"></script><!--1. 引入bootstrap css 文件--><linkrel="stylesheet"href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}"><!--2. 引入bootstrap js 文件--><scriptsrc="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script></head><body><div><h1class="text-center">用户数据</h1><!-- 栅格布局 --><divclass="row"><!-- 一共12格 用6格 右移3格 --><divclass="col-md-6 col-md-offset-3"><tableclass="table table-striped table-hover"><!-- 表头 --><thead><!-- 一个tr 一行 --><tr><th>ID</th><th>姓名</th><th>密码</th><th>编辑</th></tr></thead><!-- 表数据 --><tbody>
                {% for obj in queryset %}
                    <!-- 一个tr 一行 有多少行就有多少行 --><tr><td>{{ obj.id }}</td><td>{{ obj.username }}</td><td>{{ obj.password }}</td><td><ahref=""class="btn btn-primary btn-xs">编辑</a><ahref=""class="btn btn-danger btn-xs">删除</a></td></tr>
                {% endfor %}
                </tbody></table></div></div></div></body></html>

image-20220303232033486

10.4编辑数据

1. a标签跳转网页
点击编辑按钮,提交get请求,携带当前用户的id值到后端.a便签可以跳转使用本地的路由.
<ahref="/edit_user/?user_id={{ user_obj.id }}"class="btn btn-primary btn-xs">编辑</a>
/edit_user/?user_id={{user_obj.id}}edit_user是地址user_id={{user_obj.id}}?号后面跟着user_id=当前编辑所在行的id/edit_user/?user_obj.id=1以get请求方式向edit_user提交数据
2. 路由层
# urls.py# 4. 单个用户数据
    url(r'^edit_user/', views.edit_user),
3. 视图层
edit_id=request.GET.get('user_id')获取需要修改的用户id.
# 编辑用户信息defedit_user(request):# 请求方式print(f'请求方式{request.method}')
    user_id = request.GET.get('user_id')# 获取idprint(request.GET)print(user_id)# 通过id 获取数据库中的 数据
    edit_queryset = models.User.objects.filter(id=user_id).first()return render(request,'edit_user.html',locals())# 将当前名称空间的变量传给前端
4. 编辑用户数据页面
value="{{edit_querySet.username}}#展示用户的数据做为修改的参考
<!DOCTYPE html><htmllang="en"><head><metacharset="UTF-8"><title>编辑用户数据</title>
    {% load static %}
    <!--0. 引入jQuery 文件--><scriptsrc="{% static 'js/jquery-3.6.0.min.js' %}"></script><!--1. 引入bootstrap css文件--><linkrel="stylesheet"href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}"><!--2. 引入bootstrap js文件--><scriptsrc="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script></head><body><div><h1class="text-center">{{ edit_queryset.username }}的数据</h1><divclass="row"><divclass="col-md-6 col-md-offset-3"><formaction=""method="post"><p>用户名称:
                        <inputtype="text"name="username"class="form-control"value="{{ edit_queryset.username }}"></p><p>用户密码:
                        <inputtype="text"name="password"class="form-control"value="{{ edit_queryset.password }}"></p><p><inputtype="submit"class="btn btn-danger btn-block"value="确定修改"></p></form></div></div></div></body></html>

image-20220304011124324

1.选择一个用户的编辑按钮,编辑按钮是一个a标签,点了a标签相当于在当前url输入了127.0.0.1:8000/edit_user/?user_obj.id=xx2.通过路由层执行对应的视图函数3.视图函数,获取get请求的数据依据数据去数据库中读取信息返回一个编辑用户的页面和当前名称空间的变量4.前端页面使用模板语法获取后端的值

image-20220304010305348

5.确定修改
编辑用户数据的页面点击确定修改后,向后端发送POST请求.从POST请求中获取用户名称和密码.更新数据库中的值,在跳转到编辑页面edit.html去.

image-20220304011328070

models.User.objects.filter(id=edit_id).update(username=username,password=password)更新数据.
# 编辑用户信息defedit_user(request):# 判断请求方式print(f'请求方式{request.method}')
    user_id = request.GET.get('user_id')# 获取idprint(request.GET)print(user_id)if request.method =='POST':# 获取POST数据
        username = request.POST.get('username')
        password = request.POST.get('password')# 更新数据库
        models.User.objects.filter(id=user_id).update(username=username, password=password)return redirect('/edit/')# 通过id 获取数据库中的 数据
    edit_queryset = models.User.objects.filter(id=user_id).first()# print(edit_queryset)return render(request,'edit_user.html',locals())

image-20220304014647460

10.5 删除功能

要求:0.点击删除按钮跳转到删除页,页面中展示用户名和密码1.确定删除后写入数据库.
后端从数据库读取信息传递到前端.0.后端获取数据库所有的数据1.后端将数据传入locals()名称空间中2.前端使用模板语法获取名称空间中的数据
1. a标签跳转网页
点击删除按钮,提交get请求,携带当前用户的id值到后端.
<ahref="/delete_user/?user_id={{ obj.id }}"class="btn btn-danger btn-xs">删除</a>
2. 路由层
# 5.删除用户数据
    url(r'^delete_user/', views.delete_user),
3. 视图层
# 删除用户信息defdelete_user(request):return render(request,'delete_user.html')
4. 删除页面
在templates下的edit.html的删除标签.
0.删除页面复制编辑页面的代码,添加input的disabled数据,让input框不可选中.1.修改按钮的名称.
<!DOCTYPE html><htmllang="en"><head><metacharset="UTF-8"><title>删除用户</title>
    {% load static %}
    <!--0. 引入jQuery 文件--><scriptsrc="{% static 'js/jquery-3.6.0.min.js' %}"></script><!--1. 引入bootstrap css文件--><linkrel="stylesheet"href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}"><!--2. 引入bootstrap js文件--><scriptsrc="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script></head><body><div><h1class="text-center">{{ del_queryset.username }}的数据</h1><divclass="row"><divclass="col-md-6 col-md-offset-3"><formaction=""method="post"><p>用户名称:
                        <!-- 添加 disabled 不可选--><inputtype="text"name="username"class="form-control"value="{{ del_queryset.username }}"disabled></p><p>用户密码:
                        <!-- 添加 disabled 不可选--><inputtype="text"name="password"class="form-control"value="{{ del_queryset.password }}"disabled></p><p><inputtype="submit"class="btn btn-danger btn-block"value="确定删除"></p></form></div></div></div></body></html>

image-20220304022609576

5. 获取用户数据
在视图函数中写业务逻辑
# 删除用户信息defdelete_user(request):# 请求方式print(f'请求方式{request.method}')
    user_id = request.GET.get('user_id')print(user_id)
    queryset = models.User.objects.filter(id=user_id).first()return render(request,'delete_user.html',locals())

image-20220304022807374

6. 删除用户数据
删除用户数据的页面点击确定删除之后,向后端发送POST请求.从POST请求,POST后面跟着这个数据在数据中的id.通过id删除数据,在跳转到编辑页面edit.html去.
# 删除用户信息defdelete_user(request):# 请求方式print(f'请求方式{request.method}')
    user_id = request.GET.get('user_id')print(user_id)if request.method =='POST':# 删除数据
        models.User.objects.filter(id=user_id).delete()return redirect('/edit/')

    del_queryset = models.User.objects.filter(id=user_id).first()return render(request,'delete_user.html',locals())

image-20220304023323846

7.删除注意点
0.真正的删除功能应该需要二次确认,1.删除数据内部其实并不去真正的数据.为数据添加一个标识字段来表示当前数据是否被删除了.如果数据被删了仅仅只是将字段修改了一个状态userbanepasswordis_deletekid1230qz4561查询数据时过滤is_delete=0后续使用模板语法的if语句之后都不真删数据了.

11. ORM建立表关系

book(图书)publish(出版社)idtitlepriceidnameaddr1linux123.01上海出版社上海2python456.02北京出版社北京author(作者)authordetail(作者详情)idnameageidphoneaddr1kid18110086上海2qz19110010北京

0.先创建所有的表,与基础字段,1.后分析关系添加外键字段.

11.1创建表基表

# 2.图书图书表classBook(models.Model):# 2.1 id字段自动创建# 2.2 书名
    title = models.CharField(max_length=32, varbose_name='书名')# 2.2 价格      双精度小数    最大 数 = 8 位   小数_位 = 2
    price = models.DecimalField(max_digits=8, decimal_places=2, varbose_name='价格')# 3.出版社classPublish(models.Model):# 3.1 id字段自动创建# 3.2 出版社名字
    name = models.CharField(max_length=32, varbose_name='出版社名称')# 3.3 出版社地址
    addr = models.CharField(max_length=32, varbosr_name='出版社地址')# 4.作者基本信息classAuthor(models.Model):# 4.1 id 字段自动创建# 4.2 作者姓名
    name = models.CharField(max_length=32, varbose_name='作者名字')# 4.3 作者年龄
    age = models.IntegerField(varbose_name='作者年龄')# 5. 作者详情表classAuthorDetail(models.Model):# 5.1 id 字段自动创建# 5.2 电话
    phone = models.CharField(max_length=32, varbose_name='作者电话')# 5.3 地址
    addr = models.CharField(max_length=32, varbose_name='作者地址')

11.2 确定关系

*表与表之间:一对一,一对多,多对多,关系判断:换位思考.

image-20220304150327851

0.书与出版社:书能被多个出版社出版吗X(不抬杠)出版社能出版多本书吗√出版社一对多图书外键建在多的一方(图书这边建外键)

image-20220304151115970

1.书与作者:书可以被多个作者著作√多个作者可以著作一本书√书与作者多对多的关系,外键建在查询频率高的一方(图书中建立外键),ORM会自动创建第三张表。

image-20220304151529907

2.作者与作者详情:一个作者可以有个信息X一个信息可以给多个作者X作者与作者信息有关系✓一对一关系,外键建在查询频率高的一方(作者表)。

11.3 建立外键的方法

#一对多外键=models.ForeignKey(to='被关联表')#一对一外键=models.OneToOneField(to="被关联表")*ForeignKey与OneToOneField会自动在字段中添加_id后缀,也就是默认关联主键id多对多:虚假字段=models.ManyToManyField(to="被关联表")在Django1.x版本中外键默认都是级联更新,级联删除的。
多对多注意点:书和作者是多对多的关系,外键字段建在任意一方都可以,推荐键在查询频率高的一方,ORM会自动自动创建第三张表.设置的外键是一个虚拟的字段主要是用来告诉ORM书表和作者表是多对多的关系,让ORM自动创建第三张表,在book下建立名称就是app02_book_authors虚拟的表中存(主键idbook_idauthor_id)三个字段.

11.4 建立外键

0.出版社一对多图书-->外键建在多的一方(图书表中建外键)

image-20220304170029439

1.书与作者多对多的关系-->外键建在查询频率高的一方(图书中建立外键),ORM会自动创建第三张表。

image-20220304170324077

2.作者一对一作者详情-->外键建在查询频率高的一方(作者表)。

image-20220304170405390

# 2.图书图书表classBook(models.Model):# 2.1 id字段自动创建# 2.2 书名
    title = models.CharField(max_length=32, varbose_name='书名')# 2.2 价格      双精度小数    最大 数 = 8 位   小数_位 = 2
    price = models.DecimalField(max_digits=8, decimal_places=2, varbose_name='价格')# 2.3 外键 默认关联出版社的主键 --> id
    publish_id = models.ForeignKey(to='Publish')# 2.4 外键 ORM会自动自动创建第三张表
    author = models.ManyToManyField(to='Author')# 3.出版社classPublish(models.Model):# 3.1 id字段自动创建# 3.2 出版社名字
    name = models.CharField(max_length=32, varbose_name='出版社名称')# 3.3 出版社地址
    addr = models.CharField(max_length=32, varbosr_name='出版社地址')# 4.作者基本信息classAuthor(models.Model):# 4.1 id 字段自动创建# 4.2 作者姓名
    name = models.CharField(max_length=32, varbose_name='作者名字')# 4.3 作者年龄
    age = models.IntegerField(varbose_name='作者年龄')# 4.4 外键 默认绑定作者表详情表的主键 --> id
    AuthorDetail_id = models.OneToOneField(to='AuthorDetail')# 5. 作者详情表classAuthorDetail(models.Model):# 5.1 id 字段自动创建# 5.2 电话
    phone = models.CharField(max_length=32, varbose_name='作者电话')# 5.3 地址
    addr = models.CharField(max_length=32, varbose_name='作者地址')

11.4数据库迁移

0.pythonmanage.pymakemigrations1.pythonmanage.pymigrate

image-20220304165225255

标签: css 前端 css3

本文转载自: https://blog.csdn.net/qq_46137324/article/details/123267902
版权归原作者 开局签到Python基础 所有, 如有侵权,请联系我们删除。

“2.Django 前后端数据交互”的评论:

还没有评论