静态文件及相关配置
1.先编写一个登录功能
1. 创建Django项目并创建一个APP
2. 在urls.py添加一组对应关系
3. 在app的views.py中编写登录核心逻辑
4. 使用入门三件套与前端做交互
2.我们在访问Django框架资源的使用之所以可以拿到数据,是因为提前在urls.py中开设了相应的资源接口
3.静态文件
HTML页面上使用的不经常改变的资源
1.第三方框架文件
2.css文件
3.js文件
4.图片文件
针对静态文件资源,一般都会放在static文件夹内
当static目录下出现很多不同类型的静态文件资源,可以继续分类管理
others文件夹 第三方框架文件
css文件夹 所有的文件
js文件夹 所有的js文件
img文件夹 所有的img文件
4.针对静态文件资源的访问,也需要提前开设相应的接口
在settings.py文件最后一行,添加"""静态文件资源配置"""
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static') #这里static是静态文件存放的目录
] # 列表的形式,因为会有很多的静态文件夹
5.接口前缀
STATIC_URL = '/static/'# 必须以这个前缀为开头才能找到静态文件资源.
例如STATIC_URL = '/xxx/',静态文件是static下的jquery.js文件,想要访问该jquery.js文件
'路径需要填写成 /xxx/jquery.js' # 非常重要
6.动态解析
{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
案例:
1.pycharm创建Django项目 项目名:django_02 app名:app01
2.检查settings.py中 INSTALLED_APPS是否注册app01;修改TEMPLATES中的'DIRS': [os.path.join(BASE_DIR, 'templates')],
3.urls.py中添加login
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('login/', views.login),
]
4.app01目录下views.py中添加login函数
def login(request):
return render(request, 'login.html')# 1.返回给前端浏览器一个登录页面
5.templates中创建login.html
在head中添加
<script src="../static/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>
在body中添加
<div class="container">
<div class="row">
<h1 class="text-center">登录页面</h1>
<div class="col-md-8 col-md-offset-2">
<form action="">
<p>username:<input type="text" name="username" class="form-control"></p>
<p>password:<input type="text" name="password" class="form-control"></p>
<input type="submit" value="登录" class="btn btn-success">
</form>
</div>
</div>
</div>
6.pycharm启动Django项目,访问 http://127.0.0.1:8000/login,但是样式没有访问到
7.设置接口前缀,及静态文件资源配置
在settings.py中,文件末尾设置
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static')
]
8.浏览器再次访问,就可以访问到样式了
9.若修改接口前缀,用到静态文件夹的所有配置都需要跟着修改,此时需要设置动态解析
在login.html的head中重新修改
{% load static %}
<script src="{% static '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>
10.此时修改接口前缀,浏览器访问也能找到静态资源
请求方法
1.GET请求
朝别人索要数据
也可以携带额外的数据,比如访问拉钩网,搜索python岗位,选择工作地点等,虽然是get请求,但是可以携带条件
https://url?aaa=bbb&ccc=ddd
'''?后面的数据,不参与路由匹配'''
上述携带数据的方式有2个限制
1.数据只能是非敏感数据,不能放密码等
2.数据大小有限制,2KB-4KB左右
GET请求没有请求头(HTTP数据格式)
2.POST请求
朝别人提交数据
也可以携带额外的数据
数据都是放在请求体中,可以携带敏感数据,并且数据大小没有限制
3.form表单默认的数据提交方式是get
改成post请求方式
method="post"
action 控制数据的提交地址
方式1:不写,朝当前页面所在的地址提交
方式2:写后缀/index/ 自动补全IP和端口
方式3:切全称,比如https://www.baidu.com/
4.提交post请求,需要去配置文件中注释一行代码
注释掉settings.py中MIDDLEWARE下的'django.middleware.csrf.CsrfViewMiddleware',
request对象方法
request.method # 获取请求方式,结果是纯大写的字符串
request.POST # 获取POST请求发生的普通数据(不包括文件)
request.POST.get()# 默认只获取列表中最后一个数据值
request.POST.getlist() # 获取键对应的整个列表
request.GET """不是GET请求,是获取url后面携带的非敏感数据"""
request.GET.get()# 默认只获取列表中最后一个数据值
request.GET.getlist() # 获取键对应的整个列表
案例:
1.将login.html中复制一行
<p>username:<input type="text" name="username" class="form-control"></p>
2.view.py中修改login函数
def login(request):
if request.method == 'GET':
return render(request, 'login.html')
elif request.method == 'POST':
print(request.POST)#<QueryDict: {'username': ['jason', 'kevin'], 'password': ['123']}>
print(request.POST.get('username'))#kevin
print(request.POST.getlist('username'))#['jason', 'kevin']
print(request.GET)#<QueryDict: {'username': ['jason', 'kevin'], 'password': ['123']}>
print(request.GET.get('username'))#kevin
print(request.GET.getlist('username'))#['jason', 'kevin']
return HttpResponse('收到了')
3.浏览器输入 http://127.0.0.1:8000/login/?username=jason&username=kevin&password=123
4.pycharm查看结果,
"""补充"""
print(request.path)
print(request.path_info) # 前两个用法相同,都是拿到当前的请求路由 /app01/index/
print(request.get_full_path()) # 拿到当前请求的路由和参数 /app01/index/?name=zhang
优化login函数
def login(request):
if request.method == 'POST':
print(request.POST)
return HttpResponse("处理好了")
return render(request, 'login.html')
# 将login这样修改,减少if分支
pycharm连接MySQL
先启动数据库,这里不再多说
创建库和表
CREATE DATABASE day55;
USE day55;
CREATE TABLE userinfo (
id INT PRIMARY KEY auto_increment,
name VARCHAR ( 32 ),
age INT
);
INSERT INTO userinfo ( NAME, age ) VALUES ( 'jason', 18 ),( 'kevin', 25 );
1.查找pycharm提供的database按钮
2.点击左上角+号,选择MySQL
3.第一次连接,点击下面的驱动程序文件
4.配置ip,port,password,连接
5.修改数据内容之后,需要点击绿色箭头提交,才会修改成功
Django连接MySQL
Django默认使用的是sqlite3,一般用于本地测试,功能较少
1.在settings.py中配置数据库信息
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # 指定数据库软件名
'NAME': 'day55', # 指定库名
'USER': 'root',
'PASSWORD': '123456',
'HOST': '127.0.0.1',
'PORT': 3306,
'CHARSET': 'utf8'
}
}
2.指定连接MySQL的模块
Django1.11版本 需要在项目或者应用目录下的__init__.py中添加
improt pymysql
pymysql.install_as_MySQLdb()
Django2.2以上 需要使用mysqlclient模块
pip install mysqlclient
Django orm
ORM:对象关系映射
面向对象中的类 映射成 表
对象 映射成 记录
对象.属性 映射成 字段对应的值
"""
ORM的存在可以让不会使用MySQL的python程序员,使用python的语法简单快捷的操作MySQL
"""
1.先去应用目录下的models.py编写模型类
class User(models.Model): # 类似于定义了表名
# id int primary key auto_increment
id = models.AutoField(primary_key=True) # 类似于定义了主键
# name varchar(32)
name = models.CharField(max_length=32) # 类似定义了普通字段
# pwd int
pwd = models.IntegerField() # 类似于定义了普通字段
2.数据库迁移/同步命令
1.将models中有关数据库的操作记录下来(migrations文件夹)
python3 manage.py makemigrations
2.将操作真正影响到数据库中
python3 manage.py migrate
'''当修改了models.py中与数据库相关的代码,都必须执行上述2条命令'''
# 点击pycharm工具,运行manage.py任务,之后 python3 manage.py就不需要敲了,只需要敲下面,
makemigrations
# 默认是同步是所有的应用,也可以单独指定某个应用
migrate app01
3.数据库中会创建app01.user以及Django相关的表;Django项目下的app01会生成migrations目录,和0001_initial.py文件,里面记录了第1步定义的表结构
3.表的主键在orm中 可以不写,orm会自动帮你添加一个id的主键
如果你不想让主键的名称为id,只能自己写主键
4.只要修改models.py的class User中的内容,然后再执行数据库同步命令,就可以实现对字段的修改.
5.在pycharm里先手动加2条数据
在app01.User中添加 jason,123 和 kevin,321
6.修改view.py文件
from app01 import models # 先导入models
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
# 查询表数据
# select * from user where name='' and pwd=''
# print(models.User.objects.filter())
"""可以用索引取,或者用first取"""
# user_obj = models.User.objects.filter(name=username, pwd=password)[0]
user_obj = models.User.objects.filter(name=username, pwd=password).first()
print(user_obj) # User object (1)
if user_obj:
print(user_obj.id) # 1
print(user_obj.name) # jason
print(user_obj.pwd) # 123
return HttpResponse('登录成功')
return HttpResponse("用户名或密码错误")
return render(request, 'login.html')
7.浏览器输入 http://127.0.0.1:8000/login 输入jason和123
8.查看pycharm的返回的结果
orm语法
1.查
models.User.objects.filter() # 结果可以看成是一个列表套数据对象
models.User.objects.filter().first() # 如何获取对象,可以使用fitrst()方法,如果没有值,会返回None;使用if判断即可
models.User.objects.filter(name=username, pwd=password).query # 查看执行的sql语句
2.增
models.User.objects.create()
案例:
views.py中修改
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
# 新增表数据
models.User.objects.create(name=username, pwd=password)
return HttpResponse('注册成功')
return render(request, 'login.html')
3.改
models.User.objects.filter(id=1).update(name='jasonNB') # 不添加filter就是修改所有
案例:
views.py中修改
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
# 修改表数据
models.User.objects.filter(id=1).update(name='jasonNB')
return HttpResponse('修改成功')
return render(request, 'login.html')
4.删
models.User.objects.filter(id=4).delete() # 不添加filter就是删除所有
案例:
views.py中修改
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
# 删除表数据
models.User.objects.filter(id=4).delete()
return HttpResponse('删除成功')
return render(request, 'login.html')
"""补充"""
# 增
res=models.类名(username=username,password=password)
res.save()
# 改
res=models.表名.objects.filter().first()
res.username=username
res.password=password
res.save()
orm外键关联
1.MySQL中判断表关系
一对多,外键字段建在多的一方;models.ForeignKey(to='被关联的表名',to_field='被关联的表名中得字段')
# 被关联的表中是主键字段,to_field字段可以不写,默认就是主键
多对多,外键字段建在第三张关系表;models.OneToOneField(to='被关联的表名')
一对一,外键字段建在查询频率较高的表中;models.ManyToManyField(to='被关联的表名')
2.ORM
一对多,外键字段建在多的一方
publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
"""Django2.2需要加on_delete=models.CASCADE"""
"""Django1.1不需要添加on_delete=models.CASCADE"""
多对多,外键字段可以直接写在某张表中,orm会自动创建第三张表
authors = models.ManyToManyField(to='Authors')
一对一,外键字段建在查询频率较高的表中
detail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)
"""创建表关系,先将基表创建出来,然后再添加外键字段,且不用考虑先创建被关联表。"""
案例:
# 创建4个表, 分别是 书,出版社,作者,作者详情
书和出版社,是一对多关系
书和作者,是多对多关系
作者和作者详情,是一多一关系
1.在models.py中添加
# 图书表
class Book(models.Model):
title = models.CharField(max_length=64)
"""
max_digits=None, 总位数
decimal_places=None 小数后面的位数
"""
# price decimal(8,2)
price = models.DecimalField(max_digits=8, decimal_places=2)
# 如何创建一对多的关系
# publish_id = models.ForeignKey(to='Publish', to_field='id')
publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE) # 默认是与Publish表的主键建立关系
'''如果是外键字段的话,会自动帮你拼接_id,如果你自己写了,它也会给你拼上'''
# 如何创建多对多的关系
authors = models.ManyToManyField(to='Author')
'''
authors字段是一个虚拟字段,意思是不会在book表中创建出来authors字段,它就是用来告诉django给我创建出来第三张表
'''
# 出版社表
class Publish(models.Model):
title = models.CharField(max_length=64)
addr = models.CharField(max_length=255)
# 作者表
class Author(models.Model):
name = models.CharField(max_length=64)
# author_detail_id = models.OneToOneField(to='AuthorDetail', to_field='id')
# author_detail_id = models.OneToOneField(to='AuthorDetail')
'''如果是外键字段的话,会自动帮你拼接_id,如果你自己写了,它也会给你拼上'''
author_detail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)
'''因为to='AuthorDetail' 加了引号,所以关联外键的时候,创建表的时候顺序不重要.要是去掉了引号,就要小心了,必须先创建被关联表'''
# 作者详情表
class AuthorDetail(models.Model):
phone = models.CharField(max_length=64)
qq = models.CharField(max_length=64)
wechat = models.CharField(max_length=64)
2.执行迁移命令
pycharm打开终端
python3 manage.py makemigrations
python3 manage.py migrate
3.查看数据库
除了上述4张表,还自动创建了app01_book_authors这张多对多的第三张表
"""关联外键时,Django 1.11版本不需要加,Django2.2需要加 on_delete"""
例如 author_detail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)
on_delete
当删除关联表中的数据时,当前表与其关联的行的行为。
models.CASCADE
删除关联数据,与之关联也删除
models.DO_NOTHING
删除关联数据,引发错误IntegrityError
models.PROTECT
删除关联数据,引发错误ProtectedError
models.SET_NULL
删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)
models.SET_DEFAULT
删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)
models.SET
删除关联数据,
a. 与之关联的值设置为指定值,设置:models.SET(值)
b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)