Django 入门范例

1. Django 介绍

2. Django 环境搭建

3. 模型(Model)

4. 站点管理

5. 视图(View)

6. 模板(Template)

 

 

1. Django 介绍

MVC 模型

  • 大部分开发语言中都有 MVC 开发模型。
  • MVC 框架的核心思想是:解耦——降低各功能模块之间的耦合性,方便变更,更容易重构代码,最大程度上实现代码的重用。
  • M 表示 Model,主要用于对数据库层的封装。
  • V 表示 View,用于向用户展示结果。
  • C 表示 Controller,是核心,用于处理请求、获取数据、返回结果。

MVT 模型

  • Django 是一款 python 的 web 开发框架。
  • 与 MVC 有所不同,属于 MVT 框架。
  • M 表示 Model,负责与数据库交互。
  • V 表示 View,是核心,负责接收请求、获取数据、返回结果。
  • T 表示 Template,负责呈现内容到浏览器。

 

Django 开发流程范例

  1. 安装配置 Django 的运行环境。
  2. 创建项目、创建应用。
  3. 在应用的 model.py 定义模型类,执行迁移,生成对应的数据表(可使用简单 API 与数据库交互测试)。
  4. 使用 Django 的后台管理界面维护数据。
  5. 在应用的 views.py 定义视图,即处理核心逻辑的函数。
  6. 在项目目录下创建对应应用的模板目录,编写 html 页面。
  7. 在项目和应用的 urls.py 中配置 URL 与视图的映射。
  8. 通过视图接收指定 URL 的访问请求,通过模型操作数据,通过模板填充数据并完成页面展示。

 

2. Django 环境搭建

1)安装 Django

1.8.2 版本是一个稳定性高、使用广、文档多的版本:

pip.exe install django==1.8.2

进入 python shell,查看版本:

>>> import django
>>> django.get_version()
'1.8.2'

2)创建工程项目

执行如下命令:自定义项目名称并创建基本的工程目录

E:\>django-admin startproject DjangoDemo

项目名称 DjangoDemo 中的目录说明

  • manage.py:一个命令行工具,可以使你用多种方式对 Django 项目进行交互。
  • DjangoDemo:与我们命名的项目名称一致,真正的本项目 python 包。
  • _init _.py:一个空文件,它告诉 python 这个目录应该被看做一个 python 包。
  • settings.py:项目的配置。
  • urls.py:项目的 url 声明。
  • wsgi.py:项目与 wsgi 兼容的 web 服务器入口。

3)创建应用

在一个项目中可以创建一到多个应用,一个应用专门处理一种业务。

在项目根目录下,执行创建应用的命令:

python manage.py startapp hero_book

应用的目录结构如下图:

  • migrations 包:根据模型类生成 SQL 语句,并作用到对应的数据库。
  • admin.py:对本应用进行相关的管理。
  • models.py:定义模型类(有多少个数据表,就有多少个模型类与之对应)。
  • tests.py:Django 自带的测试模块。
  • views.py:定义视图相关函数。

将创建的应用配置进项目的 settings.py 中:(当不需要迁移时则可不做此步配置)

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'hero_book'  # 新增的应用
)

 

3. 模型(Model)

设计介绍

本示例完成“图书-英雄”两种信息的维护。“图书”、“英雄”的关系为一对多。

“图书”表结构设计:

  • 表名:BookInfo
  • 图书名称:btitle
  • 图书发布时间:bpub_date

“英雄”表结构设计:

  • 表名:HeroInfo
  • 英雄姓名:hname
  • 英雄性别:hgender
  • 英雄简介:hcontent
  • 所属图书:hbook

数据库配置

  • 在 settings.py 文件中,通过 DATABASES 项进行数据库设置。
  • Django 支持的数据库包括 SQLite、MySQL 等主流数据库。
  • Django 默认使用自带的 SQLite 数据库。

定义模型类

步骤如下:

  1. 打开应用的 models.py 文件
  2. 引入包 from django.db import models
  3. 模型类继承 models.Model 类
  4. 说明:不需要定义主键列,在生成时会自动添加,并且值为自动增长
  5. 当输出对象时,会调用对象的 str 方法
 1 from django.db import models
 2 
 3 # 声明表名
 4 class BookInfo(models.Model):
 5     # 声明表字段
 6     book_title = models.CharField(max_length=20)  # 字符串类型且限定数据长度
 7     book_public_date = models.DateTimeField()  # 时间类型
 8 
 9     def __str__(self):
