基本常用命令
django-admin
manage
- python manage.py startapp myapp:创建一个App,其中myapp为App名称;
- python manage.py runserver 127.0.0.1:8000:启动Django项目,其中127.0.0.1:8000为项目访问地址及端口
- python manage.py shell:以终端命令交互的方式启动Django项目
- python manage.py test:执行Django测试用例,默认为myproject/myapp/tests.py中的用例
- python manage.py makemigrations:创建数据模型变更记录,当数据模型发生变化时,会在myproject/migrations目录下生成新的形如"0001_initial.py"的文件
- python manage.py migrate:数据库迁移,当settings中配置好数据库后,执行此命令会在数据库中生成相应的数据表结构
Django架构
MVC & MTV
Model数据模型
|
数据存取层,定义系统的数据表结构
|
View视图模块
|
建立用户与系统的连接页面,用户通过request发送请求给Controller,再由Controller分发到指定的路由,经过Model层的数据存取,最终将数据渲染到指定模板文件,并最终呈现到页面中,由视图和模板组成
|
Controller控制模块
|
将用户提交的request分发给View模块的视图函数
|
MTV
Model数据模型
|
数据存取层,定义系统的数据表结构、数据的存取,通过View模块联接
|
View视图模块
|
业务逻辑层,包括数据模型的存取及调用适当的模板文件的相关逻辑,类型于模型与模板之间的桥梁
|
Template模板文件
|
表现层,渲染View层的数据并最终呈现在页面中
|
运行流程
URLconf
常用方法:(django.urls模块)
方法
|
说明
|
示例
|
path
|
指定的地址为确定的地址,不支持正则匹配
|
path("", views.index)
|
re_path
|
指定的地址为不确定的地址,支持正则匹配
|
re_path("user/(?Pd+)", views.user)
|
include
|
path("api/", include("allauth.urls"))
|
|
reverse
|
反向生成URL地址,其参数为urls.py中视图函数对应的name参数
|
reverse('add')
|
参数说明
- name:类似于网址的别名,可用于templates、models、views中得到对应的网址,只要这个名字不变,即使网址发生了变化,也能通过这个名字找到正确的网址;
在模板文件中的应用
在视图函数中的应用
- include:路由转发,用于从根路由出发,将app所属url请求转发到子urls.py中,path/re_path中使用;
方法一:只指定urls模块的字符串
方法二:同时指定urls(模块字符串、app_name)、命名空间(当存在多个app时,指定namespace很有必要)
api/urls.py
mblog/urls.py
在template中使用命名空间
在views中使用命令空间
Template
配置
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', # 默认模板引擎 'DIRS': [], # 默认为app目录下的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', ], }, }, ]
- BACKEND:模板引擎,可使用指定的模板引擎,如django.template.backends.jinja2.Jinga2
- DIRS:模板文件目录,默认为app目录下的templates目录,可指定特定的目录,常用方式[os.path.join(BASE_DIR, "templates")]
View中的使用
到底使用哪个模板进行渲染,由views.py的视图函数决定
from django.shortcuts import render # Create your views here. def index(request): return render(request, "index.html")
使用现有模板框架(此处以bootstrap3为例)
目前接触到使用bootstrap3的方法有两种,分别是静态引用和动态加载
- 静态引用
1.安装bootstrap3
pip install django-bootstrap3
2.在settings.py的INSTALLED_APPS中添加bootstrap3应用
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'myapp', 'bootstrap3', ]
3.在模板文件中引用bootstrap3
<head> <meta charset="UTF-8"> {% load bootstrap3 %} {% bootstrap_css %} {% bootstrap_javascript %} <title>MySite</title> </head>
- 动态加载
直接通过bootstrap官网,找到CDN并复制到<head></head>标签中
# 在https://getbootstrap.com/docs/3.4/getting-started/#download网址中,找到BootstrapCDN, # 将其复制到模板文件的<head></head>标签中即可 # jQuery框架同样可以采用此种方式加载 <head> <meta charset="UTF-8"> <title>MySite</title> <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous"> <!-- 可选的 Bootstrap 主题文件(一般不用引入) --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap-theme.min.css" integrity="sha384-6pzBo3FDv/PJ8r2KRkGHifhEocL+1X2rVCTTkUfGk7/0pbek5mMa1upzvWbrUbOZ" crossorigin="anonymous"> <script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"> </script> <!-- 最新的 Bootstrap 核心 JavaScript 文件 --> <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js" integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd" crossorigin="anonymous"> </script> </head>
支持的语法
{%%}{{}}
{% if exp %}
|
条件控制语法,语法同python,使用{% endif %}结束条件控制,可配合{% else %}、{% elif %}使用形成分支结构
|
{% if username %}
登出 {% else %}
登录 {% endif %}
|
{% for %}
|
循环控制语法,语法同python,使用{% endfor %}结束循环控制
|
{% for user in usersusers %}
{{ user.name }} {% endfor %}
|
可配合{% empty %}显示特定内容,内部变量:forloop
注意:内部变量forloop只在{% for %}循环内生效,当检测到{% endfor %}时,forloop即失效不可用
|
{% for user in usersusers %}
{{ user.name }} {% empty %}
There are no athletes. Only computer programmers. {% endfor %}
|
|
forloop.counter:表示循环次数,从1开始开始计数
|
{% for user in users %}
{{ forloop.counter }}: {{ user }} {% endfor %}
|
|
forloop.counter0:也表示循环次数,但是从0开始计数
|
{% for user in users %}
{{ forloop.counter0 }}: {{ user }} {% endfor %}
|
|
forloop.revcounter:循环中剩余元素数量,初始值为元素总数,最后一次为1
|
||
forloop.revcounter0:也是循环剩余元素数量,不过初始值为元素总数-1,最后一次为0
|
||
forloop.first:Bool类型,第一次循环时返回True,否则返回False
|
{% for object in objects %}
{% if forloop.first %}
{% else %}
{% endif %}
{{ object }}
{% endfor %}
|
|
forloop.last:Bool类型,最后一次循环时返回True,否则返回False
|
||
{% extends %}
|
html继承语法,base.html为html模板文件,类比于Python的基类
|
{% extends "base.html" %}
|
{% include %}
|
html引用语法,将其他html模板文件导入到该html文件中,一般用于网页的页眉、页脚
|
{% include "header.html" %}
{% include "footer.html" %}
|
{% load %}
|
html加载静态文件/框架
|
{% load bootstrap3 %}
{% load static %}
|
{% block %}
|
用于继承及实现;在base.html模板文件中定义了{% block %}{% endblock %}之后,所有继承base.html文件的模板文件都必须实现{% block %}{% endblock %}修饰的内容
|
base.html
{% block title %}{% endblock %}
index.html
{% extends "base.html" %}
{% block title %}MySite{% endblock %}
|
使用静态文件
Django中,使用静态文件的方式,可以一度程序上提高性能。而Django的静态文件默认存储在templates/static中
settings.py中的默认配置
# Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/3.2/howto/static-files/ STATIC_URL = '/static/'
# Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/3.2/howto/static-files/ STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR, "static"), ]
<hr> {% load static %} # 加载静态文件 <img src="{% static 'images/logo.png' %}" width=100> <em>Copyright 2016 a <a href="http://www.baidu.com">http://www.baidu.com</a>. All rights reserved. </em>
常用过滤器
过滤器名称
|
用法
|
示例
|
capfirst
|
将字符串首字母大写
|
{{ msg | capfirst }},如果msg内容为"django",则html中显示将变成"Django"
|
center/ljust/rjust
|
为字符串加上指定空格后居中、靠左、靠右对齐
|
{{ msg | center: "15" }}
|
cut
|
在字符串中删除指定的子字符串
|
{{ msg | cut: " " }},如果msg内容为" How are you",则html中显示将变成"Howareyou"
|
date
|
设置日期的显示格式
|
{{ value | date:"D d M Y" }},value为datetime的标准格式。可利用date来设置显示格式
|
default
|
如果没有值,就使用默认值
|
{{ msg | default:"没有信息" }}
|
first/last
|
只取出列表数据中的第一个/最后一个元素
|
{{ values | first }} {{ values | last }},values为列表元素
|
floatformat
|
以指定的浮点数格式显示数据
|
{{ value | floatformat:3 }},如果value为123.45678,则html中显示将变成123.457
|
linebreaks
|
将文字内容中的换行符号转换成HTML的
和 |
{{ msg | linebreaks }}
|
linebreadsbr
|
将文字内容中的换行符号转换成HTML的
|
{{ msg | linebreaksbr }}
|
linenumber
|
为显示的文字内容加上行号
|
{{ msg | linenumber}}
|
lower/upper
|
将显示的文字内容转换成小写/大写
|
{{ msg | lower }} {{ msg | upper }}
|
random
|
以随机数将数据内容显示出来
|
{{ values | random }}
|
safe
|
标记字符串为安全的,不需要再处理转义字符
|
{{ msg | safe }}
|
striptags
|
去掉文字内容中的所有HTML标签
|
{{ msg | striptags }}
|
truncatechars
|
把过长的字符串裁切成指定的长度,并将最后3个字符转换成...
|
{{ msg | truncatchars:12 }}
|
yesno
|
按照值的内容True/False/None,显示出有意义的内容
|
{{ value | yesno:"是,否,可能吧" }}
|
Models
Django中,models负责定义数据模型,通过views中的视图函数与Django Models机制的交互,调用相应的驱动程序接口,实现对数据的存取
配置
# Database # https://docs.djangoproject.com/en/3.2/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': BASE_DIR / 'db.sqlite3', } }
# mysql DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', # 数据库驱动 'NAME': 'event', # 数据库名称(需要先创建) 'USER': 'root', # 数据库用户名 'PASSWORD': '123456', # 数据库密码 'HOST': '', # 数据库主机,留空默认为localhost 'PORT': '3306', # 数据库端口 } }
# postgresql DATABASES = { "default": { "ENGINE": "django.db.backends.postgresql_psycopg2", "NAME": "event", "USER": "postgres", "PASSWORD": "123456", "HOST": "localhost", "PORT": "5432", } }
定义模型类
- 每一个模型都是一个python类,并且继承自django.db.models.Model类
- 该模型的每个属性都表示一个数据库表的字段
- 每个模型自动生成一个auto_increment的id字段,并作为主键
- 内部类Meta:用于指定一些特殊属性,如ordering(排序规则)、unique_together(联合外键)
from django.db import models class Poll(models.Model): name = models.CharField(max_length=200, null=False) create_at = models.DateField(auto_now_add=True) enabled = models.BooleanField(default=False) class Meta: ordering = ("-create_at",) # 定义结果的排序规则,此处按照创建时间进行排序,"-"表示按照倒序排序 def __str__(self): return self.name class PollItem(models.Model): poll = models.ForeignKey(Poll, on_delete=models.CASCADE) # 指定PollItem表的外键为Poll name = models.CharField(max_length=200, null=False) image_url = models.CharField(max_length=200, null=True, blank=True) vote = models.PositiveIntegerField(default=0) def __str__(self): return self.name
使用admin后台管理数据模型
from django.contrib import admin from mysite.models import Poll admin.site.register(Poll)
from django.contrib import admin from mysite.models import Poll, PollItem class PollAdmin(admin.ModelAdmin): list_display = ("name", "create_at", "enabled") ordering = ("-create_at",) class PollItemAdmin(admin.ModelAdmin): list_display = ("poll", "name", "vote", "image_url") ordering = ("poll", ) admin.site.register(Poll, PollAdmin) admin.site.register(PollItem, PollItemAdmin)
- list_display:可迭代对象,其中每个对象对应数据模型中定义的属性,如:list_display = ("name", "create_at", "enabled")
- search_fields:搜索器,可迭代对象,同上,如:search_fields = ("name", "poll")
- ordering:同上,如:ordering = ("-create_at")
- list_filter:过滤器,可迭代对象,如:list_filter = ("enabled")
常用Model属性类型
admin.Model提供的常用属性
AutoField
|
一个IntegerField类型的自增字段类型
|
BooleanField
|
用于存入布尔类型的数据(True/False)
|
CharField
|
用于存放字符型的数据,需要指定数据长度,max_length
|
DateField
|
日期类型,必须是"YYYY-MM-DD"格式
|
DateTimeField
|
日期时间类型,必须是"YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]"
|
DecimalField
|
定点数类型,max_digits指定最大值,decimal_places指定小数位数
|
EmailField
|
电子邮件类型
|
FilePathField
|
文件路径类型
|
FloatField
|
浮点数类型
|
IntegerField
|
integer类型,数值范围从-2147483648g到2147483647
|
BigIntegerField
|
用于存放大的integer类型
|
GenericIPAddressField
|
存放IP地址类型,支持IPv4和IPv6的字符串格式
|
NullBooleanField
|
类似BooleanField类型,但允许为NULL
|
PositiveIntegerField
|
integer类型,范围0~2147483647
|
TextField
|
用于存放文本类型的数据
|
TimeField
|
时间类型,必须是"HH:MM[:ss[.uuuuuu]]"格式
|
URLField
|
用于存放URL地址
|
BinaryField
|
存储原始二进制数据的字段
|
在models.ForeignKey(Poll, on_delete=models.CASCADE)中on_delete参数,支持五种操作:
- on_delete=models.CASCADE:删除被引用的对象时,此对象也一并被删除
# models.py from django.db import models class AClass(models.Model): name = models.CharField(max_length=40) def __str__(self): return self.name class AListClass(models.Model): a_name = models.ForeignKey(AClass, on_delete=models.CASCADE) name = models.CharField(max_length=40) def __str__(self): return self.name # admin.py from django.contrib import admin from mysite.models import AClass, AListClass class AListClassAdmin(admin.ModelAdmin): list_display = ("name", "a_name") # AListClass表显示name字段及外键AClass的name字段 admin.site.register(AClass) admin.site.register(AListClass, AListClassAdmin)
- on_delete=models.PROTECT:禁止删除并抛出异常ProtectdError
# models.py from django.db import models class BClass(models.Model): name = models.CharField(max_length=40) def __str__(self): return self.name class BListClass(models.Model): b_name = models.ForeignKey(BClass, on_delete=models.PROTECT) name = models.CharField(max_length=40) def __str__(self): return self.name # admin.py from django.contrib import admin from mysite.models import BClass, BListClass class BListClassAdmin(admin.ModelAdmin): list_display = ("name", "b_name") admin.site.register(BClass) admin.site.register(BListClass, BListClassAdmin)
- on_delete=models.SET_NULL:当被引用的对象被删除后,依赖它的其他对象的该字段都被设置为NULL;设置此操作时,字段必须设置null=True来允许字段值为NULL
# models.py from django.db import models class CClass(models.Model): name = models.CharField(max_length=40) def __str__(self): return self.name class CListClass(models.Model): c_name = models.ForeignKey(CClass, on_delete=models.SET_NULL, null=True) # 必须指定null=True允许字段值为空 name = models.CharField(max_length=40) def __str__(self): return self.name # admin.py from django.contrib import admin from mysite.models import CClass, CListClass class CListClassAdmin(admin.ModelAdmin): list_display = ("name", "c_name") admin.site.register(CClass) admin.site.register(CListClass, CListClassAdmin)
- on_delete=models.SET_DEFAULT:当被引用的对象被删除后,依赖它的其他对象的该字段都被设置为默认值;设置此操作时,字段必须设置default参数
# models.py from django.db import models class DClass(models.Model): name = models.CharField(max_length=40) def __str__(self): return self.name class DListClass(models.Model): d_name = models.ForeignKey(DClass, on_delete=models.SET_DEFAULT, default=None, null=True) name = models.CharField(max_length=40) def __str__(self): return self.name # admin.py from django.contrib import admin from mysite.models import DClass, DListClass class DListClassAdmin(admin.ModelAdmin): list_display = ("name", "d_name") admin.site.register(DClass) admin.site.register(DListClass, DListClassAdmin)
- on_delete=models.DO_NOTHING:什么事儿都不做?如果你的数据库后端强制引用完整性,它将引发一个IntegrityError ,除非你手动添加一个ON DELETE 约束给数据库