基础1部分的笔记(Django基本操作)
上节回顾: - 登录注册验证 默认事件先执行: checkbox 自定义先执行 a submit ... <form> <input type='type' /> <input type='password' /> <input type='submit' /> </form> $(':submit').click(function(){ $(':text,:password').each(function(){ ... return false; }) return false; }) input,checbox ================================== 验证 ================================ JS: 验证 各种验证 $(':submit').click(function(){ $(':text,:password').each(function(){ ... return false; }) return false; }) 后端:python实现 业务处理 .... 3种组件 ========》 适合全站,但功能少 BootStrap - css:v3.bootcss.com/css - js 学习 BootStrap 规则 一、响应式 @media 二、图标、字体 @font-face 三、基本使用 js:依赖于jQuery css: !important; 四、模板:http://www.niftyadmin.cn/index.html 原价56,现价39 https://item.taobao.com/item.htm?id=575025805791 ========》 仅适合后台管理 jQueryUI * - css - js 学习 jQueryUI 规则 EasyUI - css - js 学习 jQueryUI 规则 ============ Ajax操作 ================ 附件:https://bxslider.com/ 插件轮播 WEB框架 MVC Model View Controller 数据库 模板文件 业务处理 MTV Model Template View 数据库 模板文件 业务处理 ############## WEB:MVC、MTV Django # 安装 (必须python3) pip3 install django或者用pycharm创建 # 配置环境变量 C:\Python35\Scripts 如果没有配置环境变量,只能在python3的安装目录Scripts下创建工程 django-admin.exe startproject 【工程名称】 如果配置了环境变量,可以在自己目录下创建工程 django-admin startproject 【工程名称】 # 创建Django工程(在pycharm根目录下创建,可避免from import飘红) django-admin startproject 【工程名称】 mysite - mysite # 对整个程序进行配置 - init # python3中可有可无,python2中导入模块需要__init__文件(包) - settings # 配置文件 - url # URL与函数(类)对应关系 - wsgi # 遵循WSIG规范(封装socketserver),uwsgi + nginx==>上线 支持的wsgi接口都要哪些? 'cgi': CGIServer, 'flup': FlupFCGIServer, 'wsgiref': WSGIRefServer, 'waitress': WaitressServer, 'cherrypy': CherryPyServer, 'paste': PasteServer, 'fapws3': FapwsServer, 'tornado': TornadoServer, 'gae': AppEngineServer, 'twisted': TwistedServer, 'diesel': DieselServer, 'meinheld': MeinheldServer, 'gunicorn': GunicornServer, 'eventlet': EventletServer, 'gevent': GeventServer, 'geventSocketIO':GeventSocketIOServer, 'rocket': RocketServer, 'bjoern' : BjoernServer, 'auto': AutoServer, - manage.py # 管理Django程序: - python manage.py - python manage.py startapp xx 创建app - python manage.py makemigrations 创建数据库 orm:关系对象映射 - python manage.py migrate 类自动生成数据表 # 运行Django功能(进入工程目录) python manage.py runserver 127.0.0.1:8001 未加环境变量:C:\Python35\python.exe manage.py runserver 127.0.0.1:8001 chouti - chouti - 配置 - 主站 app - 后台管理 app # 创建app python manage.py startapp cmdb python manage.py startapp openstack python manage.py startapp xxoo.... app: migrations 数据修改表结构(插入数据、修改数据不记录) admin Django为我们提供的后台管理 (1)创建数据库类 (2)生成数据库表: python manage.py makemigrations python manage.py migrate (3)配置: admin.site.register(models.UerInfo(数据库创建的类)) admin.site.register(models.UerType(数据库创建的类)) (4)创建数据 python manage.py createsuperuser apps 配置当前app,添加到INSTALLED_APPS列表中 models ORM,写指定的类 通过命令可以创建数据库结构 tests 单元测试 views 业务代码 1、配置模板的路径 TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, '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', ], }, }, ] 2、配置静态目录 static STATICFILES_DIRS = ( os.path.join(BASE_DIR, 'static'), ==》 注意, ) <link rel="stylesheet" href="/static/commons.css" /> 3、app路径配置添加 INSTALLED_APPS = [] 内容整理 1. 创建Django工程 django-admin startproject 工程名 2. 创建APP cd 工程名 python manage.py startapp cmdb 3、静态文件 project.settings.py STATICFILES_DIRS = ( os.path.join(BASE_DIR, "static"), ) 4、模板路径 DIRS ==> [os.path.join(BASE_DIR,'templates'),] 5、settings中 middlerware # 注释 csrf 6、定义路由规则 url.py "login" --> 函数名 7、定义视图函数 app下views.py def func(request): # request.method GET / POST # http://127.0.0.1:8009/home?nid=123&name=alex # request.GET.get('',None) # 获取url请求发来的数据 # request.POST.get('',None) 返回数据:return 一定要用Django的函数 # return HttpResponse("字符串"或字节bytes) # return render(request, "HTML模板的路径") # return redirect('/只能填URL') / : 域名 Ctrl+S:修改业务代码时,自动保存重启服务 拓展:res=HttpResponse('Ok')--->res['name']='uson'这种方式会把name加入到响应头信息中 8、模板渲染 特殊的模板语言 -- {{ 变量名 }} def func(request): return render(request, "index.html", {'current_user': "alex"}) index.html <html> .. <body> <div>{{current_user}}</div> </body> </html> ====> 最后生成的字符串 <html> .. <body> <div>alex</div> </body> </html> -- For循环 def func(request): return render(request, "index.html", {'current_user': "alex", 'user_list': ['alex','eric']}) index.html <html> .. <body> <div>{{current_user}}</div> <ul> {% for row in user_list %} {% if row == "alex" %} <li>{{ row }}</li> {% endif %} {% endfor %} </ul> </body> </html> #####索引################# def func(request): return render(request, "index.html", { 'current_user': "alex", 'user_list': ['alex','eric'], 'user_dict': {'k1': 'v1', 'k2': 'v2'}}) index.html <html> .. <body> <div>{{current_user}}</div> <a> {{ user_list.1 }} </a> <a> {{ user_dict.k1 }} </a> <a> {{ user_dict.k2 }} </a> </body> </html> ###### 条件 def func(request): return render(request, "index.html", { 'current_user': "alex", "age": 18, 'user_list': ['alex','eric'], 'user_dict': {'k1': 'v1', 'k2': 'v2'}}) index.html <html> .. <body> <div>{{current_user}}</div> <a> {{ user_list.1 }} </a> <a> {{ user_dict.k1 }} </a> <a> {{ user_dict.k2 }} </a> {% if age %} <a>有年龄</a> {% if age > 16 %} <a>老男人</a> {% else %} <a>小鲜肉</a> {% endif %} {% else %} <a>无年龄</a> {% endif %} </body> </html> XXOO管理: MySQL SQLAlchemy 主机管理(8列): IP 端口 业务线 ... 用户表: 用户名 密码 功能: 1、 登录 2、主机管理页面 - 查看所有的主机信息(4列) - 增加主机信息(8列) ** 模态对话框 3、查看详细 url: "detail" -> detail def detail(reqeust): nid = request.GET.get("nid") v = select * from tb where id = nid ... 4、删除 del_host -> delete_host def delete_host(request): nid = request.POST.get('nid') delete from tb where id = nid return redirect('/home') 上节内容回顾: 1、Django请求生命周期 -> URL对应关系(匹配) -> 视图函数 -> 返回用户字符串 -> URL对应关系(匹配) -> 视图函数 -> 打开一个HTML文件,读取内容 2、创建django projcet django-admin startproject mysite .. mysite mysite - 配置文件 - url.py - settings.py cd mysite python manage.py startapp cmdb mysite mysite - 配置文件 - url.py - settings.py cmdb - views.py - admin.py - models.py # 创建数据库表 3、配置 模板路径 静态文件路径 # CSRF 4、编写程序 a. url.py /index/ -> func b. views.py def func(request): # 包含所有的请求数据 ... return HttpResponse('字符串') return render(request, 'index.html', {''}) retrun redirect('URL') c. 模板语言 return render(request, 'index.html', {'li': [11,22,33]}) {% for item in li %} <h1>{{item}}</h1> {% endfor %} *********** 索引用点 ********** <h2> {{item.0 }} </h2> 潜规则(一般规定): get:获取数据 post:提交数据 一、路由系统,URL 1、url(r'^index/', views.index), url(r'^home/', views.Home.as_view()), 2、url(r'^detail-(\d+).html', views.detail), 3、url(r'^detail-(?P<nid>\d+)-(?P<uid>\d+).html', views.detail) PS: def detail(request, *args,**kwargs): pass 实战: a. url(r'^detail-(\d+)-(\d+).html', views.detail), def func(request, nid, uid): pass def func(request, *args): args = (2,9) def func(request, *args, **kwargs): args = (2,9) b. url(r'^detail-(?P<nid>\d+)-(?P<uid>\d+).html', views.detail) def func(request, nid, uid): pass def funct(request, **kwargs): kwargs = {'nid': 1, 'uid': 3} def func(request, *args, **kwargs): kwargs = {'nid': 1, 'uid': 3} 4、 name 对URL路由关系进行命名, ***** 以后可以根据此名称生成自己想要的URL ***** url(r'^asdfasdfasdf/', views.index, name='i1'), url(r'^yug/(\d+)/(\d+)/', views.index, name='i2'), url(r'^buy/(?P<pid>\d+)/(?P<nid>\d+)/', views.index, name='i3'), def func(request, *args, **kwargs): from django.urls import reverse url1 = reverse('i1') # asdfasdfasdf/ url2 = reverse('i2', args=(1,2,)) # yug/1/2/ url3 = reverse('i3', kwargs={'pid': 1, "nid": 9}) # buy/1/9/ xxx.html {% url "i1" %} # asdfasdfasdf/ {% url "i2" 1 2 %} # yug/1/2/ {% url "i3" pid=1 nid=9 %} # buy/1/9/ 注: # 当前的URL request.path_info 5、多级路由 project/urls.py from django.conf.urls import url,include from django.contrib import admin urlpatterns = [ url(r'^cmdb/', include("app01.urls")), url(r'^monitor/', include("app02.urls")), ] app01/urls.py from django.conf.urls import url,include from django.contrib import admin from app01 import views urlpatterns = [ url(r'^login/', views.login), ] app02/urls.py from django.conf.urls import url,include from django.contrib import admin from app02 import views urlpatterns = [ url(r'^login/', views.login), ] 6、默认值(欠) 7、命名空间(欠) 二、视图 1、获取用户请求数据 request.GET request.POST request.FILES PS: GET:获取数据 POST:提交数据 2、checkbox等多选的内容 request.POST.getlist() 3、上传文件 # 上传文件,form标签做特殊设置 obj = request.FILES.get('fafafa') obj.name f = open(obj.name, mode='wb') for item in obj.chunks(): 迭代器 f.write(item) f.close() 4、FBV & CBV function base view url.py index -> 函数名 view.py def 函数(request): ... ====》 /index/ -> 函数名 /index/ -> 类 ====》 建议:两者都用 5、装饰器 欠 三、模板 四、ORM操作 select * from tb where id > 1 # 对应关系 models.tb.objects.filter(id__gt=1) models.tb.objects.filter(id=1) models.tb.objects.filter(id__lt=1) 创建类 a. 先写类 from django.db import models # app01_userinfo class UserInfo(models.Model): # id列,自增,主键 # 用户名列,字符串类型,指定长度 username = models.CharField(max_length=32) password = models.CharField(max_length=64) b. 注册APP INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01', ] c. 执行命令 python manage.py makemigrations python manage.py migrate d. ********** 注意 *********** Django默认使用MySQLdb模块链接MySQL 主动修改为pymysql,在project同名文件夹下的__init__文件中添加如下代码即可: import pymysql pymysql.install_as_MySQLdb() 1. 根据类自动创建数据库表 # app下的models.py python manage.py makemigrations python manage.py migrate 字段: 字符串类型 数字 时间 二进制 自增(primary_key=True) 字段的参数: null -> db是否可以为空 default -> 默认值 primary_key -> 主键 db_column -> 列名 db_index -> 索引 unique -> 唯一索引 unique_for_date -> unique_for_month unique_for_year auto_now -> 更新时,自动更新为当前时间 auto_now_add -> 创建时,自动生成时间 # obj = UserGroup.objects.filter(id=1).update(caption='CEO') 更新的时间不生效 # obj = UserGroup.objects.filter(id=1).first() 生效 # obj.caption = "CEO" # obj.save() choices -> django admin中显示下拉框,避免连表查询 blank -> django admin是否可以为空 verbose_name -> django admin显示字段中文 editable -> django admin是否可以被编辑 error_messages -> 错误信息 (欠) help_text -> django admin提示 validators -> django form ,自定义错误信息(欠) 创建 Django 用户:python manage.py createsuperuser 2. 根据类对数据库表中的数据进行各种操作 一对多: a. 外检 b. 外键字段_id c. models.tb.object.create(name='root', user_group_id=1) d. userlist = models.tb.object.all() for row in userlist: row.id row.user_group_id row.user_group.caption =================== 作业:用户管理 ==================== 1、用户组的增删改查 2、用户增删该查 - 添加必须是对话框 - 删除必须是对话框 - 修改,必须显示默认值 3、比较好看的页面 4、预习: http://www.cnblogs.com/wupeiqi/articles/5246483.html
课堂那些Low示例:
一级urls:
from django.contrib import admin from django.urls import path, re_path, include from cmdb import views from django.conf.urls import url # 一级路由 urlpatterns = [ # 给每个app再创建一个urls文件 # 测试访问地址:http://127.0.0.1:8008/cmdb/login # 测试访问地址:http://127.0.0.1:8008/monitor/login path('cmdb/', include('cmdb.urls')), #cmdb:为一级目录 cmdb:为创建的app path('monitor/', include('app02.urls')), #monitor:为一级目录 app02:为创建的app ############################jsonp跨域发请求服务端示例########################## path('uson/', include('jsonp.urls')), ]
二级urls:
from django.contrib import admin from django.urls import path, re_path from cmdb import views from django.conf.urls import url # 二级路由 urlpatterns = [ path(r'login', views.login), # r: 防止转义,以login开头 path(r'login2', views.login2), # r: 防止转义,以login开头 path(r'orm', views.orm), path(r'index2', views.index2), path(r'user_list2/', views.user_list2), re_path(r'userdetail-(?P<nid>\d+)/', views.userdetail2), #正则表达式:re_path re_path(r'userdel-(?P<nid>\d+)/', views.userdel2), #对应的url可以不写html,但需要一个函数处理 re_path(r'useredit-(?P<nid>\d+)/', views.useredit2), path(r'orm2', views.orm2), ]
views:
from django.shortcuts import HttpResponse # 免去open,close的所有文件操作 from django.shortcuts import render from django.shortcuts import redirect
登录
1 def login(request): 2 # request:包含用户提交的所有信息 3 # 获取用户提交的方法 4 # print(request.method) 5 6 # return render(request, 'login.html') #request参数必须带上 7 # settings文件里设置了自动去templates目录下找 8 9 msg_error = '' 10 if request.method == 'POST': 11 # 获取用户名 12 username = request.POST['user'] #name='user' 13 # 获取密码 14 pwd = request.POST['pwd'] #name = 'pwd' 15 16 if username == 'uson' and pwd == 'akaedu': 17 # return redirect('https://www.baidu.com') 18 return redirect('/index') 19 else: 20 msg_error = '用户名或密码错误' 21 22 return render(request, 'login.html', {"msg_error": msg_error}) 23 # 特殊字符:html中,{{ }} ,匹配msg_error 24 # kao, 很大问题:浏览器不清楚缓存,django总是无错报错
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>登录界面</title> 6 <link rel="stylesheet" href="/static/commons.css" /> 7 <style> 8 label{ 9 width: 80px; 10 display: inline-block; 11 text-align: right; 12 } 13 .lButton{ 14 margin-left: 82px; 15 } 16 </style> 17 </head> 18 <body> 19 <div class="login"> 20 {# <form action="/login/" method="post">#} <!--path('login/', views.login),--> 21 <form action="/login" method="post"> <!--path('login', views.login),--> 22 <p> 23 <label for="username" >用户名:</label> <!-- 行内标签 --> 24 <input id="username" name="user" type="text" /> <!-- 行内标签 --> 25 </p> 26 <p> 27 <label for="pwd" >密 码:</label> 28 <input id="pwd" name="pwd" type="password" /> 29 </p> 30 <div class="lButton"> 31 <input type="submit" value="立即登录" /> 32 <span style="color: red;">{{ msg_error }}</span> 33 </div> 34 </form> 35 </div> 36 37 <script src="/static/jquery.min.js"></script> 38 </body> 39 </html>
1 INFO_L = [] 2 # 必须是全局变量,每次追加才能保存数据 3 # 否则,每次只能追加一行 4 info_list = [ 5 {'name': 'alex', 'email': 'alex3714@126.com', 'gender': '男'}, 6 {'name': 'uson', 'email': 'uson@126.com', 'gender': '男'}, 7 {'name': 'cohui', 'email': 'cohui@126.com', 'gender': '女'}, 8 ] 9 10 def index(request): 11 # for i in range(20): 12 # temp = {'name': 'alex' + str(i), 'email': 'alex3714@126.com', 'gender': '男'} 13 # INFO_L.append(temp) 14 15 if request.method == "POST": 16 # 获取POST请求中用户提交的数据 17 u = request.POST.get('user', None) 18 e = request.POST.get('email', None) 19 g = request.POST.get('gender', None) 20 temp = {'name': u, 'email': e, 'gender': g} 21 info_list.append(temp) 22 23 # return render(request, 'index.html', {'info_list': info_list, 'info_l': INFO_L}) 24 return render(request, 'index.html', {'info_list': info_list})
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>主页界面</title> 6 <link rel="stylesheet" href="/static/commons.css" /> 7 <style> 8 .lButton{ 9 padding: 0 0 10px 0; 10 } 11 </style> 12 </head> 13 <body> 14 <div class="login"> 15 <form action="/index" method="post"> 16 <p> 17 <input id="username" name="user" type="text" placeholder="用户名" /> 18 </p> 19 <p> 20 <input id="email" name="email" type="text" placeholder="邮箱" /> 21 </p> 22 <p> 23 <input id="gender" name="gender" type="text" placeholder="性别" /> 24 </p> 25 <div class="lButton"> 26 <input type="submit" value="立即添加" /> 27 </div> 28 </form> 29 {# 模板语言for循环 #} 30 <table border="1"> 31 {% for row in info_list %} 32 <tr> 33 <td>{{ row.name }}</td> 34 <td>{{ row.email }}</td> 35 <td>{{ row.gender }}</td> 36 </tr> 37 {% endfor %} 38 {# {% for r in info_l %}#} 39 {# <tr>#} 40 {# <td>{{ r.name }}</td>#} 41 {# <td>{{ r.email }}</td>#} 42 {# <td>{{ r.gender }}</td>#} 43 {# </tr>#} 44 {# {% endfor %}#} 45 </table> 46 </div> 47 <script src="/static/jquery.min.js"></script> 48 </body> 49 </html>
多选、上传文件
1 # 下拉框,多选,上传文件 2 def reg(request): 3 if request.method == "POST": 4 # value = request.POST.get('gender', None) #单选,单值 5 # value = request.POST.getlist('skill', None) #多选,多值 6 obj = request.FILES.get('filename') #文件 7 print(obj, type(obj), obj.name) 8 # 2019年暑假衔接课课表及名单.pdf 9 # <class 'django.core.files.uploadedfile.InMemoryUploadedFile'> 10 from django.core.files.uploadedfile import InMemoryUploadedFile 11 # def chunks(self, chunk_size=None): 12 # def open(self, mode=None): 13 # def __str__ ===> return返回的是obj.name = 即实例化后传给了obj对象,所以obj=文件名; 14 # 另外:__str__优先于__repr__ 15 import os 16 # 文件上传路径 17 filepath = os.path.join('upload', obj.name) 18 # 打开文件 19 f = open(filepath, mode='wb') 20 #一点一点上传内容,只要有yield,此时,chunks()是一个迭代器,内存中还不存在,next时才存在 21 for item in obj.chunks(): 22 f.write(item) 23 f.close() 24 25 return render(request, 'reg.html')
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <form action="/reg" method="post" enctype="multipart/form-data"> 9 <div> 10 男:<input type="radio" name="gender" value="1" /> 11 女:<input type="radio" name="gender" value="2" /> 12 </div> 13 <div> 14 python开发:<input type="checkbox" name="skill" value="11" /> 15 C开发:<input type="checkbox" name="skill" value="22" /> 16 Java开发:<input type="checkbox" name="skill" value="33" /> 17 </div> 18 <div> 19 <input type="file" name="filename" value="66" /> 20 </div> 21 <input type="submit" value="提交" /> 22 </form> 23 </body> 24 </html>
类
1 from django.views import View 2 class Home(View): 3 # http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'] 4 # 自定义功能 5 def dispatch(self, request, *args, **kwargs): 6 print('before') 7 8 # 继承父类的功能 9 # 父类的dispatch(super...)去判断执行get还是post 10 result = super(Home, self).dispatch(request, *args, **kwargs) 11 12 print('after') 13 # get/post返回结果会给super, super(即dispatch)再把结果返回给用户 14 return result 15 16 # get和post执行之前,都会先执行dispatch方法 17 def get(self, request): 18 print('Get') 19 return render(request, 'home.html') # 实际是返回给dispatch 20 def post(self, request): 21 print('POST') 22 return render(request, 'home.html') # 实际是返回给dispatch
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <form action="/home/" method="post" enctype="multipart/form-data"> 9 <div> 10 男:<input type="radio" name="gender" value="1" /> 11 女:<input type="radio" name="gender" value="2" /> 12 </div> 13 <div> 14 python开发:<input type="checkbox" name="skill" value="11" /> 15 C开发:<input type="checkbox" name="skill" value="22" /> 16 Java开发:<input type="checkbox" name="skill" value="33" /> 17 </div> 18 <div> 19 <input type="file" name="filename" value="66" /> 20 </div> 21 <input type="submit" value="提交" /> 22 </form> 23 </body> 24 </html>
html模板字典的循环
1 list_dict = { 2 'k1': 'root1', 3 'k2': 'root2', 4 'k3': 'root3', 5 'k4': 'root4', 6 'k5': 'root5', 7 'k6': 'root6', 8 } 9 LIST_DICT_M = { 10 '0': {'name': 'uson', 'email': 'uson@126.com'}, 11 '1': {'name': 'cohui', 'email': 'cohui@126.com'}, 12 '2': {'name': 'fang', 'email': 'fang@126.com'}, 13 '3': {'name': 'zhou', 'email': 'zhou@126.com'}, 14 '4': {'name': 'han', 'email': 'han@126.com'}, 15 '5': {'name': 'wei', 'email': 'wei@126.com'}, 16 } 17 def dict(request): 18 return render(request, 'dict.html', {'list_dict': list_dict, 'LIST_DICT_M': LIST_DICT_M})
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 {{ list_dict.k1 }} {# 取值:value #} 9 <ul> 10 {% for foo in list_dict %} {# 字典: list_dict = {k1:root} #} 11 <li>{{ foo }}</li> {# foo = k1... #} 12 {% endfor %} 13 <p>##############</p> 14 {% for foo in list_dict.keys %} {# 默认就是keys #} 15 <li>{{ foo }}</li> {# foo = k1... #} 16 {% endfor %} 17 <p>**************</p> 18 {% for foo in list_dict.values %} {# 默认就是keys #} 19 <li>{{ foo }}</li> {# foo = root1... #} 20 {% endfor %} 21 <p>¥¥¥¥¥¥¥¥¥</p> 22 {% for foo in list_dict.items %} {# key, value #} 23 <li>{{ foo }}</li> {# foo = ('k6', 'root6')... #} 24 {% endfor %} 25 <p>$$$$$$$$$$$$$</p> 26 {% for k, foo in list_dict.items %} {# key, value #} 27 <li>{{ k }} ¥ {{ foo }}</li> {# foo = k6 ¥ root6... #} 28 {% endfor %} 29 <p style="color: red;">查看详情内容示例-1(动态)</p> 30 <p style="color: red;">&&&&&&&&&&&&&&</p> 31 {# 字典:LIST_DICT_M = { 0: {name:uson, email: uson@126.com} ...} #} 32 {% for k, info in LIST_DICT_M.items %} 33 <li><a target="_blank" href="/details?nid={{ k }}">{{ info.name }}</a></li> {# k = 0... #} 34 {% endfor %} 35 <p style="color: red;">url正则匹配,查看详情内容示例-2(静态)</p> 36 <p style="color: red;">$$$$$$$$$$$$$$$$$</p> 37 {% for k, info in LIST_DICT_M.items %} 38 <li><a target="_blank" href="/details-{{ k }}.html">{{ info.name }}</a></li> {# k = 0... #} 39 {% endfor %} 40 </ul> 41 </body> 42 </html>
路由命名
1 def rename(request, *args, **kwargs): 2 v = request.path_info 3 print(v) #/renamessdsfsd-2-8/ 4 return render(request, 'rename.html', {'request.path_info': v})
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <form action="{% url 'det' nid=1 uid=2 %}" method="post" enctype="multipart/form-data"> 9 <div> 10 男:<input type="radio" name="gender" value="1" /> 11 女:<input type="radio" name="gender" value="2" /> 12 </div> 13 <div> 14 python开发:<input type="checkbox" name="skill" value="11" /> 15 C开发:<input type="checkbox" name="skill" value="22" /> 16 Java开发:<input type="checkbox" name="skill" value="33" /> 17 </div> 18 <div> 19 <input type="file" name="filename" value="66" /> 20 </div> 21 <input type="submit" value="提交" /> 22 </form> 23 </body> 24 </html>
models:
1 from django.db import models 2 3 # Create your models here. 4 5 from django.db import models 6 7 # 创建用户组 8 class UserGroup(models.Model): 9 uid = models.AutoField(primary_key=True) 10 caption = models.CharField(max_length=32) 11 12 # 创建用户 13 class Userinfo(models.Model): #必须继承django的父类 14 # 默认隐藏了id列,自增,且为主键 15 name = models.CharField(max_length=32) 16 password = models.CharField(max_length=64) 17 18 # user_group = models.ForeignKey('UserGroup', to_field='uid', default=1, on_delete=1) # to_field默认是主键 19 user_group = models.ForeignKey('UserGroup', to_field='uid', on_delete=1) # to_field默认是主键 20 # user_group 自动生成为user_group_id 21 22 # email = models.EmailField() 23 # memo = models.TextField() 24 user_type_choice = ( 25 (1, '黄金用户'), 26 (2, '钻石用户'), 27 (3, '普通用户'), 28 ) 29 user_type_id = models.IntegerField(choices=user_type_choice, default=3) 30 # 添加APP 31 # python manage.py makemigrations 32 # python manage.py migrate 33 # 表名: cmdb_userinfo 34 35 # 使用navicat premium软件查看 36 # 数据库文件: D:/python/cohui/WebSiteOne/db.sqlite3 37 # 连接名:WebSiteOne 38 # 双击表名打开查看
orm基本操作
1 # 数据库创建数据 2 from cmdb import models #指定数据库文件名 3 def orm(request): 4 # 创建 5 # 方法1 6 # models.Userinfo.objects.create(name='uson', password='123') 7 # 方法2 8 # dict = {'name': 'cohui', 'password': '345'} 9 # models.Userinfo.objects.create(**dict) 10 # 方法3 11 # obj = models.Userinfo(name='Uson', password='123') 12 # obj.save() 13 # return HttpResponse('orm') 14 15 # 查 16 result = models.Userinfo.objects.all() # 1) 列表 17 result = models.Userinfo.objects.filter(name='uson') # 2) 列表 18 # result = models.Userinfo.objects.filter(name='uson').first() # 3) 对象(单条数据) 19 # result = models.Userinfo.objects.get(name='uson') # 4) 对象(单条数据) 不存在,报错,try 20 # print(result) 21 # print(result.query) #可以查看该句的SQL语句:SELECT ... 22 # <QuerySet [<Userinfo: Userinfo object (1)>, 23 # [<Userinfo: Userinfo object (2)>, <Userinfo: Userinfo object (3)>] 24 # result: QuerySet类型 --》 Django --> [obj, ...],列表里是一个一个的对象 25 for row in result: 26 print(row.id, row.name, row.password) 27 # return HttpResponse('orm') 28 29 # 删 30 # models.Userinfo.objects.all().delete() 31 # models.Userinfo.objects.filter(password=123).delete() 32 # return HttpResponse('orm') 33 34 # 改、更新 35 # models.Userinfo.objects.update(password='666') 36 # models.Userinfo.objects.filter(name='uson').update(name='Cohui') 37 return HttpResponse('orm')
orm-登录验证
1 # 登录验证(数据库) 示例 2 def login2(request): 3 msg_error = '' 4 if request.method == 'POST': 5 username = request.POST['user'] 6 pwd = request.POST['pwd'] 7 # if username == 'uson' and pwd == 'akaedu': 8 #通过数据库验证 9 obj = models.Userinfo.objects.filter(name=username, password=pwd).first() # 3) 对象(单条数据) 10 # result = models.Userinfo.objects.get(name='uson') # 4) 对象(单条数据) 不存在,报错,try 11 if obj: 12 return redirect('/cmdb/index2') 13 else: 14 msg_error = '用户名或密码错误' 15 return render(request, 'login2.html', {"msg_error": msg_error})
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>登录界面-2</title> 6 <link rel="stylesheet" href="/static/commons.css" /> 7 <style> 8 label{ 9 width: 80px; 10 display: inline-block; 11 text-align: right; 12 } 13 .lButton{ 14 margin-left: 82px; 15 } 16 </style> 17 </head> 18 <body> 19 <div class="login"> 20 <form action="/cmdb/login2" method="post"> 21 <p> 22 <label for="username" >用户名:</label> 23 <input id="username" name="user" type="text" /> 24 </p> 25 <p> 26 <label for="pwd" >密 码:</label> 27 <input id="pwd" name="pwd" type="password" /> 28 </p> 29 <div class="lButton"> 30 <input type="submit" value="立即登录" /> 31 <span style="color: red;">{{ msg_error }}</span> 32 </div> 33 </form> 34 </div> 35 <script src="/static/jquery.min.js"></script> 36 </body> 37 </html>
orm-用户列表
1 def user_list2(request): 2 if request.method == "GET": 3 user_list_obj = models.Userinfo.objects.all() #[obj, obj, ...] 4 group_list_obj = models.UserGroup.objects.all() 5 return render(request, 'user_list2.html', {'user_list_obj': user_list_obj, 'group_list_obj': group_list_obj}) 6 elif request.method == "POST": 7 # 1)增加、查找 -示例 8 u = request.POST.get('username') 9 p = request.POST.get('password') 10 # 写到数据库 11 models.Userinfo.objects.create(name=u, password=p) 12 # 从数据库中,查找数据,显示到网页 13 obj = models.Userinfo.objects.all() 14 return render(request, 'user_list2.html', {'user_list_obj': obj})
1 <!DOCTYPE html> 2 <html lang="en"> 3 4 <!--第一种布局方式: 5 fixed + overflow 6 --> 7 <head> 8 <meta charset="UTF-8"> 9 <title>Title</title> 10 <style> 11 body{ 12 margin: 0; 13 } 14 .pg-header{ 15 background-color: #a6e1ec; 16 height: 48px; 17 line-height: 48px; 18 } 19 .pg-body{ 20 /*height: 6000px;*/ 21 /*background-color: #d5d5d5;*/ 22 margin-top: 48px; 23 } 24 .pg-body .Lmenu{ 25 background-color: #d5d5d5; 26 width: 200px; 27 28 /*第一种布局方式*/ 29 position: fixed; 30 left: 0; 31 bottom: 0; 32 top: 48px; 33 overflow: auto; 34 35 /*width: 20%;*/ 36 /*min-width: 200px;*/ 37 } 38 39 .pg-body .Lmenu .userlist{ 40 } 41 .pg-body .Rcontent{ 42 background-color: #E6E6FA; 43 /*width: 80%;*/ 44 45 position: fixed; 46 right: 0; 47 top: 48px; 48 bottom: 0; 49 left: 200px; 50 overflow: auto; 51 } 52 .pg-body .Rcontent .content{ 53 background-color: #E6E6FA; 54 } 55 .pg-footer{ 56 } 57 </style> 58 </head> 59 <body> 60 <div class="pg-header"></div> 61 <div class="pg-body"> 62 <!--左--> 63 <div class="Lmenu"> 64 <div class="userlist"><a href="/cmdb/user_list2/">用户列表</a></div> 65 <div class="userlist">用户管理</div> 66 </div> 67 <!--右--> 68 <div class="Rcontent"> 69 <div class="content"> 70 <div> 71 <form action="/cmdb/user_list2/" method="post"> 72 <input type="text" name="username" /> 73 <input type="password" name="password" /> 74 <select name="usergroup"> 75 {% for foo in group_list_obj %} 76 <option value="{{ foo.uid }}">{{ foo.caption }}</option> 77 {% endfor %} 78 79 </select> 80 <input type="submit" value="添加" /> 81 </form> 82 </div> 83 <h1>用户列表</h1> 84 <ul> 85 {% for user in user_list_obj %} 86 <li> 87 <a href="userdetail-{{ user.id }}/">{{ user.name }}</a> | 88 <span>{{ user.user_group.caption }}</span> | 89 <a href="userdel-{{ user.id }}">删除</a> | 90 <a href="useredit-{{ user.id }}/">编辑</a> <!-- 在另一页面做修改 --> 91 </li> 92 {# <li>{{ user.name }}</li>#} 93 {% endfor %} 94 </ul> 95 </div> 96 </div> 97 </div> 98 <div class="pg-footer"></div> 99 </body> 100 </html>
orm-用户详细
1 def userdetail2(request, nid): 2 obj = models.Userinfo.objects.filter(id=nid).first() #obj 3 return render(request, 'userdetail2.html', {'obj': obj})
1 <!DOCTYPE html> 2 <html lang="en"> 3 4 <!--第一种布局方式: 5 fixed + overflow 6 --> 7 <head> 8 <meta charset="UTF-8"> 9 <title>Title</title> 10 <style> 11 body{ 12 margin: 0; 13 } 14 .pg-header{ 15 background-color: #a6e1ec; 16 height: 48px; 17 line-height: 48px; 18 } 19 .pg-body{ 20 /*height: 6000px;*/ 21 /*background-color: #d5d5d5;*/ 22 margin-top: 48px; 23 } 24 .pg-body .Lmenu{ 25 background-color: #d5d5d5; 26 width: 200px; 27 28 /*第一种布局方式*/ 29 position: fixed; 30 left: 0; 31 bottom: 0; 32 top: 48px; 33 overflow: auto; 34 35 /*width: 20%;*/ 36 /*min-width: 200px;*/ 37 } 38 39 .pg-body .Lmenu .userlist{ 40 } 41 .pg-body .Rcontent{ 42 background-color: #E6E6FA; 43 /*width: 80%;*/ 44 45 position: fixed; 46 right: 0; 47 top: 48px; 48 bottom: 0; 49 left: 200px; 50 overflow: auto; 51 } 52 .pg-body .Rcontent .content{ 53 background-color: #E6E6FA; 54 } 55 .pg-footer{ 56 } 57 </style> 58 </head> 59 <body> 60 <div class="pg-header"></div> 61 <div class="pg-body"> 62 <!--左--> 63 <div class="Lmenu"> 64 <div class="userlist"><a href="/cmdb/user_list2/">用户列表</a></div> 65 <div class="userlist">用户管理</div> 66 </div> 67 <!--右--> 68 <div class="Rcontent"> 69 <div class="content"> 70 <h1>用户详细信息</h1> 71 <ul> 72 <li>{{ obj.id }}</li> 73 <li>{{ obj.name }}</li> 74 <li>{{ obj.password }}</li> 75 </ul> 76 </div> 77 </div> 78 </div> 79 <div class="pg-footer"></div> 80 </body> 81 </html>
orm-删除
1 def userdel2(request, nid): 2 # 2)删除 示例 3 models.Userinfo.objects.filter(id=nid).delete() 4 return redirect('/cmdb/user_list2/')
orm-编辑
1 def useredit2(request, nid): 2 # 3) 编辑 3 if request.method == "GET": 4 obj = models.Userinfo.objects.filter(id=nid).first() 5 return render(request, 'user_edit2.html', {'obj': obj}) 6 elif request.method == 'POST': 7 u = request.POST.get('name') 8 p = request.POST.get('password') 9 models.Userinfo.objects.filter(id=nid).update(name=u, password=p) 10 return redirect('/cmdb/user_list2') #跳转到列表页,而不是html页(编辑替换特殊字符页)
1 前面都一样,部分html代码 2 <!--右--> 3 <div class="Rcontent"> 4 <div class="content"> 5 <div> 6 <form action="/cmdb/useredit-{{ obj.id }}/" method="post"> <!--仅名字与url保持一致--> 7 {# <input style="dispaly: none" type="text" name="id" value="{{ obj.id }}"/>#} 8 <input type="text" name="name" value="{{ obj.name }}" /> 9 <input type="text" name="password" value="{{ obj.password }}" /> 10 <input type="submit" value="提交" /> 11 </form> 12 </div> 13 </div> 14 </div>
orm-创建数据
1 # 给用户组创建数据 2 def orm2(request): 3 models.UserGroup.objects.create(caption='CEO') 4 return redirect('/cmdb/index2')
JsonP示例:
# 二级路由 urlpatterns = [ path(r'jsonp', views.jsonp), ]
1 from django.shortcuts import render, HttpResponse, redirect 2 3 # Create your views here. 4 def jsonp(request): 5 print(request.GET) # <QueryDict: {'key': ['uson'], 'pwd': ['akaedu']}> 6 7 # return HttpResponse('OK') # 返回数据中js无法解析OK字符串 8 # return HttpResponse('alert("12345")') 9 10 func = request.GET.get('call') # 获取javascript的src链接,即js中会以此名作为函数解析 11 # content = func('uson学Python') # X 12 content = "%s('uson学Python')" %(func,) # 传字符串 13 14 return HttpResponse(content) # 返回到javascript标签内,根据函数名会自动进行解析
1 ALLOWED_HOSTS = [ 2 'uson.com', 3 ]
配置文件路径:
C:\Windows\System32\drivers\etc\hosts
基础2部分的笔记(ORM ajax基础)
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, ........getlist() request.path_info 文件对象 = reqeust.FILES.get() 文件对象.name 文件对象.size 文件对象.chunks() # <form 特殊的设置></form> 给用户返回数据: render(request, "模板的文件的路径", {'k1': [1,2,3,4],"k2": {'name': '张扬','age': 73}}) redirect("URL") HttpResponse(字符串) 4、模板语言 render(request, "模板的文件的路径", {'obj': 1234, 'k1': [1,2,3,4],"k2": {'name': '张扬','age': 73}}) <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 %} {{ row }} {% endfor %} {% for row in k2.values %} {{ row }} {% endfor %} {% for k,v in k2.items %} {{ k }} - {{v}} {% endfor %} </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) obj = models.User(name='qianxiaohu',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) 查询也可以传字典 v1 = models.Business.objects.all() # QuerySet ,内部元素都是对象 取固定列数 # QuerySet ,内部元素都是字典 v2 = models.Business.objects.all().values('id','caption') # QuerySet ,内部元素都是元组(取值注意顺序) v3 = models.Business.objects.all().values_list('id','caption') # 获取到的一个对象,如果不存在就报错 models.Business.objects.get(id=1) 对象或者None = models.Business.objects.filter(id=1).first() 外键: v = models.Host.objects.filter(nid__gt=0) v[0].b.caption ----> 通过.进行跨表 values、values_list跨表操作(通过__): host_tuple = models.Host.objects.filter(nid__gt=0).values('nid', 'b__caption') for row in host_tuple: print(row[nid], row[b__caption]) host_tuple = models.Host.objects.filter(nid__gt=0).values_list('nid', 'b__caption') for row in host_tuple: print(row[0], row[1]) 外键: class UserType(models.Model): caption = models.CharField(max_length=32) id caption # 1,普通用户 # 2,VIP用户 # 3, 游客 class User(models.Model): age = models.IntergerFiled() name = models.CharField(max_length=10)#字符长度 # user_type_id = models.IntergerFiled() # 没有约束, user_type = models.ForeignKey("UserType",to_field='id') # 约束, name age user_type_id # 张扬 18 3 # 张A扬 18 2 # 张B扬 18 2 6、Ajax $.ajax({ url: '/host', type: "POST", data: {'k1': 123,'k2': "root"}, headers: {"": ...} success: function(data){ // data是服务器端返回的字符串 var obj = JSON.parse(data); } }) $.get(url='xx', data={}, function(){}, "json")、$.post() 本质上同$.ajax,只是改变一下type类型,但括号内不是传字典了 $.get('', function(){}) 这种方式不能传递headers信息 建议:永远让服务器端返回一个字典 return HttpResponse(json.dumps(字典)) 7、多对多: 创建多对多: 方式一:自定义关系表 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') # 10 class Application(models.Model): name = models.CharField(max_length=32) # 2 class HostToApp(models.Model): hobj = models.ForeignKey(to='Host',to_field='nid') aobj = models.ForeignKey(to='Application',to_field='id') # HostToApp.objects.create(hobj_id=1,aobj_id=2) 方式二:自动创建关系表(不能增加列,最多含id列,就是3列) 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') # 10 class Application(models.Model): name = models.CharField(max_length=32) r = models.ManyToManyField("Host") 主机对象“列表”,创建时,不是跟name一起创建,单独创建 无法直接对第三张表进行操作 # 第三张表操作(间接操作) obj = Application.objects.get(id=1) ===》.first() obj.name obj.r.add(1) (1,1) obj.r.add(2) (1,2) obj.r.add(2,3,4) (1,2)(1,3)(1,4) obj.r.add(*[1,2,3,4]) obj.r.remove(1) obj.r.remove(2,4) obj.r.remove(*[1,2,3]) obj.r.clear() 删除所有1的对应数据 obj.r.set([3,5,7]) 删除该id对应的所有关系,再添加set的关系id==》更新,保留 # 所有相关的主机对象“列表” QuerySet obj.r.all() ...
课堂那些Low示例:
urls:
# 二级路由 urlpatterns = [ # path(r'login', views.login), # r: 防止转义,以login开头 # (1)单表操作 # begins with a '^', or ends with a '$' url(r'^business$', views.business), #最好加上终止符$,否则永远都只匹配前面几个字母 # http://127.0.0.1:8008/monitor/business # (2)一对多表操作 url(r'^host$', views.host), # url(r'^testajax$', views.testajax), #Ajax示例 url(r'^testajax-(\w+)$', views.testajax), #Ajax示例 (ajax, add/edit) url(r'^host-del$', views.host_del), # (3)多对多表操作: Application 与 Host的关系表 url(r'^app$', views.app), url(r'^app-ajax$', views.app_ajax), #Ajax实现添加功能 url(r'^app-ajax-edit$', views.app_ajax_edit), #Ajax实现编辑功能 url(r'^app-ajax-del$', views.app_ajax_del), #Ajax实现删除功能 url(r'^app_newurl_edit-(\d+)$', views.app_newurl_edit), #新URL方式实现编辑功能 ]
models:
from django.db import models # Create your models here. class Business(models.Model): #id自增 caption = models.CharField(max_length=32) # 新增英文列 code = models.CharField(max_length=32, null=True) class Host(models.Model): nid = models.IntegerField(primary_key=True) #自增 hostname = models.CharField(max_length=32) #32个位字符,非字节 ip = models.GenericIPAddressField(protocol='both', db_index=True) #索引 port = models.IntegerField() # 单外键关联 b = models.ForeignKey(to="Business", to_field='id', on_delete=models.CASCADE) # user=models.OneToOneField(User,on_delete=models.CASCADE) # --在老版本这个参数(models.CASCADE)是默认值 ''' on_delete有CASCADE、PROTECT、SET_NULL、SET_DEFAULT、SET()五个可选择的值 CASCADE:此值设置,是级联删除。 PROTECT:此值设置,是会报完整性错误。 SET_NULL:此值设置,会把外键设置为null,前提是允许为null。 SET_DEFAULT:此值设置,会把设置为外键的默认值。 SET():此值设置,会调用外面的值,可以是一个函数。 ''' class Application(models.Model): name = models.CharField(max_length=32) # 方式二:Django自动维护Host与Application r = models.ManyToManyField('Host') # 方式一:创建第三张表维护Host与Application ''' class HostToApp(models.Model): hobj = models.ForeignKey('Host', to_field='nid', on_delete=models.CASCADE) aobj = models.ForeignKey('Application', to_field='id', on_delete=models.CASCADE) '''
1 from app02 import models 2 3 # (0)单表操作************************************************ 4 def business(request): 5 busi1 = models.Business.objects.all() 6 # QuerySet 列表 7 # [[obj(id,...)], [obj(id,...)]...] 8 busi2 = models.Business.objects.all().values('id', 'caption') 9 # QuerySet 字典 10 # [{'id':1, 'caption': 运维部}, {'id':1, 'caption': 运维部}, {}...] 11 busi3 = models.Business.objects.all().values_list('id', 'caption') 12 # QuerySet 元组 13 # [(1, 运维部), (1, 运维部), (1, 运维部),...] 14 return render(request, 'day20-app02/business.html', {'busi1': busi1, 'busi2': busi2, 'busi3': busi3})
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <h1>业务线列表 (列表)</h1> 9 <ul> 10 {% for foo in busi1 %} 11 <li>{{ foo.id }} - {{ foo.caption }} - {{ foo.code }}</li> 12 {% endfor %} 13 14 </ul> 15 16 <h1>业务线列表 (字典)</h1> 17 <ul> 18 {% for foo in busi2 %} 19 <li>{{ foo.id }} - {{ foo.caption }}</li> 20 {% endfor %} 21 </ul> 22 23 <h1>业务线列表 (元组)</h1> 24 <ul> 25 {% for foo in busi3 %} 26 <li>{{ foo.0 }} - {{ foo.1 }}</li> 27 {% endfor %} 28 </ul> 29 </body> 30 </html>
1 # (1)一对多************************************************** 2 # 模态框增加 √ Ajax增加 √ 3 # 新Url修改 X Ajax修改 √ 4 # ajax删除 √ 5 ''' 查 6 def host(request): 7 # *******************一对多块表操作的的三种方式************************ 8 # (1)对象 9 host_obj = models.Host.objects.filter(nid__gt=0) 10 # print(host_obj) #[<Host: Host object (1)>, <Host: Host object (2)>, <Host: Host object (3)>] 11 for row in host_obj: 12 print(row.nid, row.hostname, row.ip, row.port, row.b_id, row.b.caption, row.b.code, sep='\t\t') 13 # return HttpResponse('Host') 14 15 16 # (2)字典 17 host_dict = models.Host.objects.filter(nid__gt=0).values('nid', 'hostname', 'ip', 18 'port', 'b_id', 'b__caption', 19 'b__code') 20 # 跨表查询:__ --> str 21 for row in host_dict: 22 print(row['nid'], row['hostname'], row['ip'], row['port'], row['b_id'], 23 row['b__caption'], row['b__code']) 24 25 # (3)元组 26 # host_tuple = models.Host.objects.filter(nid__gt=0) # 相当于.all() 27 host_tuple = models.Host.objects.filter(nid__gt=0).values_list('nid', 'hostname', 28 'ip', 'port', 'b_id', 29 'b__caption', 'b__code') 30 for row in host_tuple: 31 print(row[0], row[1], row[2], row[3], row[4], row[5], row[6]) 32 33 34 return render(request, 'host.html', {'host_obj': host_obj, 'host_dict': host_dict, 35 'host_tuple': host_tuple}) 36 ''' 37 def host(request): 38 if request.method == "GET": 39 # *******************一对多块表操作的的三种方式************************ 40 # (1)对象 41 host_obj = models.Host.objects.filter(nid__gt=0) 42 for row in host_obj: 43 print(row.nid, row.hostname, row.ip, row.port, row.b_id, row.b.caption, row.b.code, sep='\t\t') 44 # (2)字典 45 host_dict = models.Host.objects.filter(nid__gt=0).values('nid', 'hostname', 'ip', 46 'port', 'b_id', 'b__caption', 47 'b__code') 48 for row in host_dict: 49 print(row['nid'], row['hostname'], row['ip'], row['port'], row['b_id'], 50 row['b__caption'], row['b__code']) 51 # (3)元组(取值注意顺序) 52 host_tuple = models.Host.objects.filter(nid__gt=0).values_list('nid', 'hostname', 53 'ip', 'port', 'b_id', 54 'b__caption', 'b__code') 55 for row in host_tuple: 56 print(row[0], row[1], row[2], row[3], row[4], row[5], row[6]) 57 58 59 # 下拉框获取业务线的所有业务数据,通过主机表获取到的数据是有限的且是重复的 60 # 我们需要单独获取business的id 61 business_obj = models.Business.objects.all() 62 63 return render(request, 'day20-app02/host.html', {'host_obj': host_obj, 'host_dict': host_dict, 64 'host_tuple': host_tuple, 65 'business_obj': business_obj}) 66 elif request.method == 'POST': 67 h = request.POST.get('hostname') 68 i = request.POST.get('ip') 69 p = request.POST.get('port') 70 b = request.POST.get('caption') #得到的是value值: b_id 71 # 创建数据 72 ''' 73 models.Host.objects.create(hostname=h, ip=i, port=p, 74 # b=models.Business.objects.filter(id=b).first() 75 b=models.Business.objects.get(id=b) #对象=对象 76 ) 77 ''' 78 models.Host.objects.create(hostname=h, ip=i, port=p, 79 b_id=b, # 数据=数据 80 ) 81 # return render(request, 'host.html') 82 # 为了在提交数据后,页面显示新增数据和原先数据,可以两种方式: 83 # 1)把上面的GET代码,再复制过来,太麻烦,代码冗余 84 # 2)redirect到当前页面,get重新渲染 85 return redirect('/monitor/host') #url=能访问的链接地址
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 <link rel="stylesheet" href="/static/day20-app02/css.css" /> 7 </head> 8 <body> 9 <h1>*******************一对多块表操作的的三种方式************************</h1> 10 <h1>主机列表(对象)</h1> 11 <div> 12 <input id="add-host" type="button" value="添加" /> 13 </div> 14 <table border="1" style="text-align: center"> 15 <thead> 16 <tr> 17 <!--<td>主机ID</td>--> 18 <td>主机名</td> 19 <td>主机IP</td> 20 <td>主机端口</td> 21 <!--<td>业务线ID</td>--> 22 <td>业务线部门</td> 23 <!--<td>业务线编码</td>--> 24 25 <!-- 编辑 --> 26 <td>操作</td> 27 </tr> 28 </thead> 29 <tbody> 30 <!-- 31 {% for row in host_obj %} 32 <tr>{{ row.nid }}</tr> 33 <tr>{{ row.hostname }}</tr> 34 <tr>{{ row.ip }}</tr> 35 <tr>{{ row.port }}</tr> 36 <tr>{{ row.b_id }}</tr> 37 <tr>{{ row.b.caption }}</tr> 38 <tr>{{ row.b.code }}</tr> 39 {% endfor %} 40 --> 41 {% for row in host_obj %} 42 <tr hid="{{ row.nid }}" bid="{{ row.b_id }}"> 43 <!--<td>{{ row.nid }}</td>--> 44 <td>{{ row.hostname }}</td> 45 <td>{{ row.ip }}</td> 46 <td>{{ row.port }}</td> 47 <!--<td>{{ row.b_id }}</td>--> 48 <td>{{ row.b.caption }}</td> 49 <!--<td>{{ row.b.code }}</td>--> 50 51 <!-- 编辑 --> 52 <td class="operate"> 53 <span class="edithost">编辑</span>|<!--循环里面的事件,不能用id,id不能重复,只能用class--> 54 <a class="delete">删除</a> 55 </td> 56 </tr> 57 {% endfor %} 58 </tbody> 59 </table> 60 61 <h1>主机列表(字典)</h1> 62 <table border="1" style="text-align: center"> 63 <thead> 64 <tr> 65 <!--<td>主机ID</td>--> 66 <td>主机名</td> 67 <td>主机IP</td> 68 <td>主机端口</td> 69 <!--<td>业务线ID</td>--> 70 <td>业务线部门</td> 71 <!--<td>业务线编码</td>--> 72 </tr> 73 </thead> 74 <tbody> 75 {% for row in host_dict %} <!-- python中的字典,在html中,对应的都是.取值--> 76 <tr hid="{{ row.nid }}" bid="{{ row.b_id }}"> 77 <!--<td>{{ row.nid }}</td>--> 78 <td>{{ row.hostname }}</td> 79 <td>{{ row.ip }}</td> 80 <td>{{ row.port }}</td> 81 <!--<td>{{ row.b_id }}</td>--> 82 <td>{{ row.b__caption }}</td> 83 <!--<td>{{ row.b__code }}</td>--> 84 </tr> 85 {% endfor %} 86 </tbody> 87 </table> 88 89 <h1>主机列表(元组)</h1> 90 <table border="1" style="text-align: center"> 91 <thead> 92 <tr> 93 <!--<td>主机ID</td>--> 94 <td>主机名</td> 95 <td>主机IP</td> 96 <td>主机端口</td> 97 <!--<td>业务线ID</td>--> 98 <td>业务线部门</td> 99 <!--<td>业务线编码</td>--> 100 </tr> 101 </thead> 102 <tbody> 103 {% for row in host_tuple %} <!-- python中的字典,在html中,对应的都是.取值--> 104 <tr hid="{{ row.0 }}" bid="{{ row.4 }}"> 105 <!--<td>{{ row.0 }}</td>--> 106 <td>{{ row.1 }}</td> 107 <td>{{ row.2 }}</td> 108 <td>{{ row.3 }}</td> 109 <!--<td>{{ row.4 }}</td>--> 110 <td>{{ row.5 }}</td> 111 <!--<td>{{ row.6 }}</td>--> 112 </tr> 113 {% endfor %} 114 </tbody> 115 </table> 116 117 <!-- 以主机列表(对象)拓展,模态对话框 添加与删除可以共用,本示例分开做的模态对话框 --> 118 <div class="shade hide"></div> 119 <div class="modal hide"> 120 <form action="/monitor/host" method="post"> 121 <div class="add-host"> 122 <input type="text" placeholder="主机名" name="hostname" /> 123 </div> 124 <div class="add-host"> 125 <input type="text" placeholder="主机IP" name="ip" /> 126 </div> 127 <div class="add-host"> 128 <input type="text" placeholder="主机端口" name="port" /> 129 </div> 130 <div class="add-host"> 131 <select name="caption"> 132 {% for row in business_obj %} 133 <option value="{{ row.id }}">{{ row.caption }}</option> 134 {% endfor %} 135 </select> 136 </div> 137 <div> 138 <input type="submit" value="提交"> 139 <input id="cancel" type="button" value="取消"> 140 <input id="ajax" type="button" value="Ajax悄悄提交"> 141 <span id="error" style="color: red;"></span> 142 </div> 143 </form> 144 </div> 145 <div class="edit-modal hide"> 146 <form id="edit-form" action="/monitor/host" method="post"> 147 <div class="edit-host"> 148 <input type="text" name="hostname" /> 149 <input style="display: none" type="text" name="hid" /> 150 </div> 151 <div class="edit-host"> 152 <input type="text" name="ip" /> 153 </div> 154 <div class="edit-host"> 155 <input type="text" name="port" /> 156 </div> 157 <div class="edit-host"> 158 <select name="caption"> 159 {% for row in business_obj %} 160 <option value="{{ row.id }}">{{ row.caption }}</option> 161 {% endfor %} 162 </select> 163 </div> 164 <div> 165 <input type="submit" value="提交"> 166 <input class="cancel" type="button" value="取消"> 167 <input class="ajax" type="button" value="Ajax悄悄提交"> 168 <span class="error" style="color: red;"></span> 169 </div> 170 </form> 171 </div> 172 173 174 <script src="/static/day20-app02/jquery-1.12.4.js"></script> 175 <script> 176 $('#add-host').click(function(){ 177 $('.shade, .modal').removeClass('hide') 178 }); 179 $('#cancel').click(function(){ 180 $('.shade, .modal').addClass('hide'); 181 }); 182 $('.cancel').click(function(){ 183 $('.shade, .edit-modal').addClass('hide'); 184 }); 185 186 //Ajax提交示例 187 188 //初识ajax 示例 189 /* 190 $('#ajax').click(function () { 191 $.ajax({ 192 //url: 'testajax', 193 url: '/monitor/testajax', 194 type: 'POST', 195 data: {'hostname': $('input[name="hostname"]').val(), 'ip': $('input[name="ip"]').val(), 196 'port': $('input[name="port"]').val(), 197 'caption': $('select[name="caption"]').val()}, 198 success: function (data2) { 199 //data2是服务端返回的字符串 200 if(data2 === 'OK'){ 201 location.reload(); 202 }else{ 203 alert(data2); 204 } 205 } 206 }); 207 }); 208 */ 209 //ajax整理 210 $('#ajax').click(function () { 211 $.ajax({ 212 //url: 'testajax', 213 url: '/monitor/testajax-add', 214 type: 'POST', 215 data: {'hostname': $('input[name="hostname"]').val(), 'ip': $('input[name="ip"]').val(), 216 'port': $('input[name="port"]').val(), 217 'caption': $('select[name="caption"]').val()}, 218 success: function (data2) { 219 //data2是服务端返回的字符串<---python字典序列化后的字符串 220 //data2 反序列化成字符串(对象:可以.获取值) 221 var obj = JSON.parse(data2); 222 if(obj.status){ //True 223 {#console.log(obj);#} 224 location.reload(); //刷新页面 225 }else{ //False 226 //获取html错误信息代码,text() 227 //替换 228 $('#error').text(obj.error_msg); 229 } 230 } 231 }); 232 }); 233 234 //编辑 - 示例 235 $('.edithost').click(function(){ 236 $('.shade, .edit-modal').removeClass('hide'); 237 238 var nid = $(this).parent().parent().attr('hid'); //获取主键,用于ajax提交数据的 239 console.log("nid", nid); 240 $('#edit-form').children(':first').children(':last').val(nid); 241 242 var bid = $(this).parent().parent().attr('bid'); //获取主键 243 console.log("bid", bid); 244 $(this).parent().prevAll().each(function(){ 245 var index = $(this).index(); 246 var text = $(this).text(); 247 console.log(index, text); 248 var selecttag = $('.edit-host').eq(index).children()[0].tagName; 249 console.log(selecttag); 250 if(selecttag === 'SELECT'){ 251 //var value = $(this).val();不是获取文字,而是获取编号bid 252 $('.edit-host').eq(index).children(':first').val(bid); //select直接.val()获取值 253 //val 实际就是option的value值:数字,不是文字 254 }else{ 255 $('.edit-host').eq(index).children(':first').val(text); 256 } 257 //console.log($('.edit-host').length) 258 }); 259 }); 260 $('.ajax').click(function () { 261 $.ajax({ 262 url: '/monitor/testajax-edit', 263 type: 'POST', 264 data: $('#edit-form').serialize(), //form把input,select...数据打包发至后台 265 success: function (data2) { 266 var obj = JSON.parse(data2); 267 if (obj.status) { //True 268 location.reload(); //刷新页面 269 } else { //False 270 $('#error').text(obj.error_msg); 271 } 272 } 273 }); 274 }); 275 276 //删除 - 示例 277 $('.delete').click(function () { 278 var hid = $(this).parent().parent().attr('hid'); 279 //删除确认 280 var v = confirm("请认真操作数据,本次为永久删除数据操作。"); 281 if(v){ 282 //正在删除 283 $.ajax({ 284 url: '/monitor/host-del', 285 type: "POST", 286 data: {'hid': hid}, 287 dataType: 'JSON', 288 success: function (obj) { 289 if(obj.status){ 290 location.reload(); 291 }else{ 292 alert('因为某种原因,无法删除。'); 293 } 294 } 295 }); 296 //console.log(hid); 297 }else{ 298 alert('已撤销数据删除操作!'); 299 } 300 }) 301 </script> 302 </body> 303 </html>
1 # Ajax示例 2 ''' #初识ajax 3 def testajax(request): 4 print(request.method) 5 if request.method == "POST": 6 h = request.POST.get('hostname') 7 i = request.POST.get('ip') 8 p = request.POST.get('port') 9 b = request.POST.get('caption') 10 print(h, i, p ,b) 11 if h and len(h) > 3: #None不能直接len() 12 models.Host.objects.create( 13 hostname=h, 14 ip=i, 15 port=p, 16 b_id=b, 17 ) 18 return HttpResponse('OK') 19 else: 20 return HttpResponse('太短了') 21 ''' 22 23 # ajax整理,对上面用了Try url(r'^testajax$', views.testajax), #Ajax示例 24 ''' 25 def testajax(request): 26 import json 27 data_dict = {'status': True, 'error_msg': None, 'data': None} 28 if request.method == "POST": 29 try: 30 h = request.POST.get('hostname') 31 i = request.POST.get('ip') 32 p = request.POST.get('port') 33 b = request.POST.get('caption') 34 if h and len(h) > 3: #None不能直接len() 35 models.Host.objects.create( 36 hostname=h, 37 ip=i, 38 port=p, 39 b_id=b, 40 ) 41 # return HttpResponse(json.dumps(data_dict)) 42 else: 43 data_dict['error_msg'] = '太短了' 44 data_dict['status'] = False 45 # return HttpResponse(json.dumps(data_dict)) 46 except Exception as e: 47 data_dict['error_msg'] = '不是太短了,有其他错误' 48 data_dict['status'] = False 49 # return HttpResponse(json.dumps(data_dict)) 50 return HttpResponse(json.dumps(data_dict)) 51 ''' 52 53 # ajax整理,对上面的拓展(增改合并) url(r'^testajax(\w+\d+)$', views.testajax), #Ajax示例 54 def testajax(request, type): 55 import json 56 data_dict = {'status': True, 'error_msg': None, 'data': None} 57 if request.method == "POST": 58 try: 59 h = request.POST.get('hostname') 60 i = request.POST.get('ip') 61 p = request.POST.get('port') 62 b = request.POST.get('caption') 63 if h and len(h) > 3: #None不能直接len() 64 65 if type == 'add': 66 models.Host.objects.create( 67 hostname=h, 68 ip=i, 69 port=p, 70 b_id=b, 71 ) 72 # return HttpResponse(json.dumps(data_dict)) 73 elif type == 'edit': 74 hid = request.POST.get('hid') 75 models.Host.objects.filter(nid=hid).update( 76 hostname=h, 77 ip=i, 78 port=p, 79 b_id=b, 80 ) 81 else: 82 data_dict['error_msg'] = '太短了' 83 data_dict['status'] = False 84 # return HttpResponse(json.dumps(data_dict)) 85 except Exception as e: 86 data_dict['error_msg'] = '不是太短了,有其他错误' 87 data_dict['status'] = False 88 # return HttpResponse(json.dumps(data_dict)) 89 return HttpResponse(json.dumps(data_dict)) 90 91 # ajax删除 92 def host_del(request): 93 import json 94 host_dict = {'status': True, 'error_msg': None, 'data': None} 95 if request.method == 'POST': 96 hid = request.POST.get('hid') 97 print("Hid>>", hid) 98 models.Host.objects.filter(nid=hid).delete() 99 return HttpResponse(json.dumps(host_dict))
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 <link rel="stylesheet" href="/static/day20-app02/css.css" /> 7 <link rel="stylesheet" href="/static/font-awesome-4.7.0/css/font-awesome.min.css" /> 8 <style> 9 /*这个只能写在这里,其他地方无效*/ 10 .apptohost{ 11 display: inline-block; 12 padding: 3px 16px; 13 background-color: green; 14 color: white; 15 16 position: relative; /* 图标 */ 17 } 18 .apptohost .font{ 19 display: none; 20 21 font-size: 0.8em; 22 position: absolute; 23 right: 3px; 24 top: 3px; 25 } 26 .apptohost:hover .font{ 27 display: inline; 28 cursor: pointer; 29 } 30 </style> 31 </head> 32 <body> 33 <h1>Application与Host的多对多关系表</h1> 34 <div> 35 <input id="addapp" type="button" value="添加" /> 36 </div> 37 <table border="1" style="text-align: center"> 38 <thead> 39 <tr> 40 <th>应用名称</th> 41 <th>主机列表</th> 42 <th>操作</th> 43 </tr> 44 </thead> 45 <tbody> 46 <!-- 循环 --> 47 {% for app in app_list %} 48 <tr aid="{{ app.id }}"> 49 <td>{{ app.name }}</td> 50 51 <!-- <td>{{ app.r.all }}</td> --> 52 <td> 53 {% for foo in app.r.all %} <!-- foo: 单个主机对象 --> 54 <span class="apptohost" hid="{{ foo.nid }}">{{ foo.hostname }} <i class="font fa fa-close"></i></span> 55 {% endfor %} 56 </td> 57 58 <!-- 操作:编辑/删除 --> 59 <td> 60 <a class="edit">编辑</a> | 61 <a class="delete">删除</a> 62 </td> 63 64 </tr> 65 {% endfor %} 66 67 </tbody> 68 </table> 69 70 <div class="shade hide"></div> 71 <div class="modal hide"> 72 <form id="ajax-add-app" action="" method="post"> 73 <div class="add-app"> 74 <input type="text" placeholder="应用名称名" name="appname" /> 75 </div> 76 <div class="add-app"> 77 <select name="host_list" multiple> 78 {% for row in host_list %} 79 <option value="{{ row.nid }}">{{ row.hostname }}</option> 80 {% endfor %} 81 </select> 82 </div> 83 <div> 84 <!-- <input type="submit" value="提交"> --> 85 <input id="cancel" type="button" value="取消"> 86 87 <input id="ajax" type="button" value="Ajax悄悄提交"> 88 <span id="error" style="color: red;"></span> 89 </div> 90 </form> 91 </div> 92 <div class="edit-modal hide"> 93 <form class="ajax-edit-app" action="" method="post"> 94 <div class="edit-app"> 95 <input type="text" name="appname" /> 96 <input style="display: none" type="text" name="aid" /> 97 </div> 98 <div class="edit-app"> 99 <select name="host_list" multiple> 100 {% for row in host_list %} 101 <option value="{{ row.nid }}">{{ row.hostname }}</option> 102 {% endfor %} 103 </select> 104 </div> 105 <div> 106 <!-- <input type="submit" value="提交"> --> 107 <input class="cancel" type="button" value="取消"> 108 109 <input class="ajax" type="button" value="Ajax悄悄提交"> 110 <span class="error" style="color: red;"></span> 111 </div> 112 </form> 113 </div> 114 <div class="delete-modal hide"> 115 <form class="ajax-delete-app" action="" method="post"> 116 <div class="delete-app"> 117 应用名称:<span></span> 118 <input style="display: none" type="text" name="aid" /> 119 </div> 120 <div class="delete-app"> 121 关联的主机名:<span></span> 122 </div> 123 <div> 124 <!-- <input type="submit" value="提交"> --> 125 <input class="cancel" type="button" value="取消"> 126 127 <input class="ajax-del" type="button" value="Ajax悄悄删除"> 128 <span class="error" style="color: red;"></span> 129 </div> 130 </form> 131 </div> 132 133 <script src="/static/day20-app02/jquery-1.12.4.js"></script> 134 <script> 135 $('#addapp').click(function(){ 136 $('.shade, .modal').removeClass('hide') 137 }); 138 $('#cancel').click(function(){ 139 $('.shade, .modal').addClass('hide'); 140 }); 141 142 //Ajax提交添加数据 143 /* //基础版 144 $('#ajax').click(function(){ 145 $.ajax({ 146 url: '/monitor/app-ajax', 147 type: 'POST', 148 data: $('#ajax-add-app').serialize(), //获取表单form的数据 149 success: function (data) { 150 var obj = JSON.parse(data); 151 if(obj.status){ 152 location.reload(); 153 } 154 else{ 155 alert('输入有误!') 156 } 157 } 158 }); 159 }); 160 */ 161 //升级版 162 $('#ajax').click(function(){ 163 $.ajax({ 164 url: '/monitor/app-ajax', 165 type: 'POST', 166 data: $('#ajax-add-app').serialize(), //获取表单form的数据 167 168 //data: {'user': 'uson', 'pwd': [1,2,3]}, 169 //traditional: true, //列表不同于字符串,必须添加参数:traditional 170 171 dataType: "JSON", 172 success: function (obj) { 173 //obj:是字符串被序列化后的对象 174 if(obj.status){ 175 location.reload(); 176 } 177 else{ 178 alert('输入有误!') 179 } 180 }, 181 error: function () { 182 alert("未发送至后台的未知错误!"); 183 } 184 }); 185 }); 186 187 //Ajax提交编辑数据 188 $('.edit').click(function(){ 189 $('.shade, .edit-modal').removeClass('hide'); 190 191 //获取数据 192 var host_list = []; 193 //$(this).parent().prev().children() 找到关联的所有主机下拉列表, 每个循环找到hid 194 $(this).parent().prev().children().each(function () { 195 //通过span标签,找到自定义属性hid 196 var nid = $(this).attr('hid'); 197 host_list.push(nid); 198 }); 199 //将获取到的关联id列表赋值,但先要找到模态框中的name=host_list的select标签 200 $('.ajax-edit-app select[name="host_list"]').val(host_list); 201 //找到application的id ===> aid 202 var aid = $(this).parent().parent().attr('aid'); 203 $('.ajax-edit-app input[name="aid"]').val(aid); 204 205 // 再获取appname, 赋值 206 //var text = $(this).parent().prev(":last").text(); //误区:就是上一个 207 var text = $(this).parent().siblings().prev(":last").text(); 208 //console.log("TEXT:", text); 209 $('.ajax-edit-app input[name="appname"]').val(text); 210 }); 211 $('.cancel').click(function(){ 212 $('.shade, .edit-modal, .delete-modal').addClass('hide'); 213 }); 214 215 //先获取数据,再赋值数据 216 //写在$('.edit').click(function(){})里面 217 $('.ajax').click(function(){ 218 $.ajax({ 219 url: '/monitor/app-ajax-edit', 220 type: 'POST', 221 data: $('.ajax-edit-app').serialize(), //获取表单form的数据 222 dataType: "JSON", 223 success: function (obj) { 224 //obj:是字符串被序列化后的对象 225 if(obj.status){ 226 location.reload(); 227 } 228 else{ 229 alert('输入有误!') 230 } 231 }, 232 error: function () { 233 // ajax的url错误:/monitor/app_ajax_edit 234 // 后台问题,'Manager' object has no attribute 'filer' 235 // data中.ajax-edit-app类型错误:TypeError: int() argument must be a string, a bytes-like object or a number, not 'list' 236 // 后台getlist接收aid: ['5'], 错误提示同上 237 // 后台查询数据类型错误 AttributeError: 'int' object has no attribute 'r' 238 // OBJ>> Application object (4) 239 alert("未发送至后台的未知错误!"); 240 } 241 }); 242 }); 243 244 //ajax删除(点击X图标删除) 245 var hid = ''; 246 var aid = ''; 247 $('i').click(function(){ 248 {#console.log(123);#} 249 $('.shade, .delete-modal').removeClass('hide'); 250 251 //提取数据 同编辑,稍作修改 252 /* 253 var host_list = []; 254 $(this).parent().prev().children().each(function () { 255 var nid = $(this).attr('hid'); 256 host_list.push(nid); 257 }); 258 $('.ajax-delete-app select[name="host_list"]').val(host_list); 259 */ 260 var text = $(this).parent().text(); 261 hid = $(this).parent().attr('hid'); 262 var app_name = $(this).parent().parent().prev().text(); 263 aid = $(this).parent().parent().parent().attr('aid'); /*这里没用上,没用到form打包*/ 264 $('.ajax-delete-app').children(':first').children(':first').text(app_name).parent().next().children(':first').text(text); 265 //console.log(aid); 266 }); 267 //ajax删除 268 $('.ajax-del').click(function(){ 269 $.ajax({ 270 url: '/monitor/app-ajax-del', 271 type: 'POST', 272 data: {'appname': $('.ajax-delete-app').children(':first').children(':first').text(), 273 //'hostname': $('.ajax-delete-app').children(':first').next().children(':first').text(), 274 'hid': hid, 275 'aid': aid}, 276 dataType: "JSON", 277 success: function (obj) { 278 if(obj.status){ 279 location.reload(); 280 } 281 else{ 282 alert('输入有误!') 283 } 284 }, 285 error: function () { 286 alert("未发送至后台的未知错误!"); 287 } 288 }); 289 }); 290 </script> 291 </body> 292 </html>
1 # (2)多对多************************************************** 2 # 模态框增加 √ Ajax增加 √ 3 # 新Url修改 √ Ajax修改 √ 4 # Ajax删除 √ 5 # Application 多对多关系表 + 模态框方式添加数据 6 def app(request): 7 if request.method == 'GET': 8 app_list = models.Application.objects.all() 9 host_list = models.Host.objects.all() #外键关联,用于模板页面的下拉框获取,不用写死 10 return render(request, 'day20-app02/app.html', {'app_list': app_list, 'host_list': host_list}) 11 elif request.method == 'POST': 12 appname = request.POST.get('appname') 13 host_list = request.POST.getlist('host_list') #下拉框 14 15 obj = models.Application.objects.create(name=appname) 16 # r不用传,外键关联,该app创建完后是一个对象obj 17 obj.r.add(*host_list) #自动生成的外键关联 18 return redirect('/monitor/app') 19 20 # Application 多对多关系表 + Ajax方式添加数据 21 def app_ajax(request): 22 import json 23 app_dict = {'status': True, 'error_msg': None, 'data': None} 24 if request.method == 'GET': 25 print('get') 26 app_list = models.Application.objects.all() 27 host_list = models.Host.objects.all() 28 return render(request, 'day20-app02/app-ajax.html', {'app_list': app_list, 'host_list': host_list}) 29 elif request.method == 'POST': 30 print('post') 31 user = request.POST.get('user') 32 test_list = request.POST.getlist('pwd') 33 print(user, test_list) #post uson [] ===> 34 # 35 # appname = request.POST.get('appname') 36 # host_list = request.POST.getlist('host_list') 37 # print(appname, host_list) 38 # 39 # obj = models.Application.objects.create(name=appname) 40 # # r不用传,该app创建完后是一个对象obj 41 # obj.r.add(*host_list) 42 # 43 44 return HttpResponse(json.dumps(app_dict)) 45 46 47 # Application 多对多关系表 + Ajax方式编辑数据 48 def app_ajax_edit(request): 49 import json 50 app_dict = {'status': True, 'error_msg': None, 'data': None} 51 if request.method == 'GET': 52 print('get') 53 app_list = models.Application.objects.all() 54 host_list = models.Host.objects.all() 55 return render(request, 'day20-app02/app-ajax.html', {'app_list': app_list, 'host_list': host_list}) 56 elif request.method == 'POST': 57 print("app-ajax-edit>>", 'post') 58 appname = request.POST.get('appname') 59 host_list = request.POST.getlist('host_list') 60 # 数据包里没有aid如何知道更新哪条数据 61 aid = request.POST.get('aid') 62 print("app-ajax更新数据》》", appname, host_list, aid) 63 64 # obj = models.Application.objects.filter(id=aid).update(name=appname) 65 # 返回的不是对象,而是数字1 66 # obj = models.Application.objects.filter(id=aid) 67 # 返回的不是对象,而是列表[] 68 69 # obj = models.Application.objects.filter(id=aid).first() 70 # 返回的才是对象 71 obj = models.Application.objects.get(id=aid) 72 # 返回的也是对象 73 print("OBJ>>", obj) 74 # r不用传,该app创建完后是一个对象obj 75 obj.r.set(host_list) #更新数据,没有* 76 77 # obj.name = appname # 无法修改 78 models.Application.objects.filter(id=aid).update(name=appname) 79 80 return HttpResponse(json.dumps(app_dict)) 81 # return HttpResponse("OK") 82 83 # Application 多对多关系表 + Ajax方式删除数据 84 def app_ajax_del(request): 85 import json 86 app_dict = {'status': True, 'error_msg': None, 'data': None} 87 if request.method == 'GET': 88 print('get') 89 app_list = models.Application.objects.all() 90 host_list = models.Host.objects.all() 91 return render(request, 'day20-app02/app-ajax.html', {'app_list': app_list, 'host_list': host_list}) 92 elif request.method == 'POST': 93 print("app-ajax-edit>>", 'post') 94 appname = request.POST.get('appname') 95 # hostname = request.POST.get('hostname') 96 hid = request.POST.get('hid') 97 aid = request.POST.get('aid') 98 print("app-ajax更新数据》》", appname, hid, aid) 99 100 obj = models.Application.objects.get(id=aid) 101 obj.r.remove(hid) 102 return HttpResponse(json.dumps(app_dict)) 103 # return HttpResponse('OK')
1 # Application 多对多关系表 + 新URL方式修改数据 2 def app_newurl_edit(request, aid): 3 # import json 4 # app_dict = {'status': True, 'error_msg': None, 'data': None} 5 6 if request.method == 'GET': 7 # print("url路径>>", request.path_info) 8 app_list = models.Application.objects.all() 9 host_list = models.Host.objects.all() 10 11 # 编辑数据 12 appobj = models.Application.objects.filter(id=aid).first() 13 print(appobj.r.all()) 14 15 return render(request, 'day21-app03/newurl/app-edit.html', 16 {'app_list': app_list, 'host_list': host_list, 17 'appobj': appobj, 'aid': aid}) 18 elif request.method == 'POST': 19 aid = request.POST.get('app') 20 host_list = request.POST.getlist('host') #下拉框 21 print(aid, host_list) 22 obj = models.Application.objects.filter(id=aid).first() 23 obj.r.set(host_list) 24 models.Application.objects.filter(id=aid).update(name=obj.name) 25 26 # app_dict['data'] = {'host_list': host_list, 'aid': aid} 27 28 return redirect('/monitor/app')
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 <link rel="stylesheet" href="/static/day20-app02/css.css" /> 7 </head> 8 <body> 9 <h1>Application与Host的多对多关系表</h1> 10 <div> 11 <input id="addapp" type="button" value="添加" /> 12 </div> 13 <table border="1" style="text-align: center"> 14 <thead> 15 <tr> 16 <th>应用名称</th> 17 <th>主机列表</th> 18 <th>操作</th> 19 </tr> 20 </thead> 21 <tbody> 22 <!-- 循环 --> 23 {% for app in app_list %} 24 <tr aid="{{ app.id }}"> 25 <td>{{ app.name }}</td> 26 27 <!-- <td>{{ app.r.all }}</td> --> 28 <td> 29 {% for foo in app.r.all %} <!-- foo: 单个主机对象 --> 30 <span hid="{{ foo.nid }}">{{ foo.hostname }}</span> 31 {% endfor %} 32 </td> 33 <td> 34 <a class="new_edit" href="/monitor/app_newurl_edit-{{ app.id }}">新Url编辑</a> 35 </td> 36 </tr> 37 {% endfor %} 38 39 </tbody> 40 </table> 41 42 <div class="shade hide"></div> 43 <div class="modal hide"> 44 <form action="/monitor/app" method="post"> 45 <div class="add-app"> 46 <input type="text" placeholder="应用名称名" name="appname" /> 47 </div> 48 <div class="add-app"> 49 <select name="host_list" multiple> 50 {% for row in host_list %} 51 <option value="{{ row.nid }}">{{ row.hostname }}</option> 52 {% endfor %} 53 </select> 54 </div> 55 <div> 56 <input type="submit" value="提交"> 57 <input id="cancel" type="button" value="取消"> 58 <!-- 59 <input id="ajax" type="button" value="Ajax悄悄提交"> 60 <span id="error" style="color: red;"></span> 61 --> 62 </div> 63 </form> 64 </div> 65 66 <script src="/static/day20-app02/jquery-1.12.4.js"></script> 67 <script> 68 $('#addapp').click(function(){ 69 $('.shade, .modal').removeClass('hide') 70 }); 71 $('#cancel').click(function(){ 72 $('.shade, .modal').addClass('hide'); 73 }); 74 75 //Ajax提交编辑数据 76 $('.new_edit').click(function(){ 77 var aid = $(this).parent().parent().attr('aid'); 78 var host_list = []; 79 $(this).parent().prev().children().each(function () { 80 var hid = $(this).attr('hid'); 81 host_list.push(hid); 82 }); 83 var appname = $(this).parent().parent().children(':first').text(); 84 $.ajax({ 85 url: '/monitor/app_newurl_edit-' + aid, 86 //type: 'POST', 87 type: 'GET', 88 89 traditional: true, 90 data: {'aid': aid, 'appname': appname, 'host_list': host_list}, 91 success: function(data){ 92 alert('新URL编辑页面跳转成功!'); 93 } 94 }); 95 }); 96 </script> 97 </body> 98 </html>
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 <link rel="stylesheet" href="/static/day20-app02/css.css" /> 7 </head> 8 <body> 9 <h1>Application与Host的多对多关系表编辑界面</h1> 10 <form action="/monitor/app_newurl_edit-{{ aid }}" method="post"> 11 <div> 12 <input type="submit" value="保存" /> 13 </div> 14 <table border="1" style="text-align: center"> 15 <thead> 16 <tr> 17 <th>应用名称</th> 18 <th>主机列表</th> 19 </tr> 20 </thead> 21 <tbody> 22 <tr> 23 <td> 24 <select name="app"> 25 {% for app in app_list %} 26 {% if app.name == appobj.name %} 27 <option selected="selected" value="{{ app.id }}">{{ app.name }}</option> 28 {% else %} 29 <option value="{{ app.id }}">{{ app.name }}</option> 30 {% endif %} 31 {% endfor %} 32 </select> 33 </td> 34 <td> 35 <select name="host" multiple> 36 {% for host in host_list %} 37 {% if host in appobj.r.all %} <!-- 对象与对象 --> 38 <option selected="selected" value="{{ host.nid }}">{{ host.hostname }}</option> 39 {% else %} 40 <option value="{{ host.nid }}">{{ host.hostname }}</option> 41 {% endif %} 42 {% endfor %} 43 </select> 44 </td> 45 </tr> 46 </tbody> 47 </table> 48 </form> 49 </body> 50 </html>