Django Project Development

Django is a web framework developed with python. It is one of the most representative Python frameworks. Many successful websites and APPs are based on Django.

Posted by Dusign on 2019-09-30
Words 3.5k and Reading Time 14 Minutes
Viewed Times

Django is an open source Web application framework written by Python. The framework model of MTV, namely model M, view V and template T, is adopted. It was originally developed to manage some news content oriented websites of the publishing group, that is, CMS (content management system) software. It was issued under BSD license in July 2005.

Install

  1. Install python
    截止目前 python 的最新版本为 python3.7.4 ,django 需要的 python 版本如下
Django版本 Python版本
1.11 2.7,3.4,3.5,3.6,3.7
2.0 3.4,3.5,3.6,3.7
2.1, 2.2 3.5,3.6,3.7

python 安装方法比较简单,安装之后记得配置环境变量,这里就不做介绍了。

  1. 安装 virtualenv

  2. Install django
    创建并激活一个虚拟环境然后执行下面的命令或直接在系统中执行下面的命令
    pip3 install Django
    然后在 python3 环境中执行下面代码,如果输出 django 版本,说明 django 安装成功

    1
    2
    import django
    print(django.get_version())

Create Project

运行下面命令创建项目
django-admin startproject PROJECT_NAME
创建之后的目录与作用如下

1
2
3
4
5
6
7
PROJECT_NAME/        # 根目录,项目的容器
manage.py # 管理 django 项目的命令行工具
PROJECT_NAME/ # 项目目录。它是一个纯 python 包,名字是引用内部东西时需要用的 python 包名,如(PROJECT_NAME.urls)
__init__.py # 空文件。告诉 python 这个目录是一个 python 包
settings.py # django 项目的配置文件
urls.py # django 项目的 URL 声明,像网站的“目录”
wsgi.py # 作为项目运行在 wsgi 兼容的 web 服务器的入口

用于开发的简易服务器使用以下命令开启
python3 manage.py runserver
runserver 命令会将服务器设置为监听本机内部 ip 的 8000 端口,想更换端口的话使用下面的命令
python3 manage.py runserver PORT

Create APP

  1. 运行以下命令创建应用
    python3 manage.py startapp APP_NAME
    创建之后的目录如下
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    APP_NAME/
    __init__.py
    admin.py
    apps.py
    migrations/
    __init__.py
    models.py
    tests.py
    # 这个文件是后期创建的,这个是 URL 映射的文件,创建完之后需要在 PROJECT_NAME/urls.py 中加入 include()
    urls.py
    views.py
  2. 将应用安装到项目里
    PROJECT_NAME/settings.py 中的 INSTALLED_APPS 中添加 APP_NAME.apps.APP_NAMEConfig—-APP_NAMEConfigAPP_NAME 首字母大写。因为 APP_NAMEConfig 类写在文件 APP_NAME/apps.py 中,所以它的点式路径是 APP_NAME.apps.APP_NAMEConfig

View

添加视图,修改文件 PROJECT_NAME/APP_NAME/views.py 如下

1
2
3
4
5
6
7
8
9
10
from django.http import HttpResponse

def index(request):
return HttpResponse("Hello, world. This is an APP.")

def VIEW_NAME(request,PARAMETER):
response = "This is a simple view"
return HttpResponse(response % PARAMETER)

...

设置路由,修改文件 PROJECT_NAME/urls.py 如下

1
2
3
4
5
6
7
8
9
10
from django.urls import path
from . import views

urlpatterns = [
path('', views.index, name='index'),
path('ROUTER_NAME', views.VIEW_NAME, name='VIEW_NAME')
# 使用尖括号捕获URL 并且以参数的形式发送给视图函数
path('<ROUTER_NAME:PARAMETER>', views.VIEW_NAME, name='VIEW_NAME')
...
]

修改 PROJECT_NAME/urls.py 的内容如下

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

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

path() 函数总共有四个参数,分别是routeviewkwargsname,前两个是必须参数,后两个是可选参数,参数意义如下

  • route 这是一个匹配 URL 的准则,当 django 响应一个请求时,会从 urlpatterns 的第一项开始,按顺序依次匹配列表中的项,直到找到匹配的项
  • view 当 django 找到一个匹配的准则,会调用这个特定的视图函数,并传入一个 HttpRequest 对象作为第一个参数,被“捕获”的参数以关键字参数的形式传入
  • kwargs 任意个关键字参数可以作为一个字典传递给目标视图函数
  • name 为你的 URL 取名能使你在 django 的任意地方唯一地引用它,尤其是在模板中。这个有用的特性允许你只改一个文件就能全局地修改某个 URL 模式

