编辑
2026-04-01
undefined
00

目录

安装
创建项目
创建应用
注册应用
设置
时区和语言
admin后台
本地配置
快速上手
URL和视图配置
编写视图函数
启动项目
命令行启动
templates模板
静态文件
模板语法
变量相关
逻辑相关
模板继承
父模板
子模板
请求和响应
操作表
创建表
修改表
统计查询结果数量
按需查询数据
defer方法
only方法
更新数据库
更新部分字段
批量创建或更新数据
命令

安装

pip install django

安装完,在Python安装目录Libsite-packages下会多一个文件夹django(框架源码),在Scripts文件夹下会多一个文件django-admin.exe(用来创建django项目)。

创建项目

打开终端,进入某个目录(项目路径),执行命令创建项目:django-admin startproject mysite

运行后将在目录下生成一个mysite目录,也就是Django项目的根目录。

创建应用

在 Django 中,每一个应用(app)都是一个 Python 包。

cd mysite python manage.py startapp app

运行后会自动生成app文件夹:

app | admin.py # Django默认提供admin后台管理 | apps.py # app启动类 | models.py # 对数据库操作 | tests.py # 单元测试 | views.py # 视图函数 | __init__.py | ---migrations # 数据框变更记录 __init__.py

注册应用

打开mysite/setting.py,在INSTALLED_APPS当中注册app模块:

INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app', ]

设置

时区和语言

修改项目的settings.py文件如下:

LANGUAGE_CODE = 'zh-hans' TIME_ZONE = 'Asia/Shanghai' USE_TZ = False

admin后台

设置admin后台应用显示为中文,需要修改应用目录下的apps.py文件:

class LoginConfig(AppConfig): default_auto_field = 'django.db.models.BigAutoField' name = 'login' verbose_name = '用户管理' # 新增

设置admin后台首页的网页标题,需要修改应用目录下的的admin.py文件:

admin.site.site_title = '后台管理' # 修改标题 admin.site.site_header = '后台管理' # 修改header

本地配置

首先创建自己的本地配置文件:local_settings.py。在settings.py中导入:

try: from .local_settings import * except ImportError: pass

切记:给别人代码时,不要给local_settings.py

快速上手

URL和视图配置

打开mysite/urls.py,修改为:

from django.contrib import admin from django.urls import path from app import views # 导入views urlpatterns = [ path('admin/', admin.site.urls), # 域名/index/ -> index函数,即绑定URL与视图函数 path('index/', views.index), ]

编写视图函数

视图,即具体的业务代码,打开app/views.py,修改为:

from django.shortcuts import render, HttpResponse def index(requests): return HttpResponse('欢迎使用')

启动项目

命令行启动

python manage.py runserver

Django的服务器默认运行在8000端口,如果想指定端口,命令如下:

python manage.py runserver 8080

templates模板

在app文件夹下新建templates文件夹,然后在templates文件夹下新建文件user_list

在文件mysite/urls.py中添加URL:

path('user/list', views.user_list, {'name': '李小龙'}),

在文件app/views.py中添加函数:

def user_list(request): # 去app目录下的templates目录寻找user_list return render(request, 'user_list')

静态文件

在app文件夹下新建static文件夹,然后在 static 目录下创建 css 目录,js 目录,img 目录,plugin 目录, 分别放css文件,js文件,图片和插件。

在模板中使用需要加入 {% load static %} 代码,以下实例从静态目录中引入图片,修改 user_list 为:

