一、内容回顾
1、Django请求的生命周期:
路由系统 -> 视图函数(获取模板+数据 -> 渲染) -> 字符串返回给用户
2、路由系统:
/index/ #-> 函数或类.as_view()/detail/(\d+) #-> 函数(参数) 或 类.as_view()(参数)/detail/(?P\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.getrequest.GET.getreqeust.FILES.get()# checkbox,select........getlist()
文件对象
文件对象 = reqeust.FILES.get()文件对象.name文件对象.size文件对象.chunks() # 直接循环文件对象也可以# 特殊的设置
给用户返回数据:
render(request, "模板文件路径", { 'k1': [1,2,3,4],"k2": { 'name': 'lgeng','age': 73}})redirect("URL") HttpResponse('字符串')
4、模板语言
render(request, "模板路径", { 'obj': 1234, 'k1': [1,2,3,4],"k2": { 'name': 'lgeng','age': 22}})
{ { obj }}
# 取变量值{ { k1.3 }}
# 取列表的值{ { k2.name }}
# 取字典的值{% for i in k1 %} # 循环列表的值{
{ i }} # 取值{% 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这里不加 "()"
5、ORM
- a. 创建类和字段
class User(models.Model): age = models.IntergerFiled() # 整数在后面加长度不起作用 name = models.CharField(max_length=10) # 字符长度# 生成数据库结构命令Python manage.py makemigrationspython 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) # **dicobj = 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 viewsurlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^business$', views.business),]
views.py
from django.shortcuts import render, redirect, HttpResponsefrom app01 import modelsdef 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
业务线列表(对象)
- {% for row in v1 %}
- { { row.id }} - { { row.caption }} - { { row.code }} {% endfor %}
业务线列表(字典)
- {% for row in v2 %}
- { { row.id }} - { { row.caption }} {% endfor %}
业务线列表(元组)
- {% for row in v3 %}
- { { row.0 }} - { { row.1 }} {% endfor %}
b.1、一对多跨表操作
一定要注意:“.”和“__”跨表,在不同场景的应用。
点跨表,点的是对象,双下划线,是在filter里的字符串中。
b.2、一对多块表操作的的三种方式
具体用法看示例,及注释
b.3、示例:host主机列表
urls.py
url(r'^host$', views.host),
- 1
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})
host.html
主机列表(对象)
主机名 | IP | 端口 | 业务线名称 |
---|---|---|---|
{ { row.hostname }} | { { row.ip }} | { { row.port }} | { { row.b.caption }} |
主机列表(字典)
主机名 | 业务线名称 |
---|---|
{ { row.hostname }} | { { row.b__caption }} |
主机列表(元组)
主机名 | 业务线名称 |
---|---|
{ { row.1 }} | { { row.3 }} |
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。
主机列表(对象)
序号 | 主机名 | IP | 端口 | 业务线名称 |
---|---|---|---|---|
{ { forloop.counter }} | { { row.hostname }} | { { row.ip }} | { { row.port }} | { { row.b.caption }} |
d、初识Ajax
上面是通过模态对话框实现的,但是有个弊端,就是弹出框里一点提交,页面肯定会刷新。如果用户输错,应该显示错误提示,而不是刷新页面
所以希望有个功能可以用户输完之后,悄悄发送数据给后台,页面不刷新。后台拿到之后再给个回复。
悄悄提交,用Ajax提交。
这里Ajax 用来实现。依赖于xml http request 对象来发的。
$.ajax({ url: '/host', // 提交地址 type: "POST", // 提交方式 data: {'k1': 123,'k2': "root"}, // 提交数据 success: function(data){ // data是服务器端返回的字符串 // 等服务器返回数据后,自动触发这个函数 var obj = JSON.parse(data); // 把字符串转换成对象 }})
Ajax请求return 用HttpResponse
obj = JSON.parse(data)
把字符串转换成对象JSON.stringfy(obj)
前端把对象转换成字符串
host.html 添加:
urls.py
url(r'^test_ajax$', views.test_ajax),
- 1
views.py
def test_ajax(request): import json ret = { 'status': True, 'error': None, 'data': None} try: h = request.POST.get('hostname') i = request.POST.get('ip') p = request.POST.get('port') b = request.POST.get('b_id') if h and len(h) > 5: models.Host.objects.create(hostname=h, ip=i, port=p, b_id=b) else: ret['status'] = False ret['error'] = "太短了" except Exception as e: ret['status'] = False ret['error'] = '请求错误' return HttpResponse(json.dumps(ret))
除了$.ajax
,还有$.get
、$.post
、$.getJson
等等,这些方法内部都是调用$.ajax
。
$.get
本质上就是type写成get。$.get(url="xxx", data={}, success……)
e、编辑一对多示例
删除数据的话,可以后台删除数据并且页面直接remove掉相应的显示内容,这样页面就不用刷新了。
修改下面主要是获取select下拉框的值做获取修改
三、Django ORM 外键操作 多对多
假设目前有两张表,主机表和应用表,
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()class Application(models.Model): name = models.CharField(max_length=32)
一个主机可以对应多个应用、一个应用也可对应多个主机。多个一对多,即多对多
1、创建多对多
- 方式一:自定义关系表
创建第三张关系表。
class HostToApp(models.Model): hobj = models.ForeignKey(to='Host',to_field='nid') aobj = models.ForeignKey(to='Application',to_field='id')
- 方式二:自动创建关系表
表中添加 ManyToManyField
class Application(models.Model): name = models.CharField(max_length=32) r = models.ManyToManyField("Host")
这样第三张表Django就帮我们创建了。这里表名为 app01_application_r
,这里写了两个类生成三张表。
总结:一般用哪种方式?
自动创建关系表,表中只能创建三列数据。想增加额外的列做不到。对于自定义的,自定制功能更好些。
2、多对多关系表中添加数据
- 方式一:自定义关系表
这种添加数据比较简单,就是表中添加数据那样。典型的 使用类操作
models.User.objects.create(hobj_id=1,aobj_id=2)
- 方式二:自动创建的关系表
上面是使用类操作数据库,但是这里自动创建的关系表,没有类,就不能通过类直接操作数据库。
所以只能通过里面定义的r进行间接操作。
和之前操作一样,获取到r:
obj = models.Application.objects.get(id=1) # 获取id为1的application对象obj.name # 应用名obj.r # 获取到 r
获取到r,里面有哪些功能呢?
obj = models.Application.objects.get(id=1) # 增加数据obj.r.add(1) # 添加application id为1,host id也是1obj.r.add(2) # 添加application id为1,host id也是2obj.r.add(2,3,4) # 增加多条关系1 2,1 3 ,1 4obj.r.add(*[1,2,3,4]) # 增加列表,增加多条关系1 1 ,1 2,1 3 ,1 4# 删除数据obj.r.remove(1) # 删除 1 1 记录obj.r.remove(2,4) # 删除 1 2,1 4 记录obj.r.remove(*[1,2,3]) # 通过列表删除obj.r.clear() # 删除application id为1的所以数据# 更新、修改数据(注意这里列表不加*)obj.r.set([3,5,7]) # 只存在1 3,1 5,1 7。application id=1的其他都没有了# 查询数据obj.r.all() # 所有application id=1的主机对象 “列表”QuerySet类型
3、多对多数据增加示例
views.py
def app(request): if request.method == "GET": app_list = models.Application.objects.all() host_list = models.Host.objects.all() return render(request,'app.html',{ "app_list": app_list,'host_list': host_list}) elif request.method == "POST": app_name = request.POST.get('app_name') host_list = request.POST.getlist('host_list') print(app_name,host_list) # 创建完之后会返回一个对象。对象就是你增加的这条数据的对象。 obj = models.Application.objects.create(name=app_name) obj.r.add(*host_list) return redirect('/app')def ajax_add_app(request): ret = { 'status':True, 'error':None, 'data': None} app_name = request.POST.get('app_name') host_list = request.POST.getlist('host_list') obj = models.Application.objects.create(name=app_name) obj.r.add(*host_list) return HttpResponse(json.dumps(ret))
urls.py
url(r'^app$', views.app),url(r'^ajax_add_app$', views.ajax_add_app),
app.html
下拉框select,默认val获取单值,如果设了multiple,获取的就是列表。
转载请务必保留此出处:
<!-- END -->
《版权说明》: 本文转自-- http://blog.csdn.net/fgf00/article/details/53812643