Django模版系统

如果页面的设计写死在视图函数的代码里的,则修改页面的样子需要编辑 Python 代码,如果使用 Django 的模板系统,只要创建一个视图,就可以将页面的设计从代码中分离出来。具体使用方法如下

  1. 在 PROJECT_NAME 目录里创建一个 templates 目录,django 将会在这个目录里查找模版文件

项目的 TEMPLATES 配置项描述了 Django 如何载入和渲染模板。默认的设置文件设置了 DjangoTemplates 后端,并将 APP_DIRS 设置成了 True。这一选项将会让 DjangoTemplates 在每个 INSTALLED_APPS 文件夹中寻找 “templates” 子目录。所以如果 templates 文件夹在 APP_NAME 目录中,就算没有修改 DIRS 设置,Django 也能正确找到 APP_NAME 的模板位置,但是如果目录在其它地方,就必须设置 DIRS
TEMPLATES 配置如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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. templates 目录里创建一个 APP_NAME 目录,此时模版文件的路径就是 APP_NAME/templates/APP_NAME/VIEW_NAME.html,使用 APP_NAME/VIEW_NAME.html 就可以引用相应的模版了

  2. APP_NAME/views.py 文件的设置如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    from django.shortcuts import render

    # Create your views here.
    from django.http import HttpResponse
    from django.template import loader

    from app1.models import User
    from app1.models import Job

    def index(request):
    latest_user_list = User.objects.order_by('name')[:3]
    template = loader.get_template('app1/index.html')
    context = {
    'latest_user_list' : latest_user_list,
    }
    return HttpResponse(template.render(context,request))
  3. render()函数
    render() 作用是载入模版,填充上下文,再返回由它生成的 HttpResponse 对象,使用此函数重写 index() 视图如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    from django.shortcuts import render
    from django.http import HttpResponse
    from app1.models import User
    from app1.models import Job

    def index(request):
    latest_user_list = User.objects.order_by('name')[:3]
    context = {
    'latest_user_list' : latest_user_list,
    }

    return render(request, 'app1/index.html', context)
  4. 抛出404
    如果查询指定的内容不存在,则抛出一个 Http404 异常

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    from django.shortcuts import render
    from django.http import HttpResponse, Http404
    from app1.models import User
    from app1.models import Job

    def index(request, user_name):
    try:
    user_detail = User.objects.get(name=user_name)
    except User.DoesNotExist:
    raise Http404("User does not exist !")

    return render(request, 'app1/index.html', {'user': user_detail})

    get_object_or_404()实现方法如下

    1
    2
    3
    4
    5
    6
    7
    8
    from django.shortcuts import render, get_object_or_404
    from django.http import HttpResponse, Http404
    from app1.models import User
    from app1.models import Job

    def index(request, user_name):
    user_detail = get_object_or_404(User, name=user_name)
    return render(request, 'app1/index.html', {'user': user_detail})

第三方模版系统

Model

  1. 设置时区 TIME_ZONE
    默认为 UTC 是国际标准时间“格林尼治时间”,中国的时间有 Asia/ShanghaiAsia/Chongqing
    USE_TZ 用于控制是否使用 UTC 时间(true and false),如果设置为 false,则使用本地时间
    LANGUAGE_CODE 默认为 en-us ,设置中文为 zh-Hans

  2. 编辑 PROJECT_NAME/settings.py
    PROJECT_NAME/settings.py 包含了 django 项目设置的 python 模块,配置文件使用 SQLite 作为默认数据库,使用其他数据库则需要安装相应的 python 数据库绑定,具体如下

    • PostgreSQL 需要安装 psycopg2
    • MySQL 需要安装 DB API driver,如 mysqlclient
      mysqlclient 安装方法如下
      pip3 install mysqlclient
    • Oracle 需要 cx_Oracle 的副本

      安装完之后需要改变设置中 DATABASES 'default' 项目中的一些键值

    • ENGINE 可选值有 django.db.backends.sqlitesdjango.db.backends.postgresqldjango.db.backends.mysqldjango.db.backends.oracle
    • NAME 数据库的名称。如果使用 SQLite,数据库将是电脑上的一个文件,此时 NAME 是此文件的绝对路径,包括文件名
    • 如果使用的不是 SQLite ,则必须添加一些额外设置,比如 USERPASSWORDHOST,设置如下
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      DATABASES = {
      'default': {
      'ENGINE': 'django.db.backends.mysql',
      'NAME': 'mydatabase',
      'USER': 'mydatabaseuser',
      'PASSWORD': 'mypassword',
      'HOST': '127.0.0.1',
      'PORT': '5432',
      }
      }