{% load static %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>用户列表</title> </head> <body> <h1>{{ name }}</h1> <img src="{% static 'img/logo.webp' %}" alt="logo"> </body> </html>

模板语法

本质上是在html中写一些占位符,由数据对这些占位符进行替换和处理。

变量相关

在文件mysite/urls.py中添加URL:

path('tpl/', views.tpl),

在文件app/views.py中添加函数:

def tpl(request): name = '李小龙' roles = ['管理员', 'CEO', '保安'] user_info = {'name': "李小龙", 'sex': '女', 'role': '保安'} return render(request, 'tpl', {'n1': name, 'n2': roles, 'n3': user_info})

render 使用了一个字典作为参数,字典中元素的键值 n1 对应了模板中的变量 {{ n1 }}。

app/templates目录下新建tpl文件,代码如下:

<h1>{{ n1 }}</h1> <h1>{{ n2 }}</h1> <h1>{{ n2.0 }}</h1> <h1>{{ n2.1 }}</h1> <h1>{{ n3.name }}</h1> <h1>{{ n3.sex }}</h1>

访问 http://127.0.0.1:8000/tpl/,查看页面输出结果。

逻辑相关

tpl文件添加如下代码:

<hr/> <div> {% for item in n2 %} <span>{{ item }}</span> {% endfor %} </div> <hr/> <ul> {% for k,v in n3.items %} <li>{{ k }} = {{ v }}</li> {% endfor %} </ul>

访问 http://127.0.0.1:8000/tpl/,查看页面输出结果。

模板继承

父模板

{% block 名称 %} 预留给子模板的区域,可以设置默认内容 {% endblock 名称 %}

子模板

{% extends "父模板路径" %}

子模板使用标签 extends 继承父模板。

接下来在 templates 目录中添加 base 文件,代码如下:

<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>编程笔记</title> </head> <body> <h1>Hello World!</h1> <p>编程笔记 Django 测试。</p> {% block mainbody %} <p>original</p> {% endblock %} </body> </html>

index 继承 base,index 修改后的代码如下:

{%extends "base" %} {% block mainbody %} <p>继承了 base 文件。</p> {% endblock %}

访问 http://127.0.0.1:8000/index 查看页面输出结果。可以看到,这里相同名字的 block 标签用于替换 base 的相应 block。

请求和响应

在文件mysite/urls.py中添加URL:

path('something/', views.something),

在文件app/views.py中添加函数:

from django.shortcuts import redirect def something(request): # 获取请求方式 GET/POST print(request.method) # 在url传递值 /something/?n1=李小龙 print(request.GET) # 在请求体中提交数据 print(request.POST) # 重定向 return redirect('https://www.baidu.com/')</code></pre><p>访问 <code>http://127.0.0.1:8000/something/</code>,查看页面输出结果。</p><h2>Django模型</h2><p>MySQL 是 Web 应用中最常用的数据库,这里以 MySQL 作为实例进行介绍。如果没安装 mysql 驱动,执行以下命令安装:</p><pre><code>pip3 install pymysql</code></pre><p>这里作个说明,pymysql和mysqlclient是目前Python连接MySQL的主流方式。</p><p>区别是:mysqlclient速度比pymysql快;pymysql更加简单易使用。</p><p>如果是大型项目,当然是用mysqlclient,该驱动性能比较优异;中小项目用pymysql就可以了,毕竟是使用Python写的,契合度更高。</p><h3>数据库配置</h3><p>在项目的 settings.py 文件中找到 DATABASES 配置项,将其信息修改为:</p><pre><code>DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', # 数据库引擎 'NAME': 'django', # 数据库名称 'HOST': '127.0.0.1', # 数据库地址,本机ip地址 'PORT': 3306, # 端口 'USER': 'root', # 数据库用户名 'PASSWORD': '', # 数据库密码 } }

接下来,告诉 Django 使用 pymysql 模块连接 mysql 数据库:

## 在与 settings.py 同级目录下的 init.py 中引入模块和进行配置 import pymysql pymysql.install_as_MySQLdb()

操作表

创建表

在models.py文件中:

class UserInfo(models.Model): name = models.CharField(max_length=32) # 设置默认值 age = models.IntegerField(default=0) # 允许为空 data = models.DateField(null=True, blank=True)

执行命令:

## 创建应用的迁移数据文件 python manage.py makemigrations app 生成数据库表 python manage.py migrate

修改表

在文件 urls.py 中添加 URL:

path('orm/', views.orm),

在文件 views.py 中添加函数:

def orm(request): # 新增 UserInfo.objects.create(name='李小龙', age=18, date='2022-04-04') # 删除 # UserInfo.objects.filter(id=1).delete() # UserInfo.objects.all().delete() # 查询数据,data_list是QuerySet类型 # data_list = UserInfo.objects.all() # for obj in data_list: # print(obj.name, obj.age, obj.date) # 获取第一条数据 # row_obj = UserInfo.objects.filter(id=5).first() # print(row_obj.id, row_obj.name) # 更新数据 # UserInfo.objects.all().update(age=20) # UserInfo.objects.filter(id=5).update(age=20) return HttpResponse('成功')</code></pre><p>访问 <code>http://127.0.0.1:8000/orm/</code>,查看页面输出结果。</p><h3>外键删除</h3><p>一个模型如果使用了外键,那么在对方那个模型被删掉后,该进行什么样的操作,可通过on_delete来指定。指定的类型如下:</p><ul><li>CASCADE:级联操作。如果外键对应的那条数据被删除了,那么这条数据也会被删除</li><li>PROTECT:受保护。即只要这条数据引用了外键的那条数据,那么就不能删除外键的那条数据。如果我们强行删除,Django就会报错</li><li>SET_NULL:设置为空。如果外键的那条数据被删除了,那么在本条数据上就将这个字段设置为空。如果设置这个选项,前提是要指定这个字段可以为空</li><li>SET_DEFAULT:设置默认值。如果外键的那条数据被删除了,那么本条数据上就将这个字段设置为默认值。如果设置这个选项,前提是要指定这个字段一个默认值。</li><li>SET():如果外键的那条数据被删除了,那么将会获取SET函数中的值来作为这个外键的值。SET函数可以接收一个可以调用的对象(比如函数或者方法),如果是可以调用的对象,那么会将这个对象调用后的结果作为值返回回去。可以不用指定默认值</li><li>DO_NOTHING:不采取任何行为。一切全看数据库级别的约束</li></ul><h3>数据库接口</h3><p>QuerySet是Django提供的强大的数据库接口(API)。从数据库中查询得到的结果一般是一个集合,这个集合叫做 QuerySet。</p><h4>QuerySet惰性</h4><p>所谓惰性,就是不会主动去执行。创建 QuerySet 的行为(语句)不会马上执行sql,而是返回一个QuerySet(查询结果集对象),只有在调用QuerySet的时候才会涉及到数据库操作。</p><h4>QuerySet缓存</h4><p>下例中例1比例2要好,因为在你打印文章标题后,Django不仅执行了查询,还把查询到的article_list放在了缓存里,因此这个article_list是可以复用的。例2就不行了。</p><pre><code>## Example 1: Good article_list = Article.objects.filter(title_contains="django") for article in article_list: print(article.title) Example 2: Bad for article in Article.objects.filter(title_contains="django"): print(article.title)

在loop前加个if判断,防止article_list是个空数据集:

article_list = Article.objects.filter(title_contains="django") if article_list: for article in article_list: print(article.title) else: print("No records")

如果只是希望了解查询的结果是否存在,而不需要使用整个数据集,这时if触发整个queryset的缓存变成了一件坏事情。这时可以用exists()方法。与if判断不同,exists只会检查查询结果是否存在,返回True或False,而不会缓存article_list。

article_list = Article.objects.filter(title_contains="django") if article_list.exists(): print("Records found.") else: print("No records")

统计查询结果数量

len()与count()均能统计查询结果的数量。一般来说count更快,因为它是从数据库层面直接获取查询结果的数量,而不是返回整个数据集,而len会导致queryset的执行,需要将整个queryset载入内存后才能统计其长度。但事情也没有绝对,如果数据集queryset已经在缓存里了,使用len更快,因为它不需要跟数据库再次打交道。

下面三个例子中,只有例2最差,尽量不要用:

## Example 1: Good count = Article.objects.filter(title_contains="django").count() Example 2:Bad count = Article.objects.filter(title_contains="django").len() Example 3: Good article_list = Article.objects.filter(title_contains="django") if article_list: print("{} records found.".format(article_list.len()))

按需查询数据

当查询到的queryset非常大时,会大量占用内存(缓存)。我们可以使用values和value_list方法按需提取数据。

article_list = Article.objects.filter(title_contains="django").values('title') if article_list: print(article.title) article_list = Article.objects.filter(title_contains="django").values_list('id', 'title') if article_list: print(article.title)

还可以使用defer和only这两个查询方法来实现按需查询数据。

defer方法

defer方法的用途是查询数据库时跳过指定的字段,防止不要的字段载入内存,从而节省空间:

## 查询时跳过id和title字段 Article.objects.defer('id', 'title')

该方法可以和filter, exclude方法联用,其顺序无关紧要,如下所示:

Article.objects.defer('id').filter(title_contains="django").defer('title')

only方法

only方法与defer方法作用类似,只不过only方法是指定需要载入的字段。比如下面查询将只会载入id和title。

Article.objects.only('id', 'title')

使用only方法要注意它的顺序,它的执行以最后一个为准。下例将只会载入pub_date:

Article.objects.only('id', 'title').only('pub_date')

only方法与defer方法可以联用,但要注意先后顺序。下例只会载入title:

Article.objects.only('id', 'title').defer('id')

更新数据库

更新部分字段

更新数据库部分字段更好的方式是用update,而不是save方法。

## Example 1: Good Article.objects.filter(id=10).update(title='Django') Example 2: Bad article = Article.objects.get(id=10) Article.title = "Django" article.save()
批量创建或更新数据

Django提供的bulk_create和bulk_update方法可以一次添加或更新多条数据,效率要高很多,如下所示:

## 内存生成多个对象实例 articles = [Article(title="title1", body="body1"), Article(title="title2", body="body2"), Article(title="title3", body="body3")] 执行一次SQL插入数据 Article.objects.bulk_create(articles)

命令

## 创建超级管理员 python manage.py createsuperuser 无需启动Django操作数据库中某个表的数据 python manage.py shell

本文作者:a

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!