django框架基础详解(二)
1.关联关系
1.一对一
2.一对多
3.多对多
2.一对一关系
场景: 人 (1个)---- 身份证 (1个) 1:1
外键关联格式: 关联的属性 = models.OneToOneField(关联表的类名) django会自动的去外键关联
1.设计模型
1.人
name 姓名
age 年龄
....
2.身份证 idCard
idNumber 身份证号
address 地址
sex 性别
.....
person --- 外键 --- OneToOneField 一对一
例: i_person = models.OneToOneField(Person)
2.插入数据
1.人
person.save()
2.身份证
# 先找到需要绑定的人
person = Person.objects.filter(p_name="三胖胖3").first()
# 外键 --- 绑定对象
idcard.i_person = person
idcard.save()
3.修改
4.删除
1. 如果删除的是主表中的数据, 如果在从表中没有对应的数据,会直接删除该数据
, 如果在从表中存在对应的数据,会连同从表中的数据一同删除
2.如果删除的是从表中的数据,会直接删除该数据,主表中的数据不会受影响
5.表的关系(主 --- 从)
主表(被动连接的一方) ---- 从表(主动连接的一方)
6.设置外键关联的数据的保护模式
on_delete的模式:
models.CASCADE 默认模式, 如果删除的是主表中的数据,如果在从表中存在对应的数据,会连同从表中的数据一同删除
models.PROTECT 保护模式,当删除主表的数据的时候,如果有对应的从表数据,则不能删除,程序报错,
,如果没有对应的从表数据,则正常删除
models.SET_DEFAULT 设置为默认值,当删除主表的数据的时候,如果有对应的从表数据,则主表数据直接删除,从表对应的外键自动设置为默认值
models.SET_NULL 设置为默认值,当删除主表的数据的时候,如果有对应的从表数据,则主表数据直接删除,从表对应的外键自动设置为空值
models.SET(value) 设置为默认值,当删除主表的数据的时候,如果有对应的从表数据,则主表数据直接删除,从表对应的外键自动设置为指定的值
如: i_person = models.OneToOneField(Person,on_delete=models.PROTECT)
2.一对多 ---- ForeignKey
场景: 人(1个)----爱好(多个) 1:N
1.设计表:
1.person表
2.hobby爱好表
name 爱好名
price 爱好的花费
.....
外键:
person人 = models.ForeginKey(类名)
2.添加数据:
1.人
2.爱好
可以给一个人绑定多个爱好
3.修改
4.删除数据
1.如果删除的是主表中的数据,如果从表中没有对应数据,直接删除该主表数据
,如果从表中有对应的数据,会连同从表中对应的(多条)数据一同删除
2.如果删除的是从表中的数据,会直接删除该数据,主表中的数据不会受影响
5.设置外键关联的数据的保护模式 ---跟一对一类似
3.多对多
场景:
用户(1个) ----- 商品(多个)
商品(1个) ------用户(多个)
用户(多个)--- 商品(多个)
1.设计模型
1.buyer 用户
name 名字
age 年龄
.....
2.goods 商品 (相对不重要)
name 商品名
price 商品价格
= models.ManyToManyField()
如:
g_buyer = models.ManyToManyField(Buyer)
3.第三张表用来维护两张表的关系---django可以自动生成
外键关联用户id
外键关联商品id
2.添加数据
如:
# 获得一个购买者
buyer1 = Buyer.objects.filter(pk=1).first()
buyer2 = Buyer.objects.filter(pk=2).first()
buyer3 = Buyer.objects.filter(pk=3).first()
# 获得一个商品
goods = Goods.objects.filter(pk=2).first()
# goods = Goods()
# 添加数据,一对多关系时,用add 表示添加, 且可以添加多个
goods.g_buyer.add(buyer1)
goods.g_buyer.add(buyer2)
goods.g_buyer.add(buyer3)
goods.save()
3.删除数据
1.主表(购买者)
2.主表(商品)
3.(从表)自动生成的表
如果删除的是主表中的数据,如果从表中没有关联的数据,直接删除
,如果从表中有关联的数据,会连同从表中的关联数据(多条)一同删除
4.查询
1.一对一
0.自己查询自己,直接查找到对应的对象既可
1.根据从表中的信息查询主表信息
从表中有一个外键关联的字段,该字段与模型中的属性对应, 我们可以直接通过该 外键属性 直接获取到关联的数据对象
如: # 可以直接获得关联的数据对象
person = idcard.i_person
2.根据主表信息查询从表信息
django在创建主表与从表关系的时候,会 自动 为主表对应的模型,创建一个隐式属性,该隐式属性就是对应的从表数据对象
格式: 主表模型对象.从表模型名的全小写 即直接可以获得从表数据
如: idcard = person.idcard
2.一对多
1.根据从表中的信息查询主表中的信息
可以直接根据外键属性获取对象
2.根据主表中的信息查询从表中的信息
格式: 主表模型对象.从表模型名的全小写_set.查询方法 既可以直接获得从表中对应的多条数据
如: hobbys = person.hobby_set.all()
3.多对多
1.根据从表中的信息查询主表(多条)中的信息
格式: 从表模型对象.外键属性.查询方法
如: buyers = goods.g_buyer.all()
2.根据主表中的信息查询从表(多条)中的信息
格式: 主表模型对象.从表模型名的全小写_set.查询方法
如: goodses = buyer.goods_set.all()
5.django中的隐式属性,显示属性
1.显示属性
开发人员直接定义的属性就是显示属性
2.隐式属性
在django中,django为了便于开发提供了很多的隐式属性(django自带的),这些隐式属性有很多强大的功能, 如: "查询",创建....
6.自定义的manger
需求1: 方便的创建测试数据
1.自定义manager的使用
1.在models中定义一个类(myManager)继承 Manager from django.db.models import Manager
2.在类中既可以定义自己的方法
如: 方便的创建测试数据
def createTestStudnet(self,name,age):
student = Student()
student.s_name = name
student.s_age = age
# .....
student.save()
3.在对应的模型类中添加一个属性 ,该属性值为 自定义manager对象
如: mymanager = myManager()
注意:Manger对象就是我们平时常用的obejcts对象,如果自己定义manager对象,那么objects对象不能使用了
应该使用自己定义manger对象
如:
4.使用
如:
Student.mymanager.createTestStudnet("死胖子",34)
格式: 类名.自己定义的manger对象名.方法()
需求2: 过滤掉已经被逻辑删除的数据
# 过滤掉所有逻辑删除的数据
方法的重写 所有的查询方法
def get_queryset(self):
return super(MyStudentManager, self).get_queryset().exclude(s_isdelete=True)
以上方法需要在myManger中定义,定义后所有的查询方法,会自动的过滤掉逻辑删除的数据
T templates
扫描二维码关注公众号,回复:
3879591 查看本文章
1.templates用来放置模板文件
1.templates 该目录本身没有,如果我们需要使用,需要我们自己创建,该目录名通常为templates
2.创建位置:
1.直接在应用下创建该目录,应用下的html模板,能直接在应用下的views中使用,一般也只给自己的应用使用
2.直接在项目下创建该目录,在项目下创建的改目录,所有的应用中的views都可以方便的使用
3.若果是项目下的templates目录,需要配置才可以使用
配置:1.在setting的TEMPLATES中配置
如: 'DIRS': [os.path.join(BASE_DIR,'templates')],
2.项目不能识别templates为模板目录,需要将该目录标记成模板目录才可以使用
标记: templates目录右键 ---- mark Directory as ---- template Folder
看到目录变成紫色即可
**4,如果遇到template不能识别,重新做以上操作
2.模板语法
1.变量
1.变量通常在views中定义,然后传递给模板,模板中直接使用就可以
2.使用的语法: {{ 变量名 }} 用两个{ 括起来
3.注意: 如果模板板中的变量没有定义就使用了, 模板不会报错,当作空使用
2. 语法
1. . 可以用来调用属性
格式: 对象名.属性名
2. . 可以用来调用方法
格式: 对象名.方法名 注意不加()
3. 如果. 用在集合(list,tuple...)的 后面,可以连接索引, 可以获取索引位置的值
格式: 集合.索引 相当于python的: 集合[索引]
4. 如果 . 用在字典的后面, 可以连接 可以,可以获取key对应的值
格式: 字典.key 相当于python的: 字典[key]
3. for 循环 注意: 有结束标签 {% endfor %}
1.格式1:
{% for 变量名 in 集合名 %}
循环体
{% endfor %}
2.格式2:
{% for 变量名 in 集合名 %}
循环体
{% empty %}
如果集合为空,应该显示的内容
{% endfor %}
3.forloop 循环的技术器
forloop.counter 从1开始计数
forloop.counter0 从0开始计数
forloop.first 是否是第一个数据
forloop.last 是否是最后一个数据
forloop.revcounter 从1开始计数, 倒着计数,即最大数是第一个
forloop.revcounter0 从0开始计数, 倒着计数,即最大数是第一个
4.判断语句
1.格式1:
{% if 判断表达式 %}
{% endif %}
2.格式2:
{% if 判断表达式 %}
如果满足条件就执行表达式1
{% else %}
否则执行表达式2
{% endif %}
3.格式3:
{% if 判断表达式1 %}
如果满足条件1就执行表达式1
{% elif 判断表达式2 %}
如果满足条件2就执行表达式2
{% else %}
否则执行表达式3
{% endif %}
4.格式4: 判断2个值是否相等
{% ifequal valu1 value2 %}
如果value1 等于value2执行表达式
{% endifequal %}
注意: 当value1与value2值相等,且类型也一样的时候才成立
5.格式5: 判断2个值是否不相等
{% ifnotequal valu1 value2 %}
如果value1 等于value2执行表达式
{% endifnotequal %}
6.比较运算符
>
>=
<=
==
!=
**表示范围的语法结果一般有结束标签,一般是{% 括弧
5.注释:
{# 这是模板语法中的单行注释 快捷键: ctrl + / #}
{% comment %}
这是多行注释 快捷键: ctrl + shift + /
{% endcomment %}
<!-- 这是HTML的注释 -->
6.其他
1.加法/减法运算
加法: 格式: {{ value|add:值 }} value + 值
加法: 格式: {{ value|add:-值 }} value - 值
2.乘法/除法运算
格式: {% widthratio value 分母 分子 %}
相当于 value * 分子/分母
除法 {% widthratio value 分母 1 %}
乘法 {% widthratio value 1 分子 %}
3.是否整除某个数
格式:{{ value|divisibleby:值 }} value是否能整除 值
需求:隔行换色
{% if forloop.counter0|divisibleby:2 %}
4.大小写转换
转换成小写:{{ value|lower }}
转换成大写:{{ value|upper }}
5.字符串拼接
字符串拼接: {{ 集合|join:"拼接的字符" }}
7.转意字符
1.问题:默认情况下,如果views视图函数传递给模板的是一个 html格式的字符串, 默认模板中html标签不会生效,而有时候需要html标签生效
2.使得标签生效:
1. 在模板中 使用{{ 变量|safe }} 是得变量的字符串中的html标签生效
2. 使用 autoescape
{% autoescape on %}
{# 这里面的内容就是不生效的HTML字符串#}
{{ strHtml }}
{% endautoescape %}
{% autoescape off %}
{# 这里面的内容就是可以生效的HTML字符串#}
{{ strHtml }}
{% endautoescape %}
8.模板的继承 — 子模板可以继承一个父模板,即可以继承父模板的css,html,js
1.如何继承:
1.定义一个父模板base.html, 通常在父模板写一些通用的功能
2.定义一个字模板index.html,在子模板的首行写 {% extends '父模板路基' %} 既可以继承父模板中的所有的css.html.js
2.在继承中可以block来在父模板中挖坑,挖坑可以给子类内容设置一个预留位置,方便子类在对应的位置填充内容
1.在父类中挖坑
在需要填充子模板内容的地方 写上 :
{% block 坑的名字 %}
{% endblock %}
2.在子模板中填坑
{% block 坑的名字 %}
填充的内容
{% endblock %}
3.第一次表示是挖坑
第二次表示填坑
第3-n次会覆盖之前的坑
4.如果填坑的时候,希望保留父模板的内容,可以在 填坑的首行加上 {{ block.super }}
如: {% block head %}
{# 保留父模板的内容 #}
{{ block.super }}
<h1>这是三级头盔</h1>
{% endblock %}
5.可以挖多个坑
6.填坑的时候不需要按照顺序
7.没有填的坑,就是空内容
好处:1.html代码可以复用
2.可以灵活的写内容
3.思想:
1.化整为零 ---- 将一个完整的html用block划分成很多的小块, 开发者只需要考虑填充对应的小模块即可...
2.化零为整 ---- 将多个零散的html用 include在一个html中包含进来, 可以拼接成一个完整的html
{# 将零散的html 拼接成一个完整的html #}
{% include 'head.html' %}
{% include 'bannar.html' %}
{% include 'foot.html' %}
9.模板的简单加载原理
# 模板的加载过程
def loadTem(request):
1.# 先将模板加载到views函数中
template = loader.get_template("loadTem.html")
2.# 把数据给模板,并转换成html形式的字符串
htmlData = template.render(context={"content":"内容xxxxxx"})
3.# 把数据作为相应体,给客户端 html本质就是字符串
return HttpResponse(htmlData)
# return render(request,"loadTem.html",context={"content":"内容"})
url — 路由, 根据url地址分配视图函数来处理不同的请求
1.urls分离,见详解(一)
2.django中urls的匹配规则
url(正则表达式,视图函数)
1.遵从python中正则表达式的匹配规则,按照正则匹配成功后,会调用对应的视图函数
2.在django的urls中会有很多个url,路径是从上至下匹配,如果其中的一个没有匹配成功则会继续向下匹配
,如果匹配成功,会调用对应的实函数,
注意:匹配成功后不会继续匹配了
** 为了防止匹配冲突,最好在正则的 后面 加上特定的字符 如: $ 结束, 最好用 /