Django学习笔记:第一个Django应用

基本流程

创建工程

1
django-admin startproject mysite  # mysite为工程名

此时的文件目录结构:

1
2
3
4
5
6
7
mysite/
manage.py
mysite/
__init__.py
settings.py
urls.py
wsgi.py

  • mysite/: 整个项目的容器,没有太大意义,名字可以随意更改
  • manage.py: 命令行工具,用来管理Django项目
  • mysite/: 当前Django工程所使用的Python包
  • __init__.py: 表明当前文件夹是一个Python包
  • settings.py: 配置文件
  • urls.py: 路由配置文件
  • wsgi.py: 兼容WSGI的Web服务入口

运行工程

1
python manage.py runserver

创建应用程序

工程(Project)和程序(App): 应用程序是真正工作的组件,例如一个博客系统或者投票系统。工程师包含网站配置信息和应用程序等的集合,一个工程可以包含多个应用程序,而一个应用程序可以属于多个工程。

1
python manage.py startapp polls  # 创建一个名为polls的投票程序

polls的目录结构:

1
2
3
4
5
6
7
8
9
polls\
__init__.py
admin.py
apps.py
migrations/
__init__.py
models.py
tests.py
views.py

配置数据库以及创建模型

  使用Django自带的数据库SQLite。

  现在,我们来定义模型model,模型本质上就是数据库表的布局,再附加一些元数据。
  Django通过自定义Python类的形式来定义具体的模型,每个模型的物理存在方式就是一个Python的类Class,每一个类都是django.db.models.Model的子类。每一个字段都是Field类的一个实例,例如用于保存字符数据的CharField和用于保存时间类型的DateTimeField,它们告诉Django每一个字段保存的数据类型。每个模型代表数据库中的一张表,每个类的实例代表数据表中的一行数据,类中的每个变量代表数据表中的一列字段。
  Django通过模型,将Python代码和数据库操作结合起来,实现对SQL查询语言的封装。也就是说,你可以不会管理数据库,可以不会SQL语言,你同样能通过Python的代码进行数据库的操作。Django通过ORM对数据库进行操作,奉行代码优先的理念,将Python程序员和数据库管理员进行分工解耦。
  示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# polls/models.py

from django.db import models


class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')


class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)

  可以在每个Field中使用一个可选的第一位置参数用于提供一个人类可读的字段名,让你的模型更友好,更易读,并且将被作为文档的一部分来增强代码的可读性,如例子中的pub_date。
  使用ForeignKey定义了一个外键关系。它告诉Django,每一个Choice关联到一个对应的Question(注意要将外键写在‘多’的一方)。Django支持通用的数据关系:一对一,多对一和多对多,如例子中的question。

启用模型

  把polls加入mysite/settings.py中的INSTALLED_APPS让项目知道该应用的存在。
  运行命令$ python manage.py makemigrations polls将数据模型的改动保存为一个’migration’
  运行命令$ python manage.py migrate对数据库执行真正的迁移动作。在这一步中会自动生成表,表明为“应用名_模型名(小写)”的组合,自动添加主键id并且按照惯例在外键字段名上附加“_id”。

开发视图

  Django的视图是负责页面展示的重要模块,用于处理网站业务逻辑。
  打开polls/view.py文件,每个视图至少做两件事之一:返回一个包含请求页面的HttpResponse对象或者弹出一个类似Http404的异常。其它的则自己定义。
  render()方法: 从Django.shortcuts导入render,将加载模板、传递参数、返回HttpResponse对象整合一起。第一个位置参数是请求对象(就是view函数的第一个参数),第二个参数是模板,第三个参数是字典,包含需要传递给模板的数据。最后render函数返回一个经过字典数据渲染过的模板封装而成的HttpResponse对象。例如:

1
2
3
4
def index(request):
latest_question_list = Question.objects.order_by('-pub_date')[:5]
context = {'latest_question_list': latest_question_list}
return render(request, 'polls/index.html', context)

  创建视图后,为了能够访问它,需要在URL中添加路由映射。在polls中创建文件urls.py:

1
2
3
4
5
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
]

  接下来需要在根目录的urls.py中引用polls/urls.py,修改mysite/urls.py:

1
2
3
4
5
6
7
from django.contrib import admin
from django.urls import include, path

urlpatterns = [
path('polls/', include('polls.urls')),
path('admin/', admin.site.urls),
]

  上面代码中include()方法可以用来引用其他URLconfs(urls.py)。出了admin.site.urls之外,在任何时候都应该使用include()方法引用其他路由模块。

模板系统

  Django提供的模板系统可以解耦视图和模板之间的硬连接。
  首先,在polls目录下创建一个新的templates目录,Django会在它里面查找模板文件。
  项目的 TEMPLATES配置项描述了 Django 如何载入和渲染模板。默认的设置文件设置了 DjangoTemplates 后端,并将 APP_DIRS设置成了 True。这一选项将会让 DjangoTemplates 在每个 INSTALLED_APPS 文件夹中寻找 “templates” 子目录。这就是为什么尽管我们没有像在第二部分中那样修改 DIRS 设置,Django 也能正确找到 polls 的模板位置的原因。
  在templates目录中,再创建一个新的子目录名叫polls,进入该子目录,创建一个新的html文件index.html。换句话说,你的模板文件应该是polls/templates/polls/index.html。因为 Django 会寻找到对应的app_directories ,所以你只需要使用polls/index.html就可以引用到这一模板了。
  在视图view.py中通过render()向模板中的页面传递的上下文变量可以直接使用,例如在detail()视图里通过return render(request, 'polls/detail.html', {'question': question})传递的question在模板polls/detail.html中通过question.question_text使用

后台管理

  运行命令$ python manage.py createsuperuser创建一个可以登录admin站点的用户,填入所需信息后通过http://127.0.0.1:8000/admin/即可访问。
随后为了让应用的信息可以在后台显示,打开polls/admin.py注册投票应用:

1
2
3
4
from django.contrib import admin
from .models import Question

admin.site.register(Question)

参考资料

李健.《Django 2.0入门与实践》.清华大学出版社
刘江的博客教程


更新 2019-08-15

使用MySQL的配置方案

./settings.py:

1
2
3
4
5
6
7
8
9
10
    DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'NewTest',
'HOST': '127.0.0.1',
'USER': 'root',
'PASSWORD': 'pwd',
'PORT': '3306',
}
}

记载数据库驱动

./init.py:

1
2
import pymysql
pymysql.install_as_MySQLdb() # 完成数据库的驱动加载

解决mysqlclient版本问题

base.py 中搜索:

1
version = Database.version_info

行内添加一个pass

1
raise ImproperlyConfigured('mysqlclient 1.3.13 or newer is required; you have %s.' % Database.version)

如下:

1
2
3
4
5
6
7
8
if version < (1, 3, 13):
pass
'''
raise ImproperlyConfigured(
'mysqlclient 1.3.13 or newer is required; you have %s.'
% Database.__version__
)
'''

保存关闭并打开 operations.py搜索

1
query = query.decode(errors='replace')

decode换为encode:

1
query = query.encode(errors='replace')

其他

使用MySQL要注意自己创建数据库

1
CREATE DATABASE <NAME>;