10         return "%d" % self.pk  # 返回主键列的值
11 
12 
13 class HeroInfo(models.Model):
14 
15     name = models.CharField(max_length=20)
16     gender = models.BooleanField()  # 布尔类型
17     content = models.CharField(max_length=100)
18     Book = models.ForeignKey('BookInfo')  # 主/外键关联(BookInfo 加不加引号都行)
19 
20     def __str__(self):
21         return "%d" % self.pk

迁移:生成数据表

1)激活模型:编辑 settings.py 文件,将 hero_book 应用加入到 installed_apps 中

2)生成迁移文件:根据模型类生成表结构的相关 sql 脚本(记录关于 models.py 的所有改动,但是还没有作用到数据库中)

python manage.py makemigrations

迁移文件被生成到应用的 migrations 目录,迁移文件中就是模型定义的对应 sql 脚本。

3)执行迁移:即执行 sql 脚本,生成数据表(将 models.py 的所有改动作用到数据库中)

python manage.py migrate

4)Django 模型修改及数据迁移

数据操作测试

进入 python shell,进行简单的模型 API 练习:

python manage.py shell

操作“图书”对象

# 引入需要的包
>>> from booktest.models import BookInfo,HeroInfo
>>> from django.utils import timezone
>>> from datetime import *

# 查询所有图书数据
>>> BookInfo.objects.all()
[]

# 新建图书数据
>>> b = BookInfo()  # 映射表名
>>> b.book_title = "射雕英雄传"  # 映射表字段
>>> b.book_public_date = datetime(year=1990, month=1, day=10)
>>> b.save()
  
# 查找图书数据
>>> b = BookInfo.objects.get(pk=1)  # 根据主键查找

# 输出图书数据
>>> b
<BookInfo: 1>
>>> b.id
1
>>> b.book_title
'射雕英雄传'

# 修改图书数据
>>> b.book_title = "天龙八部"
>>> b.save()

# 删除图书数据
>>> b.delete()

操作“英雄”对象:关联对象的操作

  • 对于 HeroInfo 可以按照上面的操作方式进行。
  • 注意添加关联对象(图书)。
>>> h = HeroInfo()
>>> h.name = "郭靖"
>>> h.gender = True
>>> h.content = "降龙十八掌"
>>> h.Book = b
>>> h.save()

# 获得关联集合:返回当前BookInfo对象的所有HeroInfo对象
>>> b.heroinfo_set.all()
[<HeroInfo: 1>]

# 有一个HeroInfo对象存在,就必须对应一个BookInfo对象
# 另一种创建关联的方式
>>> h = b.heroinfo_set.create(name="黄蓉", gender=False, content="打狗棒法")
>>> h
<HeroInfo: 2>
>>> h.name
'黄蓉'

 

4. 站点管理 

1)服务器启停

运行如下命令可以开启服务器:

python manage.py runserver ip:port

修改端口:

python manage.py runserver 8080
  • 可以不写 ip,默认端口为 8000。
  • 这是一个纯 python 编写的轻量级 web 服务器,仅在开发阶段使用。
  • 服务器成功启动后,提示如下信息:
E:\DjangoDemo>python manage.py runserver
Performing system checks...

System check identified no issues (0 silenced).
March 31, 2021 - 21:23:43
Django version 1.8.2, using settings 'DjangoDemo.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
  • 打开浏览器,输入网址“127.0.0.1:8000”可以打开默认页面。
  • 修改文件后不需要重启服务器;如果是增删文件则需要重启服务器。
  • 通过 ctrl+c 停止服务器。

2)管理操作

  • 站点分为“内容发布”和“公共访问”两部分。
  • “内容发布”的部分负责添加、修改、删除内容,开发这些重复的功能是一件单调乏味、缺乏创造力的工作。为此,Django 会根据定义的模型类完全自动地生成管理模块。

使用 django 的管理

  • 执行以下命令创建一个管理员用户,按提示输入用户名、密码、邮件:
python manage.py createsuperuser
  • 启动服务器,通过“127.0.0.1:8000/admin”访问,输入上面创建的用户名、密码完成登录;
  • 进入管理站点,默认可以对 groups、users 进行管理。

管理界面本地化

  • 编辑 settings.py 文件,设置中文编码和中国时区
LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'

向 admin 注册 hero_info 的相关模型

  • 打开 hero_book/admin.py 文件,注册模型
from django.contrib import admin
from models import BookInfo

