Django框架
Django 框架是Python Web较早或历史较长,并且稳定、功能齐全的框架。
目前主要用于开发后台管理、服务运维站点平台、云计算运维平台及信息化管理系统等。
django框架适合初级开发人员,快速掌握和使用。对于高级开发人员来说,主要优化其不足的功能。
官方文档:https://docs.djangoproject.com/zh-hans/2.1/
django的重要的版本: 1.x(1.9/1.11), 2.x(2.1, 2.2, 2.3), 3.x(3.0, 3.1, 3.2)
一、Django 入门
【建议】每一个django项目,都有它自己的环境
1.1 安装
基于pip安装
pip install django==2.1
在交互的环境中,验证的django
>>> import django
>>> django.__version__
1.2 django-admin命令
1.2.1 创建项目命令
django-admin startproject mysite
项目结构说明:
- 最外层的: 根目录只是你项目的容器, Django 不关心它的名字,你可以将它重命名为任何你喜欢的名字。
manage.py
: 一个让你用各种方式管理 Django 项目的命令行工具。你可以阅读 django-admin and manage.py 获取所有manage.py
的细节。- 里面一层的
mysite/
包含你的项目,它是一个纯 Python 包。它的名字就是当你引用它内部任何东西时需要用到的 Python 包名。 (比如mysite.urls
). mysite/__init__.py
:一个空文件,告诉 Python 这个目录应该被认为是一个 Python 包。如果你是 Python 初学者,阅读官方文档中的 更多关于包的知识。mysite/settings.py
:Django 项目的配置文件。如果你想知道这个文件是如何工作的,请查看 Django settings 了解细节。mysite/urls.py
:Django 项目的 URL 声明,就像你网站的“目录”。阅读 URL调度器 文档来获取更多关于 URL 的内容。mysite/wsgi.py
:作为你的项目的运行在 WSGI 兼容的Web服务器上的入口。阅读 如何使用 WSGI 进行部署 了解更多细节。
1.2.2 创建应用
django项目的结构:由多个app组成的, 一个app即为一个模块。
django中自带了 admin站点管理、session会话管理、log日志等app应用。
django-admin startapp <应用名称>
当项目创建成功之后,项目中包含了一个 manage.py
脚本,可以执行此脚本也可以执行django-admin
的命令。
python manage.py startapp <应用名>
应用目录结构:
- migrations 包含所有生成当前应用的数据模型迁移文件脚本
- apps.py 应用的配置信息
- admin.py 配置站点下的应用信息 【一般】
- models.py 应用的所有模型类声明所在的脚本 【重点】
- tests.py 应用测试的脚本
- views.py 应用的所有Web接口 【重点】
【重点】views和models的关系
- Django采用 MVC设计思想,设计出自己的MTV
- 在Views中,角色是Controller控制器, 通过Models将数据加载出来,再通过T(emplate)模板将数据渲染出来,最后将渲染后的HTML封装成Response响应对象返回给Django框架
- models 数据模型, 采用了ORM框架,实现数据的CURD操作。同时支持模型之间的外键关联操作。
1.2.3 运行服务
python manage.py runserver
默认启动了 127.0.0.1:8000
Web服务
可以在runserver后面指定 端口:
python manage.py runserver 9000
可以指定ip的绑定的host:
python manage.py runserver 0:9000
0:
表示为0.0.0.0:
,绑定当前host主机的实际IP地址。
在浏览器访问:
- http://localhost:9000
- http://127.0.0.1:9000
- http://10.36.174.32:9000
【注意】修改主工程目录下的settings.py文件
ALLOWED_HOSTS = ['*'] # 白名单
1.2.4 创建Web接口
第一步:创建view处理函数
from django.http import HttpResponse
def index(request):
return HttpResponse('hi, django')
【说明】view处理函数的参数必须包含request,它是 WSGIRequest类的实例,也是HttpRequest的子类。可以从request对象中获取客户端请求的路径以及请求头和body数据。
第二步: 配置路由
方式1: 直接在主路由中配置(主工程包/urls.py)
from login.views import index
from django.urls import path
from django.contrib import admin # 自带的admin应用
urlpatterns = [
path('', index),
path('admin/', admin.site.urls),
]
方式2:创建应用的子路由urls.py(复制主路由的urls.py)
from .views import index
from django.urls import path
urlpatterns = [
path('', index),
]
使用子路由时,必须要做2件事件:
- 将应用模块 添加到 settings.py中的INSTALLED_APPS 列表中 [实际上不需要]
- 将子路由添加到主路由中
修改主urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('user/', include('login.urls')),
path('admin/', admin.site.urls),
]
1.2.5 创建模型类
第一步:配置数据库
采用默认的数据库 sqlite3
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
第二步: 创建模型类
from django.db import models
# Create your models here.
class User(models.Model):
# 默认情况下 存在 id主键
user_id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=20, unique=True)
pwd = models.CharField(max_length=100)
第三步: 配置INSTALLED_APPS
INSTALLED_APPS = [
...
'django.contrib.staticfiles',
'login',
]
login
是应用名
第四步: 生成数据表(模型类)的迁移文件
python manage.py makemigrations
【注意】确认模型类所在的app是否已添加到settings.py的INSTALLED_APPS列表中。
第五步: 执行数据模型类的迁移文件
python manage.py migrate
【注意】第一次迁移时,会自动迁移django自带app下的迁移文件.
【重要】如果修改了模型类, 必须要makemigrations
和migrate
1.2.6 shell调试模型
进入django shell中
python manage.py shell
>>> from login.models import User
>>> User.objects.all()
【注意】objects是什么?
- objects是Model的元类中创建Manage类实例, 也是QuerySet查询结果类实例
- objects提供了对模型的查询相关方法 【非常重要】
1.2.7 模型类操作
查询数据
User.objects.all() 查询所有的数据,返回可迭代的对象(QuerySet实例),元素是模型类的实例对象。
QuerySet实例方法
- all()
- first()
- last()
- get(属性名=属性值) # pk主键列名属性
- delete() # 模型类的实例对象
- filter(属性名=属性值)
- count() 统计记录个数
创建模型类实例
u1 = User(name="disen", pwd="123", phone="17791692095")
u2 = User()
u2.name="jack"
u2.pwd="123"
u2.phone="18999971112"
模型类实例方法
- save() 保存数据
- delete() 删除数据
- refresh_from_db() 同步数据(从数据库的表中更新当前实例的属性)
1.2.8 admin站点管理
参考文档:https://docs.djangoproject.com/zh-hans/2.1/ref/contrib/admin/
django本身提供了admin站点管理应用, 在每一个app中提供了admin.py脚本,可以将当前应用的models.py中模型类,添加到admin站点中,以方便管理员管理模型对应的数据。
第一步: 创建后台管理员账号(超级管理员)
python manage.py createsuperuser
>> username: admin
>> email: 610039018@qq.com
>> password: admin123
>> password (again): admin123
>> Bypass password validation and create user anyway? [y/N]: :y
启动服务之后,可以访问/admin
进入站点后台管理页面。
可以尝试创建后台管理人员账号, 将active
和staff status
勾选上。并添加login应用的管理User模型的权限。
第二步:将login应用中的模型类添加到admin.py中
from django.contrib import admin
from .models import User
# @admin.register(User)
class UserAdmin(admin.ModelAdmin):
list_display = ('user_id', 'name', 'phone', 'email')
list_display_links = ('name', )
list_filter = ('name', 'phone')
list_editable = ('phone', 'email')
search_fields = ('name', 'phone', 'email')
admin.site.register(User, UserAdmin)
修改模型类:
主要添加Field字段参数的blank和verbose_name
class User(models.Model):
# 默认情况下 存在 id主键
user_id = models.IntegerField(primary_key=True, blank=True,verbose_name='用户ID')
name = models.CharField(max_length=20, unique=True,verbose_name='用户名')
pwd = models.CharField(max_length=100, verbose_name='口令')
# 添加手机号和邮箱
phone = models.CharField(max_length=11, null=True, verbose_name='手机', blank=True)
email = models.CharField(max_length=50, null=True, verbose_name='邮箱', blank=True)
def __str__(self):
return f'{
self.user_id } <{
self.name}>'
class Meta:
verbose_name = 'Vip会员'
verbose_name_plural = verbose_name
【站点中显示app应用的中文名称】
第一步:在xxx app的__init__.py
文件中,添加如下代码:
# 自模块下的AppConfig的子类
default_app_config = 'testingapp.apps.TestingappConfig'
第二步:在TestingappConfig
中添加verbose_name属性
class TestingappConfig(AppConfig):
name = 'testingapp'
verbose_name = '自动化测试'
1.2.9 配置多数据库
一个django项目,可以存在多个数据库连接,在settings.py的DATABASES字典对象中配置,如下所示:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
},
'db1': {
'ENGINE': 'django.db.backends.mysql',
'HOST': '180.76.121.47',
'PORT': 3306,
'USER': 'root',
'PASSWORD': 'rootxaqf2101',
'NAME': 'testdb'
}
}
1.2.10 反向生成模型
django-admin或manager.py中提供了 inspectdb命令,可以将已存在的表生成模型类,命令如下:
python manager.py inspectdb --database db1 > testingapp/models.py
连接db1数据库,将库中所有表全部生成模型类,并写入到testingapp应用下的models.py脚本中。
1.2.11 重写Manager
由于,模型类操作时,默认选择default数据库,因此需要重新指定模型类的objects实例的类型,需要先声明一个models.Manager类的子类,并重写get_queryset()方法,如下:
class DB1Manager(models.Manager):
def get_queryset(self):
return self._queryset_class(model=self.model, using='db1', hints=self._hints)
之后,在模型类中,显式地增加objects成员,如下:
class TbPerson(models.Model):
person_id = models.IntegerField(primary_key=True, verbose_name='ID')
phone = models.CharField(max_length=11, blank=True, null=True, verbose_name='手机号')
# ... 省略
objects = DB1Manager() # 指定using为db1数据库的查询集实例
class Meta:
managed = False
db_table = 'tb_person'
verbose_name_plural = verbose_name = '人员信息'
1.2.12 重写模型类之save
对于模型类拥有objects成员,只能用于查询和修改,如果是新增,则需要重写save方法,保证数据写入到正确的数据库中。
class TbPerson(models.Model):
person_id = models.IntegerField(primary_key=True, verbose_name='ID')
phone = models.CharField(max_length=11, blank=True, null=True, verbose_name='手机号')
# ... 省略
objects = DB1Manager()
def save(self, force_insert=False, force_update=False, using=None,
update_fields=None):
return super(TbPerson, self).save(using='db1')
class Meta:
managed = False
db_table = 'tb_person'
verbose_name_plural = verbose_name = '人员信息'
1.3 views视图与模板
1.3.1 请求路径参数
from .views import index, update_user
urlpatterns = [
path('', index),
path('<user_id>/', update_user)
]
def update_user(request, user_id):
return HttpResponse('修改用户ID:%s' % user_id)
1.3.2 模板配置
首先在项目的根目录下,创建一个templates目录,并在settings.py的TEMPLATES配置DIRS模板路径,如下:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
1.3.3 创建模板的html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>更新用户</title>
</head>
<body>
<h3> {
{ user.name }} 用户信息修改</h3>
</body>
</html>
1.3.4 在views渲染模板
在templates目录下创建
def update_user(request, user_id):
# 通过模型将user_id对应的数据表的数据加载到
user = User.objects.get(pk=user_id)
# 将数据渲染到模板中,并返回HttpResponse对象
# render(request, template_name, context= {})
resp = render(request, 'update.html', {
'user': user})
return resp
【练习】查看所有用户信息,显示到模板上
def view_users(request):
# 获取所有的用户信息
users = User.objects.all()
return render(request, 'user_list.html', {
'users': users})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户列表</title>
</head>
<body>
<h3>查询用户结果</h3>
<ul>
{% for u in users %}
<li> {
{ u.id }} - {
{ u.name }} - {
{ u.phone }} </li>
{% endfor %}
</ul>
</body>
</html>
from django.urls import path
from .views import index,update_user, view_users
urlpatterns = [
path('', index),
path('<int:user_id>/', update_user),
path('list/', view_users )
]
【Http404】抛出404异常
def update_user(request, user_id):
# 通过模型将user_id对应的数据表的数据加载到
try:
user = User.objects.get(pk=user_id)
except User.DoesNotExist:
raise Http404('未找到 {}'.format(user_id))
# 将数据渲染到模板中,并返回HttpResponse对象
# render(request, template_name, context= {})
resp = render(request, 'update.html', {
'user': user})
return resp
from django.shortcuts import render, get_object_or_404
def update_user(request, user_id):
user = get_object_or_404(User, pk=user_id)
resp = render(request, 'update.html', {
'user': user})
return resp
1.3.5 模板的url指令
第一步: 在路由中声明url路径时,可以指定name属性(path())
path('<int:user_id>/', update_user, name='update'),
path('list/', view_users, name='ulist')
第二步:在template模板文件中
<a href="{% url 'ulist' %}">查看所有用户</a>
【重要】{% url %} 指令是反向查找路径,好处,无论url路径如何修改,都可以反向获取完整的请求路径。另外格式可以带有namespace:
<a href="{% url 'user:ulist' %}">查看所有用户</a>
user:
代表是include()方法中指定的namespace属性值。
主路由中添加子路由时,可以同时指定的namespace
urlpatterns = [
path('user/', include('login.urls', namespace='user')),
path('admin/', admin.site.urls),
]
但是在子路由urls.py文件中,必须指定app_name
应用名称。
app_name = 'user'
urlpatterns = [
path('', index),
path('<int:user_id>/', update_user, name='update'),
path('user_list/', view_users, name='ulist')
]
1.4 form表单提交
1.4.1 修改模板
<!DOCTYPE html>