若要使用 django 的 manage.py migrate 命令为您的模型自动创建数据库表,则需要确保 django 有权在您正在使用的数据库中创建和更改表
如果你打算手动创建这些表,你可以只需授予 Django selectinsertupdatedelete 权限

  1. INSTALLED_APPS 设置包括了项目中启用的所有 django 应用,默认为

    1
    2
    3
    4
    5
    6
    django.contrib.admin         # 管理员站点
    django.contrib.auth # 认证授权系统
    django.contrib.contenttypes # 内容类型框架
    django.contrib.sessions # 会话框架
    django.contrib.messages # 消息框架
    django.contrib.staticfiles # 管理静态文件的框架

    这些应用被默认启用是为了给常规项目提供方便,默认开启的某些应用需要至少一个数据表,故在使用他们之前需要在数据库中创建一些表,命令如下
    python3 manage.py migrate
    migrate 命令检查 INSTALLED_APPS 设置,为其中的每个应用创建需要的数据表

  2. 创建模型
    编辑 APP_NAME/models.py ,如下

    1
    2
    3
    4
    5
    from django.db import models

    class MODEL_NAME(models.Model):
    FIELD_NAME = models.TYPE(max_length=MAX_LENGTH | default = DEFAULT_VALUE)
    ...

    TYPE 中字符字段被表示为 CharField,日期时间字段被表示为 DateTimeFieldForeignKey 定义一个关系,将相应的对象关联到另一个对象,详细的字段类型见下表

名称 类型 大小 备注
AutoField int auto increment int 一般不用,主键一般会自动创建
IntegerField int auto increment 64-bit 一般不用,主键一般会自动创建
BigIntegerField long int 64-bit
BinaryField binary max_length
BooleanField bool
CharField char max_length
DateField date auto_now | auto_now_add
DateTimeField date&time auto_now | auto_now_add
DecimalField 固定精度的十进制 max_digits | decimal_places
DurationField 一段时间的字段类型
EmailField email max_length
FileField 文件上传类型 upload_to | max_length
FilePathField 文件目录类型 path | match | recursive | max_length
ImageField 图片类型 upload_to | height_field | width_field | max_length
IntegerField int -2147483648 - 2147483647
PositiveIntegerField int 0 - 2147483647
PositiveSmallIntegerField int 0 - 32767
SmallIntegerField int -32768 - 32767
TextField char max_length
TimeField time auto_now | auto_now_add
URLField URL max_length
ForeignKey 关联关系字段 to | on_delete  
  1. 激活模型
    python3 manage.py makemigrations APP_NAME
    运行 makemigrations 命令,django 会检测你对模型文件的修改,并且把修改的部分存储为一次迁移,迁移是 django 对于模型定义(也就是你的数据库结构)的变化的储存形式,其实也只是一些你磁盘上的文件,它被储存在 APP_NAME/migrations/0001_initial.py 里。
    使用 sqlmigrate 可以查看模型的迁移信息,它可以接收一个迁移的名称,用法如下
    python3 manage.py sqlmigrate APP_NAME 0001 其中 0001 是一个迁移的名称
    之后如果定义了新模型的话,可以直接运行下面的命令创建
    python3 manage.py migrate
    migrate 命令选中所有还没有执行过的迁移(django 通过在数据库中创建一个特殊的表 django_migrations 来跟踪执行过哪些迁移)并应用在数据库上(也就是将你对模型的更改同步到数据库结构上)。

  2. 改变模型

    1. 编辑 models.py 文件,改变模型
    2. 运行 python3 manage.py makemigrations 为模型的改变生成迁移文件
    3. 运行 python3 manage.py migrate 来应用数据库迁移

Django API

使用下面命令进入交互式 Python 命令行
python3 manage.py shell 这个命令中 manage.py 会设置 DJANGO_SETTINGS_MODULE 环境变量,这个变量会让 django 根据 PROJECT_NAME/settings.py 文件来设置 python 包的导入路径

Database

