提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
提示:这里可以添加本文要记录的大概内容:
Django学习笔记
提示:以下是本篇文章正文内容,下面案例可供参考
一、创建虚拟环境
$ py -3 -m venv venv
激活虚拟环境
venv\Scripts\activate
pip install -r requirements.txt
二、请求与响应
新建项目
$ django-admin startproject (mysite)
启动开发
$ python manage.py runserver
指定端口,请在命令中显示给出:
$ python manage.py runserver 8080
修改服务器的ip地址,请按下面的方式运行命令,比如:
$ python manage.py runserver 0:8000
创建APP
python manage.py firstWEB
进入mysite项目根目录,输入以下 系统自动生成polls应用目录
python manage.py startapp (polls)
模板渲染嵌入语法
{% 命令 %} {{变量}}
三、模型层
模型与后台
数据库配置
创建数据表
python manage.py migrate
创建模型
定义模型
一个模型(model)就是一个单独的、确定的数据的信息源,包含了数据的字段和操作方法。通常,每个模型映射为一张数据库中的表。每个类的实例代表数据表中的一行数据,类中的每个变量代表数据表中的一列字段。
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
#django自动生成表名,默认格式为“项目名称+下划线+小写类名”
CREATE TABLE myapp_person (
"id" serial NOT NULL PRIMARY KEY,
"first_name" varchar(30) NOT NULL,
"last_name" varchar(30) NOT NULL
);
启用模型
将应用添加到项目中,在installed_apps设置中增加指向该应用的配置文件的链接。
它的配置类文件PollsConfig
位于polls/apps.py
脚本内,所以配置的点式路径为polls.apps.PollsConfig
、‘polls’
修改模型操作:
- 在models.py中修改模型;
- 运行
python manage.py makemigrations
为改动创建迁移记录文件(创建库表); - 运行
python manage.py migrate
,将操作同步到数据库(执行表建立)。
python manage.py makemigrations (polls)
模型隐藏属性_state
_state
属性指向一个ModelState类实例,它持续跟踪着模型实例的生命周期。
_state
自己又有2个属性:adding和db
- adding:一个标识符,如果当前的模型实例还没有保存到数据库内,则为True,否则为False(新创建的模型实例:
adding=True
&& 从某个数据库中读取出来的模型实例:adding=False
) - db:一个字符串指向某个数据库,当前模型实例是从该数据库中读取出来的。(新创建的模型实例:
db=None
&& 从某个数据库中读取出来的模型实例:db='数据库名'
)
模型方法
Python的实例方法
如果需要针对每个模型实例都有效的业务代码,应该把它们抽象成为一个函数,放到模型中成为模型方法
__str__()
: 这个其实是Python的魔法方法,用于返回实例对象的打印字符串。
get_absolute_url()
: 这个方法是返回每个模型实例的相应的访问url。具体看后面的章节。
__hash__()
:给模型实例提供唯一的哈希值。
模型字段fields
字段命名约束:
与Python关键字冲突。
字段名中不能有两个以上下划线在一起,因为两个下划线是Django的查询语法。
字段名不能以下划线结尾
关系类型字段
多对一(ForeignKey)
通过外键可以把数据和另一张表关联起来
class ForeignKey(to, on_delete, **options)
from django.db import models
class Manufacturer(models.Model):
# ...
pass
#外键定义在‘多’的一方
class Car(models.Model):
manufacturer = models.ForeignKey(Manufacturer, on_delete=models.CASCADE)
worker = models.ForeignKey('Worker', on_delete=models.CASCADE)
# ...
class Worker(models.Model):
# ...
pass
外键on_delete参数可选的值都内置在django.db.models
中(全部为大写),包括:
- CASCADE:模拟SQL语言中的
ON DELETE CASCADE
约束,将定义有外键的模型对象同时删除! - PROTECT:阻止上面的删除操作,但是弹出
ProtectedError
异常 - SET_NULL:将外键字段设为null,只有当字段设置了
null=True
时,方可使用该值。 - SET_DEFAULT:将外键字段设为默认值。只有当字段设置了default参数时,方可使用。
- DO_NOTHING:什么也不做。
- SET():设置为一个传递给SET()的值或者一个回调函数的返回值。注意大小写。
- related_name:用于关联对象反向引用模型的名称。
- related_query_name:反向关联查询名。用于从目标模型反向过滤模型对象的名称。
一对一
class OneToOneField(to, on_delete, parent_link=False, **options)
多对多
默认中间表
class Person(models.Model):
name = models.CharField(max_length=128)
def __str__(self):
return self.name
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person)
def __str__(self):
return self.name
通过members字段,以ManyToMany方式与Person建立关系
自定义中间表
通过ManyToManyField的 through参数指定中间模型
members = models.ManyToManyField(Person, through='Membership')
class Membership(models.Model):
字段的参数
null:该值为True时,Django在数据库用NULL保存空值。
blank: True时,字段可以为空。默认False。
choices:用于页面上的选择框标签,需要先提供一个二维的二元元组,第一个元素表示存在数据库内真实的值,第二个表示页面上显示的具体内容。
元数据Meta
指的是“除了字段外的所有内容”,例如排序方式、数据库表名、人类可读的单数或者复数名等等。每个模型都可以有自己的元数据类,每个元数据类也只对自己所在模型起作用。
模型的继承
Django有三种继承的方式:
- 抽象基类:被用来继承的模型被称为
Abstract base classes
,将子类共同的数据抽离出来,供子类继承重用,它不会创建实际的数据表; - 多表继承:
Multi-table inheritance
,每一个模型都有自己的数据库表,父子之间独立存在; - 代理模型:如果你只想修改模型的Python层面的行为,并不想改动模型的字段,可以使用代理模型。
抽象基类
在模型的Meta类里添加abstract=True
元数据项,就可以将一个模型转换为抽象基类。
如果子类没有声明自己的Meta类,那么它将自动继承抽象基类的Meta类。(抽象基类中的abstract=True
这个元数据不会被继承。)
如果抽象基类中存在ForeignKey或者ManyToManyField字段,并且使用了related_name
或者related_query_name
参数
多表继承
在多表继承的i情况下django会关闭子类继承父类的Meta功能,但ordering
和get_latest_by
,这两个参数是会被继承的
代理模型
声明一个代理模型只需要将Meta中proxy的值设为True
可以在代理模型中改变默认的排序方式和默认的manager管理器等等,而不会对原始模型产生影响。
- 代理模型必须继承自一个非抽象的基类,并且不能同时继承多个非抽象基类;
- 代理模型可以同时继承任意多个抽象基类,前提是这些抽象基类没有定义任何模型字段。
- 代理模型可以同时继承多个别的代理模型,前提是这些代理模型继承同一个非抽象基类。
查询操作
创建对象
使用模型类的实例化构造方法:
>>> from blog.models import Blog
>>> b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')
>>> b.save()
creat()
方法,它可以省略save的步骤,比如:
b = Blog.objects.create(name='刘江的博客', tagline='主页位于liujiangblog.com.')
修改对象并保存
检索对象
通过管理器(Manager)操作数据库并返回一个查询结果集(QuerySet)
filter(**kwargs)
:返回一个根据指定参数查询出来的QuerySetexclude(**kwargs)
:返回除了根据指定参数查询出来结果的QuerySet
四、后台管理站点
创建管理员
python manage.py createsuperuser
启动开发服务器
python manage.py runserver
注册应用
在站点中注册模型
admin.site.register(模型)
fieldsets 用来控 布局,要求 格式是有两 元素的 tuple list 如:
fieldsets = (
(名称,{内容}),
(名称,{内容}),
)
五、视图层
编写视图
在app/views.py文件中设置请求与响应函数
def index(request):
return HttpResponse()
在app/urls.py文件中加入路由
path('',views.index,name='index')
返回HttpResponse对象快捷方式render()
from django.shortcuts import render
from .models import Question
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)
def index(request):
latest_question_list = Question.objects.order_by('-pub_date')[:5]
template = loader.get_template('polls/index.html')
context = {'latest_question_list': latest_question_list}
return HttpResponse(template.render(context,request))
返回404错误get_object_or_404()
obj = get_object_or_404(SomeModel, id=1)
==
try:
obj = SomeModel.objects.get(id=1)
except SomeModel.DoesNotExist:
raise Http404("No SomeModel matches the given query.")
URl
解耦硬代码
<a href="/post/{{ post.id }}.html">{{ post.title }}</a>
属于紧耦合
六、类视图
基于类的视图:
- 通过HTTP请求方法的不同,将代码分隔在不同的类方法中,比如GET和POST,而不是类函数中的条件判断。
- 可以使用面向对象的技巧,比如混入。
- 类具有封装和继承的特性,方便代码复用、分发和重构。
场景不同:
- 简单逻辑、快速处理,请用函数视图FBV
- 代码复用、功能封装,请用类视图CBV
每个类视图都有一个as_view()
方法,用于在urlconf
中进行dispatch。
class-based view
View、TemplateView、DetailView、ListView
#function view
def my_view(request):
if request.method == 'GET':
return HttpResponse('result')
#class-based view
class MyView(View):
def get(self, request):
return HttpResponse('result')
解耦了Http GET请求、POST请求以及其他请求
测试
创建测试
运行测试
查找投票应用中所有的测试程序
python manage.py test (app)
过滤器
过滤器,变量的显示形式的改变
一、形式:小写
{{ name | lower }}
二、串联:先转义文本到HTML,再转换每行到
标签
{{ my_text|escape|linebreaks }}
三、过滤器的参数
显示前30个字
{{ bio | truncatewords:“30” }}
格式化
{{ pub_date | date:“F j, Y” }}
过滤器列表
{{ 123|add:“5” }} 给value加上一个数值
{{ “AB’CD”|addslashes }} 单引号加上转义号,一般用于输出到javascript中
{{ “abcd”|capfirst }} 第一个字母大写
{{ “abcd”|center:“50” }} 输出指定长度的字符串,并把值对中
{{ “123spam456spam789”|cut:“spam” }} 查找删除指定字符串
{{ value|date:“F j, Y” }} 格式化日期
{{ value|default:“(N/A)” }} 值不存在,使用指定值
{{ value|default_if_none:“(N/A)” }} 值是None,使用指定值
{{ 列表变量|dictsort:“数字” }} 排序从小到大
{{ 列表变量|dictsortreversed:“数字” }} 排序从大到小
{% if 92|divisibleby:“2” %} 判断是否整除指定数字
{{ string|escape }} 转换为html实体
{{ 21984124|filesizeformat }} 以1024为基数,计算最大值,保留1位小数,增加可读性
{{ list|first }} 返回列表第一个元素
{{ “ik23hr&jqwh”|fix_ampersands }} &转为&
{{ 13.414121241|floatformat }} 保留1位小数,可为负数,几种形式
{{ 13.414121241|floatformat:“2” }} 保留2位小数
{{ 23456 |get_digit:“1” }} 从个位数开始截取指定位置的1个数字
{{ list|join:", " }} 用指定分隔符连接列表
{{ list|length }} 返回列表个数
{% if 列表|length_is:“3” %} 列表个数是否指定数值
{{ “ABCD”|linebreaks }} 用新行用
、
标记包裹
{{ “ABCD”|linebreaksbr }} 用新行用
标记包裹
{{ 变量|linenumbers }} 为变量中每一行加上行号
{{ “abcd”|ljust:“50” }} 把字符串在指定宽度中对左,其它用空格填充
{{ “ABCD”|lower }} 小写
{% for i in “1abc1”|make_list %}ABCDE,{% endfor %} 把字符串或数字的字符个数作为一个列表
{{ “abcdefghijklmnopqrstuvwxyz”|phone2numeric }} 把字符转为可以对应的数字??
{{ 列表或数字|pluralize }} 单词的复数形式,如列表字符串个数大于1,返回s,否则返回空串
{{ 列表或数字|pluralize:“es” }} 指定es
{{ 列表或数字|pluralize:“y,ies” }} 指定ies替换为y
{{ object|pprint }} 显示一个对象的值
{{ 列表|random }} 返回列表的随机一项
{{ string|removetags:“br p div” }} 删除字符串中指定html标记
{{ string|rjust:“50” }} 把字符串在指定宽度中对右,其它用空格填充
{{ 列表|slice:“:2” }} 切片
{{ string|slugify }} 字符串中留下减号和下划线,其它符号删除,空格用减号替换
{{ 3|stringformat:“02i” }} 字符串格式,使用Python的字符串格式语法
{{ “EABCD”|striptags }} 剥去[X]HTML语法标记
{{ 时间变量|time:“P” }} 日期的时间部分格式
{{ datetime|timesince }} 给定日期到现在过去了多少时间
{{ datetime|timesince:“other_datetime” }} 两日期间过去了多少时间
{{ datetime|timeuntil }} 给定日期到现在过去了多少时间,与上面的区别在于2日期的前后位置。
{{ datetime|timeuntil:“other_datetime” }} 两日期间过去了多少时间
{{ “abdsadf”|title }} 首字母大写
{{ “A B C D E F”|truncatewords:“3” }} 截取指定个数的单词
{{ “111221”|truncatewords_html:“2” }} 截取指定个数的html标记,并补完整
- {{ list|unordered_list }}
{{ string|upper }} 全部大写
linkage url编码
{{ string|urlize }} 将URLs由纯文本变为可点击的链接。(没有实验成功)
{{ string|urlizetrunc:“30” }} 同上,多个截取字符数。(同样没有实验成功)
{{ “B C D E F”|wordcount }} 单词数
{{ “a b c d e f g h i j k”|wordwrap:“5” }} 每指定数量的字符就插入回车符
{{ boolean|yesno:“Yes,No,Perhaps” }} 对三种值的返回字符串,对应是 非空,空,None