一、内容回顾
1、Django请求的生命周期:
路由系统 -> 视图函数(获取模板+数据 -> 渲染) -> 字符串返回给用户
2、路由系统:
/index/ #-> 函数或类.as_view()
/detail/(\d+) #-> 函数(参数) 或 类.as_view()(参数)
/detail/(?P<nid>\d+) #-> 函数(参数) 或 类.as_view()(参数)
/detail/ #-> include("app01.urls")
/detail/ name='a1' #-> include("app01.urls")
#-> 视图中:reverse
#-> 模板中:{% url "a1" %}
3、视图:
-
FBV:函数
def index(request,*args,**kwargs):
-
CBV:类
class Home(views.View):
def get(self,reqeust,*args,**kwargs):
-
获取用户请求中的数据:
request.POST.get request.GET.get reqeust.FILES.get() # checkbox,select ........getlist()
-
文件对象
文件对象 = reqeust.FILES.get() 文件对象.name 文件对象.size 文件对象.chunks() # 直接循环文件对象也可以 # 特殊的设置 <form action="/login/" method="POST" enctype="multipart/form-data">
-
给用户返回数据:
render(request, "模板文件路径", {'k1': [1,2,3,4],"k2": {'name': 'fgf','age': 73}}) redirect("URL") HttpResponse('字符串')
4、模板语言
render(request, "模板路径", {'obj': 1234, 'k1': [1,2,3,4],"k2": {'name': 'fgf','age': 22}})
<html>
<body>
<h1> {{ obj }} </h1> # 取变量值
<h1> {{ k1.3 }} </h1> # 取列表的值
<h1> {{ k2.name }} </h1> # 取字典的值
{% for i in k1 %} # 循环列表的值
<p> {{ i }} </p> # 取值
{% endfor %}
{% for row in k2.keys %} # 循环取字典key
{{ row }} # 取值
{% endfor %}
{% for row in k2.values %} # 循环取字典values
{{ row }} # 取值
{% endfor %}
{% for k,v in k2.items %} # 循环取key、values
{{ k }} - {{v}} # 取值
{% endfor %}
# 注意:模板语言循环keys、values、items这里不加 "()"
</body>
</html>
5、ORM
- a. 创建类和字段
class User(models.Model):
age = models.IntergerFiled() # 整数在后面加长度不起作用
name = models.CharField(max_length=10) # 字符长度
# 生成数据库结构命令
Python manage.py makemigrations
python manage.py migrate
# settings.py 配置 注册APP
- b. 操作
# 增
models.User.objects.create(name='qianxiaohu',age=18) # 第一种
dic = {'name': 'xx', 'age': 19} # 第二种
models.User.objects.create(**dic) # **dic
obj = models.User(name='xiao',age=18) # 第三种
obj.save()
# 删
models.User.objects.filter(id=1).delete()
# 改
models.User.objects.filter(id__gt=1).update(name='alex',age=84)
dic = {'name': 'xx', 'age': 19}
models.User.objects.filter(id__gt=1).update(**dic)
# 查
models.User.objects.filter(id=1,name='root')
models.User.objects.filter(id__gt=1,name='root')# 大于
models.User.objects.filter(id__lt=1) # 小于
models.User.objects.filter(id__gte=1) # 大于等于
models.User.objects.filter(id__lte=1) # 小于等于
models.User.objects.filter(id=1,name='root')
dic = {'name': 'xx', 'age__gt': 19}
models.User.objects.filter(**dic) # 这里也可以传字典,增删改查都可以加字典
二、Django ORM 外键操作一对多
a.1、创建一对多表结构
class Business(models.Model):
# id
caption = models.CharField(max_length=32)
code = models.CharField(max_length=32,null=True,default="SA")
# 新增列 允许为空null=True 或 default="SA",就不会提示信息
class Host(models.Model):
nid = models.AutoField(primary_key=True)
hostname = models.CharField(max_length=32,db_index=True) # 加上索引
ip = models.GenericIPAddressField(protocol="ipv4",db_index=True)
port = models.IntegerField()
b = models.ForeignKey(to="Business", to_field='id') # 表中生成列名:b_id
# b = models.ForeignKey("Business", to_field='id') # 外键约束,
# b = models.ForeignKey("Business") #只写表名,默认与那张表主键关联
# 外键:
# v = models.Host.objects.filter(nid__gt=0)
# v[0].b.caption #----> 通过.进行跨表
a.2 获取单表数据的三种方式
v1 = models.Business.objects.all()
QuerySet类型 ,内部元素都是对象(对象内类似字典结构)v2 = models.Business.objects.all().values('id','caption')
QuerySet ,内部元素都是字典
v3 = models.Business.objects.all().values_list('id','caption')
QuerySet ,内部元素都是元组- ===============
models.Business.objects.get(id=1)
获取到的一个对象,如果不存在就报错obj = models.Business.objects.filter(id=1).first()
对象或者None
a.3、示例:展示业务线
urls.py
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^business$', views.business),
]
views.py
from django.shortcuts import render, redirect, HttpResponse
from app01 import models
def business(request):
v1 = models.Business.objects.all()
# QuerySet
# [obj(id,caption,code), obj(id,caption,code), obj(id,caption,code)]
v2 = models.Business.objects.values('id','caption')
# QuerySet
# [{'id':1,'caption':'运维'},{'id':1,'caption':'运维'},{'id':1,'caption':'运维'}]
v3 = models.Business.objects.values_list('id','caption')
# QuerySet
# [(1,运维),(2,开发)]
return render(request, "business.html", {'v1':v1,'v2':v2 ,'v3':v3})
business.html
<body>
<h1>业务线列表(对象)</h1>
<ul>
{% for row in v1 %}
<li>{{ row.id }} - {{ row.caption }} - {{ row.code }}</li>
{% endfor %}
</ul>
<h1>业务线列表(字典)</h1>
<ul>
{% for row in v2 %}
<li>{{ row.id }} - {{ row.caption }}</li>
{% endfor %}
</ul>
<h1>业务线列表(元组)</h1>
<ul>
{% for row in v3 %}
<li>{{ row.0 }} - {{ row.1 }}</li>
{% endfor %}
</ul>
</body>
b.1、一对多跨表操作
一定要注意:“.”和“__”跨表,在不同场景的应用。
点跨表,点的是对象,双下划线,是在filter里的字符串中。
b.2、一对多块表操作的的三种方式
具体用法看示例,及注释
b.3、示例:host主机列表
urls.py
url(r'^host$', views.host),
views.py
def host(request):
v1 = models.Host.objects.filter(nid__gt=0) # 同 all()
# QuerySet [host 对象,]
for row in v1:
print(row.nid,row.b_id,row.b.caption,sep='\t') # 注意 row.b.caption 的含义
# 注意:这里通过"__"双下划线跨表。'b__caption'
v2 = models.Host.objects.filter(nid__gt=0).values('nid','hostname','b_id','b__caption')
# QuerySet: [ {} ]
print(v2)
for row in v2:
print(row['nid'], row['hostname'],row['b_id'], row['b__caption'])
# 注意:这里通过"__"双下划线跨表。'b__caption'
v3= models.Host.objects.filter(nid__gt=0).values_list('nid','hostname','b_id','b__caption')
# QuerySet: [ () ]
b_list = models.Business.objects.all()
return render(request, 'host.html', {'v1':v1, 'v2':v2, 'v3':v3, 'b_list':b_list})
<body>
<h1>主机列表(对象)</h1>
<table border="1">
<thead>
<tr>
<th>主机名</th>
<th>IP</th>
<th>端口</th>
<th>业务线名称</th>
</tr>
</thead>
<tbody>
{% for row in v1 %}
<tr hid="{{ row.nid }}" bid="{{ row.b.id }}">
{# 主机id不需要让用户看见,但修改时又需要,所以自定义个属性#}
<td>{{ row.hostname }}</td>
<td>{{ row.ip }}</td>
<td>{{ row.port }}</td>
<td>{{ row.b.caption }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<hr>
<h1>主机列表(字典)</h1>
<table border="1">
<thead>
<tr>
<th>主机名</th>
<th>业务线名称</th>
</tr>
</thead>
<tbody>
{% for row in v2 %}
<tr hid="{{ row.nid }}" bid="{{ row.b.id }}">
<td>{{ row.hostname }}</td>
<td>{{ row.b__caption }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<hr>
<h1>主机列表(元组)</h1>
<table border="1">
<thead>
<tr>
<th>主机名</th>
<th>业务线名称</th>
</tr>
</thead>
<tbody>
{% for row in v3 %}
<tr hid="{{ row.0 }}" bid="{{ row.2 }}">
<td>{{ row.1 }}</td>
<td>{{ row.3 }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
c、增加一对多数据示例
如果前端展示序号的话,模板语言for循环那里有几个点可以实现。
{% for row in v1 %} # 假设3条数据
{{ forloop.counter}} # 依次为:1、2、3
{{ forloop.counter0}} # 依次为:0、1、2
{{ forloop.revcounter}} # 依次为:3、2、1
{{ forloop.revcounter0}} # 依次为:2、1、0
{{ forloop.last }} # 是否最后一个,是为True,其他False
{{ forloop.first }} # 是否第一个
{{ forloop.parentloop }} # 嵌套循环,表示上层循环的上面的六个值分别是多少。
{% endfor %}
CSS 知识点position回顾:
-
fixed
:生成绝对定位的元素,相对于浏览器窗口进行定位。元素的位置通过 “left”, “top”, “right” 以及 “bottom” 属性进行规定。 -
relative
:生成相对定位的元素,相对于其正常位置进行定位。因此,”left:20” 会向元素的 LEFT 位置添加 20 像素。 -
absolute
:生成绝对定位的元素,相对于第一个父元素进行定位 (static 定位除外外)。元素的位置通过 “left”, “top”, “right” 以及 “bottom” 属性进行规定。
上面的b.3示例,views里host函数,修改为:
def host(request):
if request.method == "GET":
v1 = models.Host.objects.filter(nid__gt=0)
v2 = models.Host.objects.filter(nid__gt=0).values('nid','hostname','b_id','b__caption')
v3 = models.Host.objects.filter(nid__gt=0).values_list('nid','hostname','b_id','b__caption')
b_list = models.Business.objects.all()
return render(request, 'host.html', {'v1': v1,'v2': v2,'v3': v3,'b_list':b_list})
elif request.method == "POST":
h = request.POST.get('hostname')
i = request.POST.get('ip')
p = request.POST.get('port')
b = request.POST.get('b_id')
models.Host.objects.create(hostname=h,
ip=i,
port=p,
# b=models.Business.objects.get(id=b) # 效果一样,只是多了一次数据库查询操作
b_id=b
)
# renturn render(request, 'host.html') # 每次post提交都会有刷新操作
# 使用render需要返回模板数据,if条件里的代码再写一遍,为了提高重用性,让用户再次访问。
return redirect('/host')
host.html (部分与上面重复的代码略,行数太多,有些合并为一行了),需要加载jQury。
<head>
<style>
.hide{ display: none; }
.shade{
position: fixed;
top: 0; right: 0; left: 0; bottom: 0;
background: black;
opacity: 0.6; z-index: 100;
}
.add-modal{
position: fixed;
height: 300px; width: 400px; margin-left: -200px; top:100px; left: 50%;
background: white; border: 1px solid red;
z-index: 101;
}
</style>
</head>
<body>
<h1>主机列表(对象)</h1>
<div>
<input id="add_host" type="button" value="添加" />
</div>
<table border="1">
<thead>
<tr>
<th>序号</th>
<th>主机名</th>
<th>IP</th>
<th>端口</th>
<th>业务线名称</th>
</tr>
</thead>
<tbody>
{% for row in v1 %}
<tr hid="{{ row.nid }}" bid="{{ row.b_id }}">
<td>{{ forloop.counter }}</td>
<td>{{ row.hostname }}</td>
<td>{{ row.ip }}</td>
<td>{{ row.port }}</td>
<td>{{ row.b.caption }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="shade hide"></div>
<div class="add-modal hide">
<form method="POST" action="/host">
<div class="group">
<input id="host" type="text" placeholder="主机名" name="hostname" />
</div>
<div class="group">
<input id="ip" type="text" placeholder="IP" name="ip" />
</div>
<div class="group">
<input id="port" type="text" placeholder="端口" name="port" />
</div>
<div class="group">
<select id="sel" name="b_id">
{% for op in b_list %}
<option value="{{ op.id }}">{{ op.caption }}