静态文件配置,django连接MySQL,ORM基本操作
静态文件
什么是静态文件
静态文件是不怎么经常变化的文件,主要针对html文件所使用的到的各种资源。
css文件、js文件、img文件、第三方框架文件
django针对静态文件资源需要单独开始一个目录统一存放——static目录
该目录下如果各种类型的文件都多,还可以继续创建目录:
js目录
img目录
utils目录/plugins目录/libs目录/others目录/不创
导入静态文件
我们可以把bootstrap目录直接拷贝到static目录下:
想要用bootstrap里面的功能,必须提前导入一下:
<link rel="stylesheet" href="../static/bootstrap-3.4.1-dist/css/bootstrap.min.css"> <script src="../static/bootstrap-3.4.1-dist/js/bootstrap.min.js"></script>
/..指的是返回上一层目录查找/
我们先写一个登录功能:
views.py
from django.shortcuts import render def login_func(request): # 1.返回html页面 return render(request,'login_page.html')
urls.py
from django.contrib import admin from django.urls import path from app01 import views urlpatterns = [ path('admin/', admin.site.urls), # 定义登录接口 path('login/', views.login_func), ]
login_page.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script> <link rel="stylesheet" href="../static/bootstrap-3.4.1-dist/css/bootstrap.min.css"> <script src="../static/bootstrap-3.4.1-dist/js/bootstrap.min.js"></script> </head> <body> <div class="container"> <div class="row"> <h1 class="text-center">用户登录</h1> <div class="col-md-6 col-md-offset-3"> <form action="/login" method="post"> <p>username: <input type="text" class="form-control" name="name"> </p> <p>password: <input type="text" class="form-control" name="pwd"> </p> <input type="submit" class="btn btn-success btn-block" value="用户登录"> </form> </div> </div> </div> </body> </html>
启动任务,发现样式无法使用:
为什么会出现这种情况?
回想我们在进行资源访问时,我们在地址栏中之所以可以使用路由获取到相应的资源是因为程序员提前开设了资源的接口。
静态文件资源访问,默认情况下无法访问,因为我们没有提前开设静态文件资源的访问接口。
说明:
STATIC_URL = '/static/' # 访问静态文件资源的接口前缀(通行证) STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static'), # 存储静态文件资源的目录名称 ]
接口前缀正确之后,会拿着后面的路径依次去到列表中自上而下查找,一旦找到就返回。
<link rel="stylesheet" href="/static/bootstrap-3.4.1-dist/css/bootstrap.min.css"> <script src="/static/bootstrap-3.4.1-dist/js/bootstrap.min.js"></script>
当修改服务器代码时,浏览器有时候不会做出相应的响应,有可能是浏览器直接拿了之前的缓存来用,可以在浏览器中设置禁用缓存。
禁用缓存方法:
打开控制台,点击右上角settings图标,刚下翻到网络这块的“停用缓存(Disable cache)”,勾上即可。
接口前缀动态匹配
当接口前缀发生变化时,希望仍然能够访问静态文件,可以手动修改导入的静态文件前缀,但是静态文件较多时,手动修改比较麻烦,那么就需要进行动态匹配
{% load static %} //相当于模块导入 <link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}"> <script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
1.action="" 数据默认提交给当前页面所在的地址
2.action="https://www.baidu.com/" 完整地址
3.action="/index/" 朝当前服务端的index地址提交
method 控制数据提交的方法
默认是get
可以改post
请求方法补充
get 朝服务端索要数据,也可以携带一些额外的要求 携带额外数据的方式: URL?xxx=yyy&uuu=zzz 问号后面携带数据的大小是有限制(2KB)的并且不能携带敏感数据 post 朝服务端提交数据 携带额外数据的方式: 请求体 请求体携带数据安全性较高并且没有大小限制
发送post请求时注意事项
1. input标签中要有name属性
2. 浏览器可能会出现如下图所示的403报错
解决上面的报错,发送post请求需要注释掉配置文件中的某一行
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', ]
request.method # 获取请求方式,结果是纯大写的字符串数据
request.POST # 获取post请求请求体里面携带的数据 <QueryDict: {'name': ['alex'], 'pwd': ['123']}> request.POST.get('name') # 获取name列表最后一个数据值 alex request.POST.getlist('name') # 获取name整个列表数据 ['kevin','alex'] request.GET # 获取网址问号后面携带的数据 request.GET.get() # 获取列表最后一个数据值 request.GET.getlist() # 获取整个列表数据
在视图函数中针对不同的请求代码编写套路
from django.shortcuts import render,HttpResponse def login_func(request):
if request.method == 'GET': # 1.返回html页面 return render(request,'login_page.html') elif request.method == 'POST': # 2. 获取post请求请求体里面的数据 return HttpResponse('数据我收到了')
可以简写:
if request.method == 'POST': return HttpResponse() return HttpResponse()
2. 初次连接数据库时会出现黄色的提醒的三角形,提示要下载相应的驱动,填写红色框框里的内容之后可以测试下载的驱动是否可用
- Host:id
- User:用户名
- Password:密码
- Database:要用到的数据库
3. 都设置好了之后可以点击Text Connection进行测试,成功之后应用即可。
1. 修改配置文件
django自带的sqlite3是一个小型的数据库,功能比较少,主要用于本地测试,我们实际项目中都会替换掉它。
要先到settings.py文件中修改相应的配置
修改配置文件:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'day51', 'HOST': '127.0.0.1', 'PORT': 3306, 'USER': 'root', 'PASSWORD': '123', 'CHARSET': 'utf8' } }
此时启动会报错:
2.需要指定模块
django1.X版本需要在项目目录下或者app目录下的__init__.py编写代码
import pymysql pymysql.install_as_MySQLdb()
django2.X及以上都可以直接通过下载mysqlclient模块解决
pip3.8 install mysqlclient
ps:该模块windows下载问题不大,主要是mac电脑可能有问题,参考:https://www.cnblogs.com/yong-wu/p/16967146.html
什么是ORM
ORM:对象关系映射
能够让不会SQL语句的python程序员使用python面向对象的语法来操作数据库
类 | 表 |
对象 | 一条条数据 |
对象点名字 | 数据获取字段对应的值 |
ORM由于高度封装了SQL,所以有时候效率较低,我们需要自己写SQL
1. 先在models.py中编写模型类
# 字段名 = 字段类型 + 约束条件
from django.db import models class GirlsInfo(models.Model): # id int primary key auto_increment id = models.AutoField(primary_key=True) # name varchar(32) name = models.CharField(max_length=32) # age int age = models.IntegerField()
2.执行数据库迁移相关命令
# 命令1:
python38 manage.py makemigrations # 将操作记录到小本本上(migrations)
执行完之后migrations目录下会多出两个文件,会自动记录要进行的操作:
# 命令2:
python38 manage.py migrate # 将操作同步到数据库上
点击database的刷新按钮,会出来一系列的表格(先不用管)
注意:每次在models.py修改了与数据库相关的代码,都需要再次执行上述两条命令
models.GirlsInfo.objects.create(name='alex,age='888') # 创建一条数据,也可以通过前端动态获取
2. 查询数据
models.GirlsInfo.objects.filter() # 查询数据 eg: res = models.GirlsInfo.objects.filter(name=name) # 查询name框中输入的数据,是一个列表 print(res) # [数据对象,] queryset print(res[0]) # 获取到这个对象 print(res[0].id) # 获取对象的id值 print(res[0].name) # 获取对象的name值 print(res[0].age) # 获取对象的age值
3. 修改数据
models.GirlsInfo.objects.filter(id=1).update(name='lucy',age=18) # 将id为1的数据修改为lucy, 18
4. 删除数据
models.GirlsInfo.objects.filter(id=1).delete() # 查询到id为1的数据并删除
小知识点:
- 针对数据对象主键字段的获取可以使用更加方便的 obj.pk获取
- 在模型类中定义双下str方法可以在数据对象被执行打印操作的时候方便的查看
- form表单中能够触发调剂动作的按钮只有两个
<input type='submit'/> <button></button>
数据增删改查功能
1. 数据展示功能
开设接口、获取数据、传递页面、展示数据
view.py
def user_list_func(request): user_data = models.UserInfor.objects.filter() return render(request,'userListPage.html',{'user_data':user_data})
html文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>List</title> {% load static %} <script src="{% static 'jquery-3.6.1.js' %}"></script> <link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}"> <script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script> </head> <body> <div class="container"> <div class="row"> <h1 class="text-center">数据展示页</h1> <div class="col-md-8 col-md-offset-2"> <a href="/user_add/" class="btn btn-success">数据添加</a> <table class="table table-hover table-striped"> <thead> <tr> <th>Id</th> <th>Name</th> <th>Pwd</th> <th class="text-center">Operation</th> </tr> </thead> <tbody> {% for user_obj in user_data %} <tr> <td>{{ user_obj.pk }}</td> <td>{{ user_obj.name }}</td> <td>{{ user_obj.pwd }}</td> <td class="text-center"> <a href="/user_edit/?edit_id={{ user_obj.pk }}" class="btn btn-primary btn-xs">编辑</a> <a href="/user_delete/?delete_id={{ user_obj.pk }}" class="btn btn-danger btn-xs delBtn">删除</a> </td> </tr> {% endfor %} </tbody> </table> </div> </div> </div> <script> $('.delBtn').click(function (){ let res = confirm('确定删除吗') if (res){ }else { return false } }) </script> </body> </html>
2. 数据添加功能
开设接口、获取数据、发送数据、校验数据、录入数据、重定向
view.py
def user_add_func(request): if request.method == 'POST': name_infor = request.POST.get('name') pwd_infor = request.POST.get('pwd') if len(name_infor) == 0 or len(pwd_infor) == 0: return HttpResponse('用户名或年龄不能为空') user_infor = models.UserInfor.objects.filter(name=name_infor) if user_infor: return HttpResponse('用户名已存在') models.UserInfor.objects.create(name=name_infor, pwd=pwd_infor) return redirect('/user_list/') return render(request, 'userAddPage.html')
html文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>add</title> {% load static %} <script src="{% static 'jquery-3.6.1.js' %}"></script> <link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.css' %}"> <script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.js' %}"></script> </head> <body> <div class="container"> <div class="row"> <h1 class="text-center">数据添加页</h1> <div class="col-md-6 col-md-offset-3"> <form action="" method="post"> <p>name: <input type="text" name="name" class="form-control"> </p> <p>pwd: <input type="text" name="pwd" class="form-control"> </p> <input type="submit" value="添加用户" class="btn btn-warning btn-block"> </form> </div> </div> </div> </body> </html>
3. 数据编辑功能
开设接口、后端如何区分所要编辑的数据(问号携带参数)、后端获取用户数据、前端展示默认数据、获取用户并完成更新
view.py
def user_edit_func(request): target_edit_id = request.GET.get('edit_id') if request.method == 'POST': name_infor = request.POST.get('name') pwd_infor = request.POST.get('pwd') if len(name_infor) == 0 or len(pwd_infor) == 0: return HttpResponse('用户名或年龄不能为空') models.UserInfor.objects.filter(pk=target_edit_id).update(name=name_infor, pwd=pwd_infor) return redirect('/user_list/') target_edit_obj = models.UserInfor.objects.filter(pk=target_edit_id)[0] print(target_edit_obj) return render(request, 'userEditPage.html', {'target_edit_obj': target_edit_obj})
html文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>edit</title> {% load static %} <script src="{% static 'jquery-3.6.1.js' %}"></script> <link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.css' %}"> <script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.js' %}"></script> </head> <body> <div class="container"> <div class="row"> <h1 class="text-center">数据编辑页</h1> <div> <form action="" method="post"> <p>name: <input type="text" name="name" class="form-control" value="{{ target_edit_obj.name }}"> </p> <p>pwd: <input type="text" name="pwd" class="form-control" value="{{ target_edit_obj.pwd }}"> </p> <input type="submit" value="编辑用户" class="btn btn-primary btn-block"> </form> </div> </div> </div> </body> </html>
4. 数据删除功能
开设接口、问号携带参数、删除二次确认
view.py
def user_delete_func(request): target_delete_id = request.GET.get('delete_id') models.UserInfor.objects.filter(pk=target_delete_id).delete() return redirect('/user_list/')