准备工作
将不同day下的代码分目录管理,方便后续复习查阅
(testenv) [root@localhost projects]# ls
day01 day02
(testenv) [root@localhost projects]# mkdir day03
(testenv) [root@localhost projects]# cd day03
(testenv) [root@localhost day03]# django-admin startproject mysite3
(testenv) [root@localhost day03]# ls
mysite3 # 今日在mysite3项目进行操作
使用 Pycharm 打开新项目 mysite3,并设置解释器为 testenv 虚拟环境
修改基础配置 settings.py
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware', # 注释掉 csrf
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
# ......
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS':[os.path.join(BASE_DIR,"templates")], #配置模板目录,项目根目录创建templates
# ......
LANGUAGE_CODE = 'zh-Hans' # 配置语言支持
TIME_ZONE = 'Asia/Shanghai' # 配置时区
如:图片、音频、视频、css、js等
静态文件的相关配置也在 settings.py 文件中进行配置
配置静态文件的 访问路径【该配置默认存在】
配置静态文件的存储路径 STATICFILES_DIRS
修改配置文件—settings.py 文件,添加指定参数配置
STATIC_URL = '/static/'
STATICFILES_DIRS = (os.path.join(BASE_DIR, 'static'),) # 注意元组中的逗号
在项目根目录创建 static文件夹
复制一张图放入 image 文件夹,图片可自行寻找(本地或网络均可)
在 mysite3项目/mysite3 创建 views.py 文件,在该文件中编写指定视图函数
from django.shortcuts import render
def test_static(request):
return render(request, "test_static.html")
在 mysite3/templates 中创建 test_static.html 模板文件
Title
p
修改 mysite3/mysite3/urls.py 文件,添加路由配置
from . import views
urlpatterns = [
path('admin/', admin.site.urls),
###day03###
path("test_static", views.test_static),
]
查看服务是否重启,浏览器访问:http://127.0.0.1:8000/test_static,查看模板加载是否成功
修改 mysite3/templates 中的 test_static.html 模板文件,添加 django 加载静态文件的方式
Title
{% load static %}
查看服务是否重启,浏览器访问:http://127.0.0.1:8000/test_static,查看模板加载是否成功
查看网页源代码,django方式加载的图片url路径默认是相对显示的方式
修改 settings.py 文件中的 STATIC_URL 参数
STATIC_URL = '/statics/' # 多了个s
重启服务后再次刷新页面,只有 {% static 'xxx' %} 的方式可以显示
通过查看网页源代码,观察图片地址,发现带有标签的img标签图片地址会更动态
应用在Django项目中是一个独立的业务模块,可以包含自己的路由,视图,模板,模型
用 manage.py 中的子命令 startapp 创建应用文件夹
(testenv) [root@localhost mysite3]# python3 manage.py startapp music
(testenv) [root@localhost mysite3]# ls
db.sqlite3 manage.py music mysite3 static templates
在 settings.py 的 INSTALLED_APPS 列表中配置安装此应用
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'music', # 安装应用
]
migrations文件夹
__init__.py
admin.py
apps.py
models.py
tests.py
views.py
Django中,主路由配置文件(urls.py)可以不处理用户具体路由,主路由配置文件可以做请求的分发(分布式请求处理)。具体的请求可以由各自的应用来进行处理。
语法: include(‘app名字.url模块名’) 作用: 用于将当前路由转到各个应用的路由配置文件的urlpatterns进行分布式处理
应用下手动创建urls.py文件,内容结构同主路由完全一致
修改 mysite3/mysite3/urls.py 主路由文件,修改路由配置
from django.urls import path, include
from . import views
urlpatterns = [
path('admin/', admin.site.urls),
###day03###
path("test_static", views.test_static),
path("music/", include("music.urls")),
]
在 mysite3/music 创建子路由 urls.py 文件,修改路由配置
from django.urls import path
from . import views
urlpatterns = [
# http://127.0.0.1:8000/music/index
path("index", views.index_view),
]
修改 mysite3/music/views.py 视图文件,添加指定视图函数
from django.shortcuts import render
from django.http import HttpResponse
def index_view(request):
return HttpResponse("这是音乐首页")
查看服务是否重启,浏览器访问:http://127.0.0.1:8000/music/index,查看是否响应成功
需求:创建两个应用
创建sport应用并注册
创建news应用并注册
创建分布式路由系统
解题过程
用 manage.py 中的子命令 startapp 创建应用文件夹
(testenv) [root@localhost mysite3]# python3 manage.py startapp sport
(testenv) [root@localhost mysite3]# python3 manage.py startapp news
(testenv) [root@localhost mysite3]# ls
db.sqlite3 manage.py music mysite3 news sport static templates
在 settings.py 的 INSTALLED_APPS 列表中配置安装此应用
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'music',
'news',
'sport',
]
修改 mysite3/mysite3/urls.py 主路由文件,修改路由配置
from django.urls import path, include
from . import views
urlpatterns = [
path('admin/', admin.site.urls),
###day03###
path("test_static", views.test_static),
path("music/", include("music.urls")),
path("sport/", include("sport.urls")),
path("news/", include("news.urls")),
]
在 mysite3/sport 创建子路由 urls.py 文件,修改路由配置
from django.urls import path
from . import views
urlpatterns = [
# http://127.0.0.1:8000/sport/index
path("index", views.index_view),
]
修改 mysite3/sport/views.py 视图文件,添加指定视图函数
from django.shortcuts import render
from django.http import HttpResponse
def index_view(request):
return HttpResponse("这是体育首页")
在 mysite3/news 创建子路由 urls.py 文件,修改路由配置
from django.urls import path
from . import views
urlpatterns = [
# http://127.0.0.1:8000/news/index
path("index", views.index_view),
]
修改 mysite3/news/views.py 视图文件,添加指定视图函数
from django.shortcuts import render
from django.http import HttpResponse
def index_view(request):
return HttpResponse("这是新闻首页")
查看服务是否重启,浏览器访问:http://127.0.0.1:8000/sport/index,查看是否响应成功
应用内部可以配置模板目录
应用下手动创建templates文件夹
settings.py中开启应用模板功能
应用下templates和外层templates都存在时,Django得查找模板规则
在 settings.py 中开启应用模板功能
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, "templates")],
'APP_DIRS': True, # 将改值改为True即可,默认为True
在 mysite3/news/templates 下创建 index.html 模板文件,编写模板内容
新闻首页
我是新闻频道首页
在 mysite3/news/views.py 中修改视图函数 index_view
from django.shortcuts import render
from django.http import HttpResponse
def index_view(request):
# return HttpResponse("这是新闻首页")
return render(request, "index.html")
查看服务是否重启,浏览器访问:http://127.0.0.1:8000/news/index,查看模板加载是否成功
如果此时在外层的 templates 中也创建 index.html 文件
首页
我是首页
查看服务是否重启,浏览器访问:http://127.0.0.1:8000/news/index,查看模板加载结果是否有冲突
ORM(Object Relational Mapping)即对象关系映射,它是一种程序技术,它允许你使用类和对象对数据库进行操作,从而避免通过SQL语句操作数据库
如果此时在外层的 templates 中也创建 index.html 文件,经测试后,会优先找外层文件
解决方式
将应用中存储模板的路径改为:应用下---templates---应用名---index.html
在 mysite3/news/views.py 中修改视图函数 index_view
def index_view(request):
# return HttpResponse("这是新闻首页")
return render(request, "news/index.html") # 修改渲染模板路径,改为APP内部模板路径
看服务是否重启,浏览器访问:http://127.0.0.1:8000/news/index,查看模板加载结果
回顾 Django MTV
模型层:负责跟数据库中间进行通信
安装数据库服务并且创建数据库
(testenv) [root@localhost mysite3]# yum -y install mariadb-server
(testenv) [root@localhost mysite3]# systemctl start mariadb
(testenv) [root@localhost mysite3]# systemctl enable mariadb
(testenv) [root@localhost mysite3]# mysqladmin password
New password: 123456
Confirm new password: 123456
(testenv) [root@localhost mysite3]# mysql -uroot -p123456
MariaDB [(none)]> CREATE DATABASE mysite3 DEFAULT CHARSET utf8;
修改 settings.py 文件
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # 更改数据引擎
'NAME': 'mysite3', # 操作的数据库名称
'USER': 'root', # 连接数据库的用户名
'PASSWORD': '123456', # 连接数据库用户名的密码
'HOST': '127.0.0.1', # 数据库服务所在的主机地址
'PORT': 3306 # 端口号
}
}
测试—python3 manage.py migrate
(testenv) [root@localhost mysite3]# python3 manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying sessions.0001_initial... OK
什么是模型
models.py
对于复杂业务,使用成本较高 根据对象的操作转换成SQL语句,根据查询的结果转换成对象,在映射过程中由性能损失
此示例为添加一个 bookstore_book 数据表来存放图书馆中数目的信息
添加一个 bookstore 的 app
添加模型类并注册 app
# settings.py
INSTALLED_APPS = [
# ......
'bookstore'
]
模型类代码示例:
# file: bookstore/models.py
from django.db import models
class Book(models.Model):
title = models.CharField("书名", max_length=50, default="")
price = models.DecimalField("定价", max_digits=7, decimal_places=2, default=0.0)
数据库迁移
(testenv) [root@localhost mysite3]# python3 manage.py makemigrations
Migrations for 'bookstore':
bookstore/migrations/0001_initial.py
- Create model Book
(testenv) [root@localhost mysite3]# python3 manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, bookstore, contenttypes, sessions
Running migrations:
Applying bookstore.0001_initial... OK
查看数据库,验证指定表是否创建成功
(testenv) [root@localhost mysite3]# mysql -uroot -p123456
MariaDB [(none)]> USE mysite3;
MariaDB [mysite3]> SHOW TABLES;
+----------------------------+
| Tables_in_mysite3 |
+----------------------------+
| auth_group |
| auth_group_permissions |
| auth_permission |
| auth_user |
| auth_user_groups |
| auth_user_user_permissions |
| bookstore_book |
| django_admin_log |
| django_content_type |
| django_migrations |
| django_session |
+----------------------------+
MariaDB [mysite3]> DESC bookstore_book;
+-------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| title | varchar(50) | NO | | NULL | |
| price | decimal(7,2) | NO | | NULL | |
+-------+--------------+------+-----+---------+----------------+
使用 python3 manage.py startapp 应用名称
的方式创建应用,然后要及时的在 settings.py 文件中进行注册
任何关于表结构的修改,务必在对应模型类上修改,例:为 bookstore_book 表添加一个名为 info 的字段,类型是 varchar(100),解决方案:
BooleanField() | CharField() |
---|---|
数据库类型:tinyint(1) | 数据库类型:varchar |
编程语言中:使用True或False来表示值 | 注意:必须要指定max_length参数值 |
在数据库中:使用1或0来表示具体的值 | |
DateField() | DateTimeField() |
数据库类型:date 作用:表示日期 | 数据库类型:datetime |
参数(以下参数只能三选一) | 作用:表示日期和时间 |
1.auto_now:每次保存对象时,自动设置该字段为当前时间 | 参数同DateField |
2.auto_now_add:当对象第一次被创建时自动设置当前时间 | FloatField() |
注意:1和2两个选项取值范围(True/False) | 数据库类型:double |
3.default:设置当前时间(取值:字符串格式时间,如:2019-01-01) | 编程语言中和数据库中都使用小数表示值 |
DecimalField() | IntergerField() |
数据库类型:decimal(x, y) | 数据库类型:int |
编程语言中和数据库中:使用小数表示 | 编程语言和数据库中使用字符串 |
参数: | EmailField() |
1.max_digits:位数总数,包括小数点后的位数,该值必须大于等于decimal_places | 数据库类型:varchar |
2.decimal_places:小数点后的数字数量 | 编程语言和数据库中使用字符串 |
字段选项,指定创建的列的额外信息,允许出现多个字段选项,多个选项之间使用,隔开
primary_key
null
db_column
verbose_name
字段选项样例
default
db_index
unique
使用内部Meta类来给模型赋予属性,Meta类下有很多内建的类属性,可对模型类做一些控制
示例:
模型类-Book 表名 book
模型类-Author 表名 author
解决方式
处理方法
问题2:数据库的迁移文件混乱解决办法
解决方案
基本操作包括增删改查,即(CRUD操作)
CRUD是指在做计算处理时的增加(create),读取查询(read),更新(update)和删除(delete)
ORM CRUD 核心 -> 模型类.管理器对象
修改模型类—bookstore/models.py
# file: bookstore/models.py
from django.db import models
class Book(models.Model):
title = models.CharField("书名", max_length=50, default="", unique=True)
pub = models.CharField("出版社", max_length=50, default="")
price = models.DecimalField("定价", max_digits=7, decimal_places=2, default=0.0)
market_price = models.DecimalField("零售价", max_digits=7, decimal_places=2, default=0.0)
class Meta:
db_table = "book"
class Author(models.Model):
name = models.CharField("姓名", max_length=11)
age = models.IntegerField("年龄", default=1)
email = models.EmailField("邮箱", null=True)
class Meta:
db_table = "author"
数据迁移
(testenv) [root@localhost mysite3]# python3 manage.py makemigrations
(testenv) [root@localhost mysite3]# python3 manage.py migrate
数据库检测
(testenv) [root@localhost mysite3]# mysql -uroot -p123456
MariaDB [(none)]> USE mysite3;
MariaDB [mysite3]> SHOW TABLES;
| author |
| book |
MariaDB [mysite3]> DESC author;
+-------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(11) | NO | | NULL | |
| age | int(11) | NO | | NULL | |
| email | varchar(254) | YES | | NULL | |
+-------+--------------+------+-----+---------+----------------+
MariaDB [mysite3]> DESC book;
+--------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| title | varchar(50) | NO | UNI | NULL | |
| price | decimal(7,2) | NO | | NULL | |
| market_price | decimal(7,2) | NO | | NULL | |
| pub | varchar(50) | NO | | NULL | |
+--------------+--------------+------+-----+---------+----------------+
问题1:当执行 python3 manage.py makemigrations 出现如下迁移错误时的处理方法:
对应中文解释:
错误原因
删除所有migrations里所有的000?_xxxx.py(init.py除外)
删除数据库
重新创建数据库
重新生成migrations里所有的 000?_xxx.py
重新更新数据库
每个继承自models.Model的模型类,都会有一个objects对象被同样继承下来,这个对象叫做管理器对象,数据库的增上改查可以通过模型的管理器实现
Django ORM 使用一种直观的方式把数据库表中的数据表示成Python对象,创建数据中每一条记录就是创建一个数据对象
方案1
MyModel.objects.create(属性1=值1,属性2=值2,...)
成功:返回创建好的实体对象
失败:抛出异常
方案2:创建MyModel实例对象,并调用save()进行保存
在 Django 中提供了一种交互式操作项目叫做 Django Shell,能够在交互模式用项目工程代码执行相应的操作
利用 Django Shell 可以代替编写 view 视图层的代码进行直接操作
注意:项目代码发生变化时,需要重新进入Django Shell
启动方式:
启动 Django Shell(代码发生变化需要重新进入):
(testenv) [root@localhost mysite3]# python3 manage.py shell
>>>
测试 方案1 后查看数据库:
# Django Shell
>>> from bookstore.models import Book
>>> Book.objects.create(title='Python', pub='清华大学出版社', price=20, market_price=25)
# mysql
MariaDB [mysite3]> select * from book;
+----+--------+-------+--------------+-----------------------+
| id | title | price | market_price | pub |
+----+--------+-------+--------------+-----------------------+
| 1 | Python | 20.00 | 25.00 | 清华大学出版社 |
+----+--------+-------+--------------+-----------------------+
测试 方案2 后查看数据库:
# Django Shell
>>> from bookstore.models import Book
>>> b2 = Book(title='Django', pub='清华大学出版社', price=70, market_price=75)
>>> b2.save()
# mysql
MariaDB [mysite3]> select * from book;
MariaDB [mysite3]> select * from book;
+----+--------+-------+--------------+-----------------------+
| id | title | price | market_price | pub |
+----+--------+-------+--------------+-----------------------+
| 1 | Python | 20.00 | 25.00 | 清华大学出版社 |
| 2 | Django | 70.00 | 75.00 | 清华大学出版社 |
+----+--------+-------+--------------+-----------------------+