数据库操作是项目必不可少的,以下介绍 django 的数据库操作的 API

  1. Insert save()create()
    1
    2
    3
    4
    5
    6
    7
    # 插入
    tmp = MODEL_NAME(FIELD_NAME=‘FIELD_VALUE’,...)
    tmp.save()

    # 修改
    MODEL_NAME.FIELD_NAME = 'FIELD_VALUE'
    MODEL_NAME.save()
    1
    MODEL_NAME.objects.create(FIELD_NAME="FIELD_VALUE",...)
  2. Select objects
    从数据库检索对象要通过模型类的 manager 构建一个 querySet
    querySet 代表来自数据库中对象的一个集合。它可以有 0 个,1 个或者多个 filters. filters可以根据给定参数缩小查询结果量。在 SQL 的层面上, queryset 对应 select 语句,而过滤器对应类似 wherelimit 的限制子句。可以通过模型的 manager 获取 querySet。每个模型至少有一个 manager,默认名称是 objects。用法如下
    1
    2
    # 检索全部对象,返回值是一个 queryset,包含所有的 MODEL_NAME 对象
    ALL_MODEL = MODEL_NAME.objects.all()
    过滤器
  • all() —> 查询所有
  • filter( **kwargs ) —> 使用过滤器查询
  • exclude( **kwargs ) —> 条件查询
  • get( **kwargs ) —> 查询

    **kwargs 为参数,参数的形式为 FIELD_NAME__LOOKUPTYPE=VALUE (有个双下划线)
    其中 __LOOKUPTYPE 具体有

参数 作用
__exact 精确等于
__iexact 精确等于,忽略大小写
__contains 包含
__icontains 包含,忽略大小写
__gt 大于
__gte 大于等于
__lt 小于
__lte 小于等于
__in 存在于一个list范围内
__startswith 以…开头
__istartswith 以…开头,忽略大小写
__endswith 以…结尾
__iendswith 以…结尾,忽略大小写
__range 在…范围内
__year 日期字段的年份
__month 日期字段的月份
__day 日期字段的日
__isnull True/False

在查询的过程中 pk 表示主键,如

1
2
# 查询主键为 1 的数据
MODEL_NAME.objects.get(pk=1)

  1. 跨关系查询

  2. Delete delete()
    删除方法被命名为 delete()。该方法立刻删除对象,并返回被删除的对象数量和一个包含了每个被删除对象类型的数量的字典,也能批量删除对象。所有 QuerySet 都有个 delete() 方法,它会删除 QuerySet 中的所有成员

  3. update()

    1
    MODEL_NAME.objects.filter().update(FIELD_NAME='NEW_FIELD_VALUE')

原生SQL查询

Django 允许你用两种方式执行原生 SQL 查询:你可以使用 manager.raw() 来执行原生查询并返回模型实例,或者完全不用模型层 直接执行自定义 SQL
manager.raw(raw_query,params=none,translations=none)

1
MODEL_NAME.objects.raw('SQL statement')

除了上面的 manager.raw() 之外,如果想要功能更强大的查询,可以使用下面的方法绕过模型层,直接访问数据库
对象 django.db.connection 代表默认数据库连接。要使用这个数据库连接,调用 connection.cursor() 来获取一个指针对象。然后,调用 cursor.execute(sql,[params]) 来执行该 SQL 和 cursor.fetchone()cursor.fetchaall() 获取结果数据,使用方法如下
1
2
3
4
5
6
7
8
9
from django.db import connection

def custom_sql(self):
with connection.cursor() as cursor:
cursor.execute("SQL insert statement", [self.baz])
cursor.execute("SQL select statement", [self.baz])
row = cursor.fetchone()

return row

要避免 SQL 注入,你绝对不能在 SQL 字符串中用引号包裹 %s 占位符,若要在查询中包含文本的百分号,你需要在传入参数使用两个百分号

Django 管理页面

  1. 创建管理账号
    python3 manage.py createsuperuser
    启动开发服务器之后通过 http://127.0.0.1:8000/admin/ 就可以看到管理员登录界面
  2. 添加被管理的应用
    如果想要一个应用被管理,只需要将应用加入 APP_NAME/admin.py 文件即可,具体如下
    1
    2
    3
    4
    5
    from django.contrib import admin
    from .models import MODEL_NAME

    admin.site.register(MODEL_NAME)
    ...

配置Django运行环境

如果要在生产站点上使用 django ,则需要搭建 Apache 或者 Nginx 服务器,具体搭建方法如下

Apache&mod_wsgi

  1. Install Apache

Nginx&uWSGI

  1. Install Nginx

If you like this blog or find it useful for you, you are welcome to comment on it. You are also welcome to share this blog, so that more people can participate in it. If the images used in the blog infringe your copyright, please contact the author to delete them. Thank you !

...

...

00:00
00:00