admin.site.register(BookInfo)
admin.site.register(HeroInfo)
  • 刷新管理页面,可以对 BookInfo 的数据进行增删改查操作。
  • 问题:如果要在 str() 方法中返回中文,在修改和添加时会报 ascii 的错误。
  • 解决:在 str() 方法中,将字符串末尾添加“.encode('utf-8')”。

自定义管理页面

  • Django 提供了 admin.ModelAdmin 类。
  • 通过自定义 ModelAdmin 的子类,来定义模型在站点管理界面的显示方式。

列表页的相关属性

 1 from django.contrib import admin
 2 from .models import *
 3 
 4 
 5 # 自定义ModelAdmin的子类,定义BookInfo模型在站点管理界面的显示方式
 6 class BookInfoAdmin(admin.ModelAdmin):
 7     list_display = ['pk', 'book_title', 'book_public_date']  # list_display:显示字段,可以点击列头进行排序
 8     list_filter = ['book_title']  # list_filter:过滤字段,过滤框会出现在右侧
 9     search_fields = ['book_title']  # search_fields:搜索字段,搜索框会出现在上侧
10     list_per_page = 10  # list_per_page:分页,分页框会出现在下侧
11 
12 
13 admin.site.register(BookInfo, BookInfoAdmin)  # 将ModelAdmin子类与对应的模型类放一起
14 admin.site.register(HeroInfo)

界面效果:

 添加/修改页的相关属性

 1 from django.contrib import admin
 2 from .models import *
 3 
 4 
 5 # 自定义ModelAdmin的子类,定义BookInfo模型在站点管理界面的显示方式
 6 class BookInfoAdmin(admin.ModelAdmin):
 7 
 8     '''列表页属性'''
 9     list_display = ['pk', 'book_title', 'book_public_date']  # list_display:显示字段,可以点击列头进行排序
10     list_filter = ['book_title']  # list_filter:过滤字段,过滤框会出现在右侧
11     search_fields = ['book_title']  # search_fields:搜索字段,搜索框会出现在上侧
12     list_per_page = 10  # list_per_page:分页,分页框会出现在下侧
13 
14     '''添加、修改页属性'''
15     # fields:属性的先后顺序
16     # fields = ['book_public_date', 'book_title']
17     # fieldsets:属性分组
18     fieldsets = [
19         ('basic', {'fields': ['book_title']}),
20         ('more', {'fields': ['book_public_date']}),
21     ]
22 
23 
24 admin.site.register(BookInfo, BookInfoAdmin)  # 将ModelAdmin子类与对应的模型类放一起
25 admin.site.register(HeroInfo)

页面效果:

3)关联对象

对于 HeroInfo 模型类,有两种注册方式:

  • 方式一:与 BookInfo 模型类相同的注册方式
  • 方式二:关联注册

接下来实现关联注册

 1 from django.contrib import admin
 2 from .models import *
 3 
 4 
 5 # 自定义admin.StackedInline的子类,实现关联对象的注册
 6 class HeroInfoInline(admin.StackedInline):
 7     model = HeroInfo
 8     extra = 2
 9 
10 
11 # 自定义ModelAdmin的子类,定义BookInfo模型在站点管理界面的显示方式
12 class BookInfoAdmin(admin.ModelAdmin):
13 
14     '''列表页的相关属性'''
15     list_display = ['pk', 'book_title', 'book_public_date']  # list_display:显示字段,可以点击列头进行排序
16     list_filter = ['book_title']  # list_filter:过滤字段,过滤框会出现在右侧
17     search_fields = ['book_title']  # search_fields:搜索字段,搜索框会出现在上侧
18     list_per_page = 10  # list_per_page:分页,分页框会出现在下侧
19 
20     '''添加/修改页的相关属性'''
21     # fields:属性的先后顺序
22     # fields = ['book_public_date', 'book_title']
23     # fieldsets:属性分组
24     fieldsets = [
25         ('basic', {'fields': ['book_title']}),
26         ('more', {'fields': ['book_public_date']}),
27     ]
28 
29     '''实现关联对象的方式二'''
30     inlines = [HeroInfoInline]
31 
32 
33 admin.site.register(BookInfo, BookInfoAdmin)  # 将ModelAdmin子类与对应的模型类放一起
34 # admin.site.register(HeroInfo)  # 实现关联对象的方式一

还可以将内嵌的方式改为表格,只需替换继承的父类:

class HeroInfoInline(admin.TabularInline)

4)布尔值的显示

发布性别的显示不是一个直观的结果,可以使用方法进行封装:

1 def gender(self):
2     if self.hgender:
3         return ''
4     else:
5         return ''
6 
7 gender.short_description = '性别'

在 admin 注册中使用函数名 gender 代替类属性 gender:

class HeroInfoAdmin(admin.ModelAdmin):
    list_display = ['id', 'name', 'gender', 'content']

 

5. 视图(View)

views.py

  • 在 Django 中,视图负责对 web 请求进行回应。
  • 视图接收 reqeust 对象作为第一个参数,该参数包含了请求的信息。
  • 视图就是一个 python 函数,被定义在 views.py 中。
1 from django.http import HttpResponse  # 引入响应对象
2 
3 # 定义访问主页时的响应
4 def index(request):  # 视图函数的第一个参数必须是request(请求)对象
5     return HttpResponse("welcome index page!")  # 视图函数返回的必须是HttpResponse(响应)对象或其子类
6 
7 # 定义访问详情页时的响应
8 def detail(request, id):
9     return HttpResponse("detail:%s" % id)

定义完成视图后,需要配置 URLconf,否则无法处理请求。

URLconf

  • 在 Django 中,定义 URLconf 包括两方面内容:配置正则表达式和视图。
  • Django 使用正则表达式匹配请求 URL,一旦匹配成功,则调用对应的视图。
  • 注意:只匹配路径部分,即除去域名、参数后的字符串。
  • 在 DjangoDemo/urls.py 中新增 hero_book.urls,使主 URLconf 连接到 hero_book.urls 模块。

注意:django 2.0 起,urls 不支持正则表达式问题。如果需要使用正则,需要导入 re_path,使用方法如下:

from django.urls import path, re_path

urlpatterns = [
    path('admin/', admin.site.urls),
    re_path(r'^test-(\d+)-(\d+)/', views.test),
    path('index/', views.index),
]

示例

DjangoDemo/urls.py:

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^', include('hero_book.urls')),  # 关联hero_book包下的urls模块
]

hero_book/urls.py:

1 from django.conf.urls import url
2 from . import views
3 
4 
5 urlpatterns = [
6     url(r'^$', views.index),  # URI不带多余字符时访问index函数
7     url(r'^book/([0-9]+)/$', views.detail),  # URI带数字时访问detail函数
8 ]

页面效果

 

6. 模板(Template)

模板其实就是 html 页面,可以根据视图中传递的数据填充值。

(实际上,文件扩展名并不一定要是 html。只要文件中是 html 的内容,使用其他文件扩展名也可。)

创建模板目录

1)在项目目录下创建模板的目录,如下图:

为了清晰起见,一个模板目录对应一个应用,存放该应用的所有页面。

2)修改应用的 settings.py 文件,设置 TEMPLATES 的 DIRS 值:

'DIRS': [os.path.join(BASE_DIR, "templates")],  # 关联到项目目录下的templates目录(BASE_DIR是setings.py中已定义好的变量)

定义模板

在模板中访问视图传递的数据的方式:

{{输出值,可以是变量,也可以是对象.属性}}
{%执行代码段%}

index.html

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>首页</title>
 6 </head>
 7 <body>
 8 <h1>图书列表</h1>
 9 <ul>
10     {%for book in booklist%}
11     <li>
12         <a href="book/{{book.id}}">{{book.book_title}}</a>
13     </li>
14     {%endfor%}
15 </ul>
16 </body>
17 </html>

detail.html

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>详情页</title>
 6 </head>
 7 <body>
 8 <h1>编号:{{book.id}}</h1>
 9 <ul>
10     {%for hero in book.heroinfo_set.all%}
11     <li>{{hero.name}}——{{hero.content}}</li>
12     {%endfor%}
13 </ul>
14 </body>
15 </html>

使用模板

编辑 views.py,在方法中调用对应的模板:

 1 from django.shortcuts import render
 2 from .models import BookInfo
 3 
 4 # 首页
 5 def index(request):
 6     # 获取所有BookInfo对象
 7     booklist = BookInfo.objects.all()
 8     # render 参数2:指定模板文件;参数3:将booklist对象列表传递给模板页面中引用
 9     return render(request, 'hero_book/index.html', {'booklist': booklist})
10 
11 # 详情页
12 def detail(request, id):
13     # 将url正则中的分组作为主键,获取对应的BookInfo对象
14     book = BookInfo.objects.get(pk=id)
15     return render(request, 'hero_book/detail.html', {'book': book})

页面效果

 

posted @ 2021-04-01 23:17  Juno3550  阅读(646)  评论(0编辑  收藏  举报