一、概述

1、什么是框架?

框架,即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以帮你快速开发特定的系统,简单说就是使用别人搭好的舞台,你来做表演。

2、常见的Python Web框架:

Full-Stack Frameworks(全栈框架、重量级框架):
Django、web2py、TurboGears、Pylons、...

Non Full-Stack Frameworks(非全栈框架、轻量级的框架):
tornado、Flask、Bottle、web.py、Pyramid、...

详见:https://wiki.python.org/moin/WebFrameworks

3、这么多框架,如何选择?

a、根据项目需求去选择。
b、根据框架的特点去选择

国内常用:django、tornado、flask、bottle,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM、模型绑定、模板引擎、缓存、Session等诸多功能。

Django官网:https://docs.djangoproject.com/en/1.11/

二、基本配置

1、创建django程序

  • 终端命令:django-admin startproject sitename
  • IDE创建Django程序时,本质上都是自动执行上述命令

常用命令:

  1. django-admin startproject sitename
  2. django-admin startapp appname
  3. python manage.py runserver 0.0.0.0:8000
  4. python manage.py makemigrations
  5. python manage.py migrate
  6. python manage.py createsuperuser
  7. python manage.py changepassword
  8. python manage.py clearsessions

其他命令:

  1. python manage.py shell #进入django shell
  2. python manage.py dbshell #进入django dbshell
  3. python manage.py check #检查django项目完整性
  4. python manage.py flush #清空数据库
  5. python manage.py compilemessages #编译语言文件
  6. python manage.py makemessages #创建语言文件
  7. python manage.py showmigrations #查看生成的数据库同步脚本
  8. python manage.py sqlflush #查看生成清空数据库的脚本
  9. python manage.py sqlmigrate #查看数据库同步的sql语句
  10. python manage.py dumpdata #导出数据
  11. python manage.py loaddata #导入数据
  12. python manage.py diffsettings #查看你的配置和django默认配置的不同之处

其他命令

2、程序目录,django 1.9以上templates会自动创建

3、配置文件

(1)APP配置,后续创建app需要添加进这里

  1. INSTALLED_APPS = [
  2. 'django.contrib.admin',
  3. 'django.contrib.auth',
  4. 'django.contrib.contenttypes',
  5. 'django.contrib.sessions',
  6. 'django.contrib.messages',
  7. 'django.contrib.staticfiles',
  8. 'cmdb',
  9. ]

(2)数据库配置,默认是sqlite3

  1. DATABASES = {
  2. 'default': {
  3. 'ENGINE': 'django.db.backends.mysql',
  4. 'NAME':'dbname',
  5. 'USER': 'root',
  6. 'PASSWORD': '123456',
  7. 'HOST': '',
  8. 'PORT': '',
  9. }
  10. }

由于Django内部连接MySQL时使用的是MySQLdb模块,而python3中还无此模块,所以需要使用pymysql来代替
如下设置放置的与project同名的配置的 __init__.py文件中

  1. import pymysql
  2. pymysql.install_as_MySQLdb()

(3)模版配置

templates是用于放置模板html,在django1.9以上中会自动创建并设置

  1. TEMPLATES = [
  2. {
  3. 'BACKEND': 'django.template.backends.django.DjangoTemplates',
  4. 'DIRS': [os.path.join(BASE_DIR, 'templates')]
  5. ,
  6. 'APP_DIRS': True,
  7. 'OPTIONS': {
  8. 'context_processors': [
  9. 'django.template.context_processors.debug',
  10. 'django.template.context_processors.request',
  11. 'django.contrib.auth.context_processors.auth',
  12. 'django.contrib.messages.context_processors.messages',
  13. ],
  14. },
  15. },
  16. ]

(4)静态文件配置

static是自己创建的目录用于放置css,js,image,需要在settings中设置这个目录  

  1. STATIC_URL = '/static/'
  2. # 这个路径是对应 src="/static/ 这个的别名, 如果这个路径改为 STATIC_URL = '/abc/' 那么<script src="/abc/jquery-2.2.4.min.js"></script>
  3.  
  4. STATICFILES_DIRS = (
  5. os.path.join(BASE_DIR,'static'),
  6. )
  7.  
  8. <script src="/static/jquery-2.2.4.min.js"></script>

MEDIA是自己创建的目录用于上传图片和文件

MEDIA_ROOT:是本地路径的绝对路径,一般是这样写
MEDIA_URL:是指从浏览器访问时的地址前缀

  1. MEDIA_URL = '/upload/'
  2. MEDIA_ROOT = os.path.join(BASE_DIR,'upload')

from django.conf.urls import url
from django.contrib import admin
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^upload/(?P<path>.*)$', "django.views.static.serve", {"document_root": settings.MEDIA_ROOT,}),  #以前是这种
] + static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)  #现在的版本应该是这样

  1. from django.db import models
  2.  
  3. class Article(models.Model):
  4. '''
  5. 图片上传的路径就会在/upload/article/2016/09/23/a1.jpg
  6. 浏览器访问:http://127.0.0.1:8000/upload/article/2016/09/23/a1.jpg
  7. '''
  8. head_img = models.ImageField(max_length=200,upload_to='article/%Y/%m/%d',\
  9. default='article/default.png',null=True,blank=True)

models.py

文件上传类似,前端form属性要有enctype='multipart/form-data',models中的字段为models.FileField(max_length='',upload_to='')

三、路由系统详解

  1. urlpatterns = [
  2. url(正则表达式, views视图函数, 参数, 别名name=""),
  3. url(r'^index/(\d*)', views.index, {'id':333}, name="test")
  4. ]
  5.  
  6. #别名name="test" 那么前端比如form <form action="{% url "test" %}" method="post"></form> 这样提交就会交给 views.index这个方法

1、每个路由规则对应一个view中的函数,前端传的任何数据类型到后端都是字符串

  1. # 有分组后端view即需要参数接收
  2. url(r'^index/(\d*)', views.index),
  3. url(r'^list/(\d*)/(\d*)/$', views.list),
  4. url(r'^manage/(?P<name>\w*)/(?P<id>\d*)', views.manage),
  5. url(r'^login/(?P<name>\w*)', views.login,{'id':333}),
  6. url(r'^login/(?P<id>[0-9]{4})', views.login,{'id':333}), #id:333会覆盖掉前面匹配到的值
  1. def index(request,id): # id形参的名字是随便定义的
  2.  
  3. return render_to_response('index.html')
  4.  
  5. def list(request,id1,id2): # id1,id2形参的名字是随便定义的
  6.  
  7. return render_to_response('list.html')
  8.  
  9. def manage(request,name,id): # name,id形参的名字是和(?P<name>\w*)/(?P<id>\d*)是一样的
  10.  
  11. return render_to_response('index.html')
  12.  
  13. def login(request,name,id): # name,id形参的名字是和(?P<name>\w*),{'id':}是一样的
  14.  
  15. return render_to_response('login.html')

2、根据app对路由规则进行一次分类

  1. from django.conf.urls import include
  2.  
  3. urlpatterns = patterns[
  4. url(r'^web/', include('web.url')),
  5. url(r'^app01/', include('app01.url')),
  6. ]

django中的路由系统和其他语言的框架有所不同,在django中每一个请求的url都要有一条路由映射,这样才能将请求交给对一个的view中的函数去处理。其他大部分的Web框架则是对一类的url请求做一条路由映射,从而是路由系统变得简洁。

通过反射机制,为django开发一套动态的路由系统Demo: 点击下载

四、views详解

http请求中产生的两个核心对象:所在位置:django.http
                
http请求:HttpRequest
http响应:HttpResponse

1、HttpRequest:

(1)HttpRequest对象的属性:

 
(2)HttpRequest对象的方法(部分):
  1. get_full_path():返回包含查询字符串的请求路径。例如, "/music/bands/the_beatles/?print=true"
 
(3)QueryDict对象(部分) 
  1. get():如果key对应多个valueget()返回最后一个value
在HttpRequest对象中, GET和POST属性是django.http.QueryDict类的实例。

2、HttpResponse:

对于HttpRequest 对象来说,是由Django自动创建, 但是,HttpResponse对象就必须我们自己创建。
每个View请求处理方法必须返回一个HttpResponse对象。如果没有返回,则会捕获valueerror异常,HttpResponse类在django.http.HttpResponse。
 
(1)构造HttpResponse:
  1. >>> response = HttpResponse("Here's the text of the Web page.")
  2. >>> response = HttpResponse("Text only, please.", mimetype="text/plain")
  3.  
  4. # 在HttpResponse对象上常用方法:render、render_to_response、redirect(重定向)
  5. >>> response = render(request,'index.html',{向模板传递的变量})
  6. >>> response = render_to_response('index.html',{向模板传递的变量})
  7. >>> response = redirect("http://www.baidu.com") 或者 redirect("/blog/py/login")
  8.  
  9. # render与render_to_response区别在于第一个参数是否要request,所以就用render
  10. # 表单提交的时候render_to_response还需要添加 context_instance=RequestContext(request)否则会报csrf错误

更多详见

(2)HttpResponse的子类(部分):

更详细的有关request和response对象的介绍:
https://docs.djangoproject.com/en/1.11/ref/request-response/

(3)locals()
可以直接将函数中所有的变量全部传给模板,自动拼接成字典,很方便。
但是它会多传递一些没用的变量,有点浪费

五、模板详解

1、模版的执行

  1. return render(request,"index.html",{"name":"alex"})
  2.  
  3. # "index.html是Template模板
  4. # {"name":"alex"}是上下文

HttpResponse模版的创建过程,对于模版,其实就是读取模版(其中嵌套着模版标签),

是通过Template,Context对象来创建渲染模板的,所以render已经封装了HttpResponse,Template,Context所以很简单

  1. def current_datetime(request):
  2. now = datetime.datetime.now()
  3. html = "<html><body>It is now %s.</body></html>" % now
  4. return HttpResponse(html)

手动嵌套变量到模板中

  1. from django import template
  2. t = template.Template('My name is {{ name }}.')
  3. c = template.Context({'name': 'Adrian'})
  4. print(t.render(c))

django通过模板语言将变量嵌套html中(一)

  1. import datetime
  2. from django import template
  3. import DjangoDemo.settings
  4.  
  5. now = datetime.datetime.now()
  6. fp = open(settings.BASE_DIR+'/templates/Home/Index.html')
  7. t = template.Template(fp.read())
  8. fp.close()
  9. html = t.render(template.Context({'current_date': now}))
  10. return HttpResponse(html)

django通过模板语言将变量嵌套html中(二)

  1. from django.template.loader import get_template
  2. from django.template import Context
  3. from django.http import HttpResponse
  4. import datetime
  5.  
  6. def current_datetime(request):
  7. now = datetime.datetime.now()
  8. t = get_template('current_datetime.html')
  9. html = t.render(Context({'current_date': now}))
  10. return HttpResponse(html)

django通过模板语言将变量嵌套html中(三)

  1. return render_to_response('Account/Login.html',data,context_instance=RequestContext(request))
  2. 注意:当数据POST的时候,Django做了跨站请求伪造

2、模版语言

 模板中也有自己的语言,该语言可以实现数据展示

(1)模板取值

  1. # views函数返回的是字符串,通过{{ k1 }}获取字符串v1,前端引用的名字是k1
  2. return render('index.html',{'k1':'v1'}
  3.  
  4. # views函数返回的是列表,通过{{ list.0 }}获取字符串11,{{ list.1 }}获取字符串22,前端引用的名字是list
  5. return render('index.html',{'list':[11,22,33,44]}
  6.  
  7. # views函数返回的是字典,通过{{ dict.k1 }}获取字符串v1,{{ dict.k2 }}获取字符串v2,前端引用的名字是dict
  8. return render('index.html',{'dict':{'k1':'v1','k2':'v2'}}
  9.  
  10. # views把全部变量传入前端,locals(),前端引用的名字直接是views中的变量名
  11. return render('index.html',locals()}
  12.  
  13. # views把一个对象传入前端,前端通过obj.name,obj.age来取值
  14. def index(request):
  15. class Person():
  16. def __init__(self,name,age):
  17. self.name = name
  18. self.age = age
  19. s4 = Person("xiao",18)
  20. return render(request,"index.html",{"obj":s4})

(2)流程控制

  1. {% if a > b %}
  2. .......
  3. {% elif a == b %}
  4. .......
  5. {% else %}
  6. .......
  7. {% endif %}

(3)for循环

  1. {% for item in data %}
  2.   {{ item }}
  3. {# 下面几个是特殊变量 #}
  4. forloop.counter {# 索引从1开始 #}
  5. forloop.counter0 {# 索引从0开始 #}
  6. forloop.first {# 是否是循环的第一个 #}
  7. forloop.last {# 是否是循环的最后一个 #}
  8. {% endfor %}
  1. 1、{% if %}
  2. 可以使用and, or, not来组织你的逻辑。但不允许andor同时出现的条件语句中。新版本中已经支持{% elif %}这样的用法。
  3. 2、{% ifequal %}和{% ifnotequal %}
  4. 比较是否相等,只限于简单的类型,比如字符串,整数,小数的比较,列表,字典,元组不支持。
  5. 3、{% for %}
  6. 用来循环一个list,还可以使用resersed关键字来进行倒序遍历,一般可以用if语句来先判断一下列表是否为空,再进行遍历;还可以使用empty关键字来进行为空时候的跳转。
  7.  
  8. ** for标签中可以使用forloop
  9. a. forloop.counter 当前循环计数,从1开始
  10. b. forloop.counter0 当前循环计数,从0开始,标准索引方式
  11. c. forloop.revcounter 当前循环的倒数计数,从列表长度开始
  12. d. forloop.revcounter0 当前循环的倒数计数,从列表长度减1开始,标准
  13. e. forloop.first bool值,判断是不是循环的第一个元素
  14. f. forloop.last 同上,判断是不是循环的最后一个元素
  15. g. forloop.parentloop 用在嵌套循环中,得到parent循环的引用,然后可以使用以上的参数
  16. 4、{% cycle %}
  17. 在循环时轮流使用给定的字符串列表中的值。
  18. 5、{# #} 单行注释,{% comment %}多行注释
  19. 6、{% csrf_token %}
  20. 生成csrf_token的标签,用于防止跨站攻击验证。
  21. 7、{% debug %}
  22. 调用调试信息
  23. 8、{% filter %}
  24. filter 标签圈定的内容执行过滤器操作。
  25. 9、{% autoescape %}
  26. 自动转义设置
  27. 10、{% firstof %}
  28. 输出第一个值不等于False的变量
  29. 11、{% load %}
  30. 加载标签库
  31. 12、{% now %}
  32. 获取当前时间
  33. 13、{% spaceless %}
  34. 移除空格
  35. 14、{% url %}
  36. 引入路由配置的地址
  37. 15、{% verbatim %}
  38. 禁止render
  39. 16、{% with %}
  40. 用更简单的变量名缓存复杂的变量名

更多常用标签

(4)内置过滤器

  1. {{ item.event_start|date:"Y-m-d H:i:s"}}
  2. {{ bio|truncatewords:"30" }}
  3. {{ my_list|first|upper }}
  4. {{ name|lower }}
  5. {{ obj | safe }}
  6. {% autoescape off %}
  7. {{ obj }}
  8. {% endautoescape %}
  9. {% csrf_token %} # 提交表单的时候需要加上否则django中间件会报csrf错误

其他常用内置过滤器

  1. 0datedate:"F j Y",data过滤器通过使用"F j Y"这几个参数来格式化日期数据。
  2. 1add:给变量加上响应的值
  3. 2addslashes:给变量中的引号前加上斜线
  4. 3capfirst:首字母大写
  5. 4cut:从字符串中移除指定的字符
  6. 5date:格式化日期字符串
  7. 6default:如果值是False,就替换成设置的默认值,否则就使用本来的值
  8. 7default_if_none:如果值是None,就替换成设置的默认值,否则就使用本来的值
  9. 8dictsort:按照设定参数(key)对应的value对列表进行排序
  10. 9dictsortreversed:和上面恰好相反
  11. 10divisibleby:是否能够被某个数字整除,是的话返回True,否则返回False
  12. 11escape:对字符串进行转义
  13. 12escapejs:替换value中的某些字符,以适应JAVASCRIPTJSON格式
  14. 13filesizeformat:格式化文件大小显示
  15. 14first:返回列表中的第一个值
  16. 15last:返回列表中最后一个值
  17. 16floatformat:格式化浮点数
  18. 17length:求字符串或者列表长度
  19. 18length_is:比较字符串或者列表的长度
  20. 19urlencode:对URL进行编码处理
  21. 20upper\lower:大写\小
  22. 21safe:对某个变量关闭自动转义
  23. 22slice:切片操作
  24. 23time:格式化时间
  25. 24timesince:格式化时间 (e.g., 4 days, 6 hours”).
  26. 25truncatechars:按照字符截取字符串
  27. 26truncatewords:按照单词截取字符串
  28. 27striptags:过滤掉html标签

其他常用内置过滤器

(5)自定义方法filter或者simple_tag

filter和simple_tag的区别:

  filter:限制传参2个,支持 if 条件

  simple_tag:不限制传参,不支持 if 条件

官网:https://docs.djangoproject.com/en/1.11/howto/custom-template-tags/

1、在app01中创建templatetags模块(templatetags名字是不能变)

2、创建任意 .py 文件,如:mysimple.py

  1. from django import template
  2. from django.utils.safestring import mark_safe
  3.  
  4. register = template.Library() # 这一句一定是这样写的
  5.  
  6. @register.simple_tag
  7. def my_simple_time(v1,v2,v3):
  8. '''传递多个参数'''
  9. return v1 + v2 + v3
  10.  
  11. @register.simple_tag
  12. def my_input(id,arg):
  13. result = "<input type='text' id='%s' class='%s' />" %(id,arg,)
  14. return mark_safe(result)
  15.  
  16. @register.filter
  17. def f1(value):
  18. return value + '1000'
  19.  
  20. @register.filter
  21. def f2(value,arg):
  22. '''传递一个参数'''
  23. return value + '1000' + arg
  24.  
  25. @register.filter
  26. def f3(value):
  27. if value == 'vvv':
  28. return True
  29. else:
  30. return False

3、在使用自定义simple_tag的html文件中导入之前创建的 mysimple.py 文件名

  1. {% load mysimple %}

4、使用simple_tag和filter,它们使用是不一样的

  1. {% my_simple_time 1 2 3%} # 可以传递多个参数
  2. {% my_input 'id_username' 'hide'%}
  3. {{ k1 | f1 }}
  4. {{ k1 | f2:'python' }} # 只能传递一个参数
  5. {% if k1 | f3 %}
  6. <h1>True</h1>
  7. {% else %}
  8. <h1>False</h1>
  9. {% endif %}

5、在settings中配置当前app,不然django无法找到自定义的simple_tag  

  1. INSTALLED_APPS = (
  2. 'django.contrib.admin',
  3. 'django.contrib.auth',
  4. 'django.contrib.contenttypes',
  5. 'django.contrib.sessions',
  6. 'django.contrib.messages',
  7. 'django.contrib.staticfiles',
  8. 'app01',
  9. )

(六)模板继承

  1. 母板:{% block title %}{% endblock %}
  2. 子板:{% extends "base.html" %}
  3.   {% include "xx.html" %} # 在子板中使用其他模板
  4.    {% block title %}{% endblock %}
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title></title>
  6. <link rel="stylesheet" href="..." />
  7. <style>
  8. .pg-header{
  9. height: 48px;
  10. background-color: cadetblue;
  11. }
  12. .pg-body{
  13. min-height: 500px;
  14. }
  15. .pg-body .body-menu{
  16. width: 20%;
  17. float: left;
  18. }
  19. .pg-body .body-content{
  20. width: 80%;
  21. float: left;
  22. }
  23. .pg-footer{
  24. height: 100px;
  25. background-color: brown;
  26. }
  27. .active{
  28. background-color: aquamarine;
  29. color: white;
  30. }
  31. </style>
  32.  
  33. {% block css %}{% endblock %}
  34. </head>
  35. <body>
  36. <div class="pg-header">
  37. 后台系统V1
  38. </div>
  39. <div class="pg-body">
  40. <div class="body-menu">
  41. <ul>
  42. <li><a id="userinfo" href="/userinfo">用户管理</a></li>
  43. <li><a id="assets" href="/assets">资产管理</a></li>
  44. </ul>
  45. </div>
  46. <div class="body-content">
  47. {% block body %}{% endblock %}
  48. </div>
  49.  
  50. </div>
  51. <div class="pg-footer"></div>
  52. <script src="xxx"></script>
  53. {% block js %}{% endblock %}
  54. </body>
  55. </html>

layout.html

  1. {% extends 'layout.html' %}
  2.  
  3. {% block body %}
  4. {% include 'xx.html' %}
  5. <table>
  6. {% for item in assets_list %}
  7. <tr>
  8. <td>{{ item.hostname }}</td>
  9. <td>{{ item.port }}</td>
  10. </tr>
  11. {% endfor %}
  12. </table>
  13. {% endblock %}
  14.  
  15. {% block js %}
  16. <script>
  17. document.getElementById('assets').className = 'active';
  18. </script>
  19. {% endblock %}

assets.html

  1. {% extends 'layout.html' %}
  2.  
  3. {% block css %}
  4. <style></style>
  5. {% endblock %}
  6.  
  7. {% block body %}
  8. {% include 'xx.html' %}
  9. <ul>
  10. {% for item in user_list %}
  11. <li>{{ item.username }},{{ item.salary }}</li>
  12. {% endfor %}
  13. </ul>
  14.  
  15. {% endblock %}
  16.  
  17. {% block js %}
  18. <script>
  19. document.getElementById('userinfo').className = 'active';
  20. </script>
  21. {% endblock %}

userinfo.html

  1. <form>
  2. <input type="text" placeholder="请输入内容"/>
  3. <input type="text" placeholder="请输入内容"/>
  4. <input type="text" placeholder="请输入内容"/>
  5. <input type="text" placeholder="请输入内容"/>
  6. </form>

xx.html

  1. from django.shortcuts import render,HttpResponse
  2.  
  3. # Create your views here.
  4.  
  5. USER_LSIT = []
  6.  
  7. for item in range(94):
  8. temp = {"id":item, "ip":"192.168.1." + str(item),"username":"user" + str(item)}
  9. USER_LSIT.append(temp)
  10.  
  11. def index(request,page):
  12. page = int(page)
  13. start = (page - 1) * 10
  14. end = page * 10
  15. user_list = USER_LSIT[start:end]
  16. return render(request,'index.html',{'user_list':user_list})
  17.  
  18. def detail(request,nid):
  19. nid = int(nid)
  20. current_detail_dict = USER_LSIT[nid]
  21. return render(request,"detail.html",{"current_detail_dict":current_detail_dict})
  22.  
  23. def assets(request):
  24. assets_list = []
  25. for i in range(10):
  26. temp = {'hostname':'192.168.1.'+str(i),'port':80}
  27. assets_list.append(temp)
  28.  
  29. return render(request,'assets.html',{'assets_list':assets_list})
  30.  
  31. def userinfo(request):
  32. user_list = []
  33. for i in range(10):
  34. temp = {'username': 'user' + str(i),'salary':80}
  35. user_list.append(temp)
  36.  
  37. return render(request,'userinfo.html',{'user_list':user_list})

views

  1. from django.conf.urls import url
  2. from django.contrib import admin
  3. from cmdb import views
  4.  
  5. urlpatterns = [
  6. url(r'^admin/', admin.site.urls),
  7. url(r'^assets/', views.assets),
  8. url(r'^userinfo/', views.userinfo),
  9. ]

urls

更多官网模板介绍:

https://docs.djangoproject.com/en/1.11/ref/templates/builtins/

https://docs.djangoproject.com/en/1.11/ref/templates/builtins/#extends

https://docs.djangoproject.com/en/1.11/ref/templates/builtins/#block

https://docs.djangoproject.com/en/1.11/ref/templates/builtins/#include

六、Model详解

1、django默认支持sqlite、mysql、oracle、postgresql数据库,像db2和sqlserver之类的数据库需要第三方的支持。具体详见:

2、mysql驱动程序:

  1. MySQLdbmysql-python):https://pypi.python.org/pypi/MySQL-python/1.2.5(支持python2)
  2. mysqlclienthttps://pypi.python.org/pypi/mysqlclient (支持python3)
  3. MySQL Connector/Python https://dev.mysql.com/downloads/connector/python
  4. PyMySQL(纯pythonmysql驱动):https://pypi.python.org/pypi/PyMySQL (python3中使用,常用)

3、model配置步骤:

  1. 1、创建数据库
  2. >> CREATE DATABASE IF NOT EXISTS testdb DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
  3. 2、配置文件settings里连接数据库
  4. INSTALLED_APPS = [
  5. .......
  6. 'app02',
  7. 'app01',
  8. ]
  9. DATABASES = {
  10. 'default': {
  11. 'ENGINE': 'django.db.backends.mysql’,#注意改成mysql后台
  12. 'NAME': 'hello_django_db',
  13. 'USER':'root',
  14. 'PASSWORD':'123456’,#就是连接mysql的密码
  15. #'HOST':'',
  16. #'PORT':'',
  17. }
  18. }
  19. 3、和项目project同名的__init__
  20. import pymysql
  21. pymysql.install_as_MySQLdb()
  22. 4、创建model,继承自models.Model
  23. name = models.CharField(max_length=50)
  24. 5、同步数据库
  25. python manage.py makemigrations
  26. python manage.py migrate

(一)、使用原生SQL

到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞:

  • 创建数据库,设计表结构和字段
  • 使用 MySQLdb 来连接数据库,并编写数据访问层代码
  • 业务逻辑层去调用数据访问层执行数据库操作
  1. import pymysql
  2.  
  3. def GetList(sql):
  4. db = pymysql.connect(user='root', db='wupeiqidb', passwd='', host='localhost')
  5. cursor = db.cursor()
  6. cursor.execute(sql)
  7. data = cursor.fetchall()
  8. db.close()
  9. return data
  10.  
  11. def GetSingle(sql):
  12. db = pymysql.connect(user='root', db='wupeiqidb', passwd='', host='localhost')
  13. cursor = db.cursor()
  14. cursor.execute(sql)
  15. data = cursor.fetchone()
  16. db.close()
  17. return data

通过pymysql操作数据库

(二)、使用Django的ORM

django为使用一种新的方式,即:关系对象映射(Object Relational Mapping,简称ORM)。

  PHP:activerecord

  Java:Hibernate

  C#:Entity Framework

django中遵循 Code Frist 的原则,即:根据代码中定义的类来自动生成数据库表。

1、创建Model,之后可以根据Model来创建数据库表

  1. from django.db import models
  2.  
  3. class userinfo(models.Model):
  4. name = models.CharField(max_length=30)
  5. email = models.EmailField()
  6. memo = models.TextField()

更多字段:  

  1. 1models.AutoField  自增列 = int(11)
  2.   如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True
  3. 2models.CharField  字符串字段
  4.   必须 max_length 参数
  5. 3models.BooleanField  布尔类型=tinyint(1)
  6.   不能为空,Blank=True
  7. 4models.ComaSeparatedIntegerField  用逗号分割的数字=varchar
  8.   继承CharField,所以必须 max_lenght 参数
  9. 5models.DateField  日期类型 date
  10.   对于参数,auto_now = True 则每次更新都会更新这个时间;auto_now_add 则只是第一次创建添加,之后的更新不再改变。
  11. 6models.DateTimeField  日期类型 datetime
  12.   DateField的参数
  13. 7models.Decimal  十进制小数类型 = decimal
  14.   必须指定整数位max_digits和小数位decimal_places
  15. 8models.EmailField  字符串类型(正则表达式邮箱) =varchar
  16.   对字符串进行正则表达式
  17. 9models.FloatField  浮点类型 = double
  18. 10models.IntegerField  整形
  19. 11models.BigIntegerField  长整形
  20.   integer_field_ranges = {
  21.     'SmallIntegerField': (-32768, 32767),
  22.     'IntegerField': (-2147483648, 2147483647),
  23.     'BigIntegerField': (-9223372036854775808, 9223372036854775807),
  24.     'PositiveSmallIntegerField': (0, 32767),
  25.     'PositiveIntegerField': (0, 2147483647),
  26.   }
  27. 12models.IPAddressField  字符串类型(ip4正则表达式),django1.10逐步废弃使用下面一种
  28. 13models.GenericIPAddressField  字符串类型(ip4ip6是可选的)
  29.   参数protocol可以是:bothipv4ipv6
  30.   验证时,会根据设置报错
  31. 14models.NullBooleanField  允许为空的布尔类型
  32. 15models.PositiveIntegerFiel  正Integer
  33. 16models.PositiveSmallIntegerField  正smallInteger
  34. 17models.SlugField  减号、下划线、字母、数字
  35. 18models.SmallIntegerField  数字
  36.   数据库中的字段有:tinyintsmallintintbigint
  37. 19models.TextField   字符串=longtext
  38. 20models.TimeField   时间 HH:MM[:ss[.uuuuuu]]
  39. 21models.URLField   字符串,地址正则表达式
  40. 22models.BinaryField  二进制
  41. 23models.ImageField 图片,需要max_length
  42. 24models.FilePathField 文件,需要max_length

更多参数:

  1. 1null=True # 数据库中字段是否可以为空
  2. 2blank=True # django的 Admin 中添加数据时是否可允许空值
  3. 3primary_key = False #主键,对AutoField设置主键后,就会代替原来的自增 id 列
  4. 4auto_nowauto_now_add
  5.   auto_now # 自动创建---无论添加或修改,都是当前操作的时间
  6.   auto_now_add # 自动创建---永远是创建时的时间
  7. 5choices
  8. GENDER_CHOICE = (
  9. (u'M', u'Male'),
  10. (u'F', u'Female'),
  11. )
  12. gender = models.CharField(max_length=2,choices = GENDER_CHOICE)
  13.  
  14. gender_choice = (
    (0,'男'),
    (1,'女'),
    )
    gender = models.IntergetFiled(choice=gener_choice) # 数据库中存储的是0,1但是显示的是男,女
  15. 6max_length # 在charfield必须指定最大长度
  16. 7default   # 默认值
  17. 8verbose_name   # Admin中字段的显示名称
  18. 9name|db_column  # 数据库中的字段名称
  19. 10unique=True   # 不允许重复
  20. 11db_index = True  # 数据库索引
  21. 12editable=True   # 在Admin里是否可编辑
  22. 13error_messages=None  # 在Admin错误提示
  23. 14auto_created=False   # 自动创建
  24. 15help_text   # 在Admin中提示帮助信息
  25. 16validators=[] # 自定义规则
  26. 17upload-to # 指定上传的路径
    18class Meta():
    verbose_name = '这张表的名字在admin后台的显示名字'
    verbose_name_plural = verbose_name
    ordering = ['-id'] # 根据id反向排序

2、数据库操作

增加:create()、bulk_create()

  1. # create 第一种方式
  2. models.类名.objects.create(hostname="name")
  3.  
  4. # create 第二种方式,推荐这种
  5. models.类名.objects.create(**{"hostname":"name"})
  6.  
  7. # save 第三种方式
  8. obj = 类名(hostname="name")
  9. obj.save()
  10.  
  11. # save 第四种方式,其实和第三种是一样的,推荐第二种
  12. obj = 类名()
  13. obj.hostname = "name"
  14. obj.save()
  15.  
  16. 注意:hostname是数据库中的字段名,name是值
  17.  
  18. # bulk_create() 批量创建数据
  19. models.类名.objexts.bulk_create([
  20. 类名(字段=值),
  21. 类名(字段=值),
  22. ])

更新:update()

  1. # 第一种方式,推荐这种,而且高效
  2. models.类名.objects.filter(id=2).update(hostname='tomcat')
  3.  
  4. # 第二种方式
  5. obj = models.类名.objects.get(id=2)
  6. obj.hostname = 'tomcat'
  7. obj.save()

第二种方式修改不能用get的原因是:update是QuerySet对象的方法,get返回的是一个model对象,它没有update方法,而filter返回的是一个QuerySet对象(filter里面的条件可能有多个条件符合,比如name='alvin',可能有两个name='alvin'的行数据)

删除:delete()

  1. models.类名.objects.get(id=2).delete() # 不建议
  2. models.类名.objects.filter(id=2).delete()
  3. models.类名.objects.all().delete()

查询:

filter() 集合queryset对象

all(), 集合queryset对象

get(),获取单条数据,不存在就报错

getlist()用于取多个值

  1. models.类名.objects.get(id=123) # 获取单条数据,不存在则报错(不建议),
  2. models.类名.objects.all() # 获取全部
  3. models.类名.objects.filter(name='tomcat') # 获取指定条件的数据

显示指定字段:values(),values_list()

  1. models.类名.objects.get(id=123).values('id','name') # 返回的是queryset字典
  2. models.类名.objects.get(id=123).values__list('id','name') # 返回的是queryset元组

复杂查询:Q()表达式:

https://docs.djangoproject.com/en/1.11/topics/db/queries/#complex-lookups-with-q-objects

数量:count()

  1. models.类名.objects.filter(name='tomcat').count()
  2. models.类名.objects.get(name='tomcat').count()
  3. models.类名.objects.all().count()

去重:distinct()

  1. models.类名.objects.values('字段').distinct()

大于小于:__gt,__lt,__gte,__lte

  1. models.类名.objects.filter(id__gt=1) # 获取id大于1的值
  2. models.类名.objects.filter(id__lt=10) # 获取id小于10的值
  3. models.类名.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值

等于多个值:__in

  1. models.类名.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据
  2. models.类名.objects.exclude(id__in=[11, 22, 33]) # not in

模糊查询:__contains,__icontains  

  1. models.类名.objects.filter(name__contains="ven")
  2. models.类名.objects.filter(name__icontains="ven") # icontains大小写不敏感
  3. models.类名.objects.exclude(name__icontains="ven")

范围查询:__range

  1. models.类名.objects.filter(id__range=[1, 2]) # 范围bettwen and

其他类似:__startswith,__endswith, __iendswith, __istartswith  

排序:order_by("name") 相当于asc;order_by("-name") 相当于desc;  

  1. models.类名.objects.filter(name='seven').order_by('id') # asc,从小到大
  2. models.类名.objects.filter(name='seven').order_by('-id') # desc,从大到小

返回第n-m条:第n条[0];前两条[0:2]  

  1. # limit 、offset
  2.  
  3. models.类名.objects.all()[10:20]

分组与聚合:group_by,annotate,aggregate

annotate(*args, **kwargs):可以为 QuerySet 中的每个对象添加注解。可以通过计算查询结果中每个对象所关联的对象集合,从而得出总计值(也可以是平均值或总和,等等)
aggregate(*args, **kwargs):通过对 QuerySet 进行计算,返回一个聚合值的字典。 aggregate() 中每个参数都指定一个包含在字典中的返回值。用于聚合查询
  • Avg(返回所给字段的平均值)
  • Count(根据所给的关联字段返回被关联 model 的数量)
  • Max(返回所给字段的最大值)
  • Min(返回所给字段的最小值)
  • Sum(计算所给字段值的总和)
  1. # group by
  2. from django.db.models import Count, Min, Max, Sum
  3. # models.类名.objects.filter(c1=1).values('id').annotate(c=Count('num'))
  4. # SELECT "app01_类名"."id", COUNT("app01_类名"."num") AS "c" FROM "app01_类名" WHERE "app01_类名"."c1" = 1 GROUP BY "app01_类名"."id"

更多实例:

  1. >>> Publisher.objects.filter(name='广东人民出版社').aggregate(Count('name'))
  2.  
  3. 还可以自定义别名
  4. >>> Publisher.objects.filter(name='广东人民出版社').aggregate(mycount = Count('name'))
  5.  
  6. 查询胡大海出的书的总价格是多少
  7. >>> Book.objects.filter(authors__name='胡大海').aggregate(Sum('price'))
  8.  
  9. 查询各个作者出的书的总价格是多少
  10. >>> Book.objects.values('authors__name').annotate(Sum('price'))
  11.  
  12. 查询各个出版社最便宜的书价是多少
  13. >>> Book.objects.values('publisher__name').annotate(Min('price'))

更多:

https://docs.djangoproject.com/en/1.11/topics/db/aggregation/

https://docs.djangoproject.com/en/1.11/topics/db/annotate/

原始SQL:

注意:使用原生sql的方式主要目的是解决一些很复杂的sql,不能用ORM的方式写出的问题。
  • extra:结果集修改器 - 一种提供额外查询参数的机制
  • raw:执行原始sql并返回模型实例,最适合用于查询,(异常:Raw query must include the primary key,返回结果必须包含主键)
  • 直接执行自定义SQL(这种方式完全不依赖model,前面两种方式还是要依赖于model),适合增删改
  1. A.使用extra
  2. >>> Book.objects.filter(publisher__name='广东人民出版社').extra(where=['price>50’])
  3. >>> Book.objects.filter(publisher__name='广东人民出版社', price__gt=50)
  4. >>> Book.objects.extra(select={'count':'select count(*) from hello_book'})
  5.  
  6. B.使用raw:
  7. >>> Book.objects.raw('select * from hello_book')
  8.  
  9. C.自定义sql:
  10. from django.db import connection
  11. cursor = connection.cursor() #获得一个游标(cursor)对象
  12.  
  13. cursor.execute("insert into hello_author(name) values('郭敬明')") #插入操作
  14. cursor.execute("update hello_author set name = '韩寒' where name='郭敬明'") #更新操作
  15. cursor.execute("delete from hello_author where name='韩寒'") #删除操作
  16. cursor.execute('select * from hello_author') #查询操作
  17. raw = cursor.fetchone() #返回结果行
  18. cursor.fetchall()
更多详见:
https://docs.djangoproject.com/en/1.11/topics/db/sql/
 
自定义Manager:
https://docs.djangoproject.com/en/1.11/topics/db/managers/

3、连表操作:

  • 一对多,models.ForeignKey('UserType')
  • 一对一,models.OneToOneField('UserType',on_delete=models.SET_NULL)
  • 多对多,models.ManyToManyField('UserType',on_delete=models.CASCADE)

应用场景:

  • 一对一:在某表中创建一行数据时,有一个单选的下拉框(下拉框中的内容被用过一次就消失了)。
    例如:原有含10列数据的一张表保存相关信息,经过一段时间之后,10列无法满足需求,需要为原来的表再添加5列数据。
  • 一对多:当一张表中创建一行数据时,有一个单选的下拉框(可以被重复选择)。
    例如:创建用户信息时候,需要选择一个用户类型【普通用户】【金牌用户】【铂金用户】等。
  • 多对多:在某表中创建一行数据是,有一个可以多选的下拉框。
    例如:创建用户信息,需要为用户指定多个爱好。

利用双下划线和 _set 将表之间的操作连接起来

  1. from django.db import models
  2.  
  3. class UserProfile(models.Model):
  4. username = models.CharField(max_length=64)
  5. password = models.CharField(max_length=64)
  6. user_info = models.OneToOneField('UserInfo')
  7.  
  8. def __str__(self): # __unicode__ on python2
  9. return self.username
  10.  
  11. class UserInfo(models.Model):
  12. user_type_choice = (
  13. (0, '普通用户'),
  14. (1, '高级用户'),
  15. )
  16. user_type = models.IntegerField(choices=user_type_choice)
  17. name = models.CharField(max_length=32)
  18. email = models.CharField(max_length=32)
  19. address = models.CharField(max_length=128)
  20.  
  21. def __str__(self): # __unicode__ on python2
  22. return self.name
  23.  
  24. class UserGroup(models.Model):
  25.  
  26. caption = models.CharField(max_length=64)
  27.  
  28. user_info = models.ManyToManyField('UserInfo')
  29.  
  30. def __str__(self): # __unicode__ on python2
  31. return self.caption
  32.  
  33. class Host(models.Model):
  34. hostname = models.CharField(max_length=64)
  35. ip = models.GenericIPAddressField()
  36. user_group = models.ForeignKey('UserGroup')
  37.  
  38. def __str__(self): # __unicode__ on python2
  39. return self.hostname

表结构实例:models.py

  1. urlpatterns = [
  2. url(r'^admin/', admin.site.urls),
  3. url(r'^add/', views.addata),
  4. url(r'^danbiao/', views.danbiao),
  5. url(r'^yiduiyi/', views.yiduiyi),
  6. url(r'^yiduiduo/', views.yiduiduo),
  7. url(r'^duoduiduo/', views.duoduiduo),
  8. ]

urls.py

  1. def addata(request):
  2.  
  3. # 批量插入UserInfo表
  4. models.UserInfo.objects.bulk_create([
  5. UserInfo(user_type=0, name='Shi Zhongyu', email='shizhongyu@163.com', address='深圳市'),
  6. UserInfo(user_type=0, name='Sun Dasheng', email='sundasheng@163.com', address='佛山市'),
  7. UserInfo(user_type=0, name='Lin Daiyu', email='lindaiyu@163.com', address='揭阳市'),
  8. UserInfo(user_type=0, name='Lin Chong', email='linchong@163.com', address='中山市'),
  9. UserInfo(user_type=0, name='Ma Chao', email='machao@126.com', address='福州市'),
  10. UserInfo(user_type=0, name='Xie Yanke', email='xieyanke@126.com', address='厦门市'),
  11. UserInfo(user_type=0, name='Xiao Qiao', email='xiaoqiao@yahoo.com', address='漳州市'),
  12. UserInfo(user_type=0, name='Tian Boguang', email='tianboguang@qq.com', address='龙岩市'),
  13. UserInfo(user_type=0, name='Yuan Chengzhi', email='yuanchengzhi@qq.com', address='北京市'),
  14. UserInfo(user_type=0, name='Ren Yingying', email='renyingying@360.com', address='上海市'),
  15. UserInfo(user_type=0, name='Diao Chan', email='diaochan@baidu.com', address='南京市'),
  16. UserInfo(user_type=0, name='Lu Wushuang', email='luwushuang@ali.com', address='青岛市'),
  17. UserInfo(user_type=0, name='Xue Baochai', email='xuebaochai@live.com', address='浙江市'),
  18. UserInfo(user_type=1, name='Xiao Dasheng', email='xiaodasheng@gmail.com', address='伊拉克'),
  19. ])
  20.  
  21. # 批量插入UserProfile表
  22. userprofile_list = []
  23. for i in range(1,16):
  24. username = 'zhanghao' + str(i)
  25. password = ''
  26. userinfo = i
  27. uprofile = models.UserProfile(username=username,password=password,userinfo=userinfo)
  28. userprofile_list.append(uprofile)
  29. models.UserProfile.objects.bulk_create(userprofile_list)
  30.  
  31. # 批量插入UserGroup表
  32. models.UserGroup.objects.bulk_create([
  33. UserInfo(capation='CTO'),
  34. UserInfo(capation='CEO'),
  35. UserInfo(capation='COO'),
  36. ])
  37.  
  38. # 批量插入Host表
  39. models.Host.objects.bulk_create([
  40. UserInfo(hostname='c1.salt.com',ip='192.168.1.1',user_group_id=1),
  41. UserInfo(hostname='c2.salt.com',ip='192.168.1.2',user_group_id=1),
  42. UserInfo(hostname='c3.salt.com',ip='192.168.1.3',user_group_id=1),
  43. UserInfo(hostname='c4.salt.com',ip='192.168.1.4',user_group_id=1),
  44. UserInfo(hostname='c5.salt.com',ip='192.168.1.5',user_group_id=1),
  45. UserInfo(hostname='c6.salt.com',ip='192.168.1.6',user_group_id=2),
  46. UserInfo(hostname='c7.salt.com',ip='192.168.1.7',user_group_id=2),
  47. UserInfo(hostname='c8.salt.com',ip='192.168.1.8',user_group_id=2),
  48. UserInfo(hostname='c9.salt.com',ip='192.168.1.9',user_group_id=2),
  49. UserInfo(hostname='c10.salt.com',ip='192.168.1.10',user_group_id=2),
  50. UserInfo(hostname='c11.salt.com',ip='192.168.1.11',user_group_id=3),
  51. UserInfo(hostname='c12.salt.com',ip='192.168.1.12',user_group_id=3),
  52. UserInfo(hostname='c13.salt.com',ip='192.168.1.13',user_group_id=3),
  53. UserInfo(hostname='c14.salt.com',ip='192.168.1.14',user_group_id=3),
  54. UserInfo(hostname='c15.salt.com',ip='192.168.1.15',user_group_id=3),
  55. ])
  56.  
  57. return render(request,'addata.html')

增加数据:views.py

多对多那张表可以自己在数据库插入数据,所有html都是空的

  1. def danbiao(request):
  2.  
  3. # filter是querset对象,所以要迭代取出值
  4. queryset = models.UserInfo.objects.filter(name='user')
  5. print(queryset.query)
  6. print(type(queryset))
  7. for item in queryset:
  8. print(item.id)
  9. print(item.user_type)
  10. print(item.name)
  11. print(item.email)
  12. print(item.address)
  13.  
  14. # get是userinfo类对象,不需要迭代取值,直接取
  15. obj = models.UserInfo.objects.get(id=10)
  16. print(type(obj))
  17. print(obj.id)
  18. print(obj.name)
  19. print(obj.user_type)
  20. print(obj.email)
  21. print(obj.address)
  22.  
  23. # values也是queryset对象,需要迭代取值,values是字典
  24. obj1 = models.UserInfo.objects.filter(name='redhat').values('id','name')
  25. print(type(obj1))
  26. for i in obj1:
  27. print(i['id'])
  28. print(i['name'])
  29.  
  30. # values_list也是queryset对象,需要迭代取值,values_list元组
  31. obj2 = models.UserInfo.objects.filter(name='centos').values_list('id','name')
  32. print(type(obj2))
  33. for i in obj2:
  34. print(i[0])
  35. print(i[1])
  36.  
  37. obj3 = models.UserInfo.objects.all()
  38. print(type(obj3))
  39. for iter in obj3:
  40. print(iter.id)
  41. print(iter.name)
  42.  
  43. return render(request,'danbiao.html',locals())

单表操作:views.py

  1. def yiduiyi(request):
  2.  
  3. # 正向查询
  4. u_profile = models.UserProfile.objects.all()
  5. for i in u_profile:
  6. print(i.id)
  7. print(i.username)
  8. print(i.password)
  9. print(i.user_info.get_user_type_display())
  10. print(i.user_info.name)
  11. print(i.user_info.email)
  12. print(i.user_info.address)
  13.  
  14. # 正向连表查询
  15. u_profile1 = models.UserProfile.objects.values('username','password','user_info__user_type','user_info__name')
  16. for i in u_profile1:
  17. print(i['username'])
  18.  
  19. obj = models.UserProfile.objects.values('username','password','user_info__user_type','user_info__name').first()
  20. print(obj['username'])
  21. print(obj['password'])
  22. print(obj['user_info__user_type'])
  23. print(obj['user_info__name'])
  24.  
  25. # 反向查询userprofile表
  26. user_info_obj = models.UserInfo.objects.filter(id=1).first()
  27. print(type(user_info_obj))
  28. print(user_info_obj.user_type)
  29. print(user_info_obj.get_user_type_display())
  30. print(user_info_obj.userprofile.password)
  31.  
  32. # 反向连表查询
  33. user_info_obj1 = models.UserInfo.objects.filter(id=1).values('email', 'userprofile__username').first()
  34. print(type(user_info_obj1))
  35. print(user_info_obj1.keys())
  36. print(user_info_obj1.values())
  37.  
  38. return render(request,'yiduiyi.html',locals())

一对一操作:views.py

  1. def yiduiduo(request):
  2.  
  3. # 正向查询
  4. obj = models.Host.objects.all()
  5. for i in obj:
  6. print(i.id)
  7. print(i.hostname)
  8. print(i.ip)
  9. print(i.user_group.caption)
  10.  
  11. # 正向查询连表操作
  12. obj1 = models.Host.objects.all().values('hostname','user_group__caption').first()
  13. print(obj1)
  14. print(obj1['hostname'])
  15. print(obj1['user_group__caption'])
  16.  
  17. obj2 = models.Host.objects.all().values('hostname','user_group__caption')
  18. print(type(obj2))
  19. for i in obj2:
  20. print(i.keys())
  21. print(i.values())
  22.  
  23. # 反向查询
  24. obj3 = models.UserGroup.objects.all()
  25. print(obj3)
  26. print(type(obj3))
  27. for i in obj3:
  28. print(i.caption)
  29. print(i.host_set.all())
  30. host_obj = i.host_set.all()
  31. for j in host_obj:
  32. print(j.hostname)
  33. print(j.ip)
  34.  
  35. # 反向查询连表操作
  36. obj4 = models.UserGroup.objects.all().values('caption','host__hostname').first()
  37. print(obj4['caption'])
  38. print(obj4['host__hostname'])
  39.  
  40. obj5 = models.UserGroup.objects.all().values('caption','host__hostname')
  41. for i in obj5:
  42. print(i['caption'])
  43. print(i['host__hostname'])
  44.  
  45. # 一对多,三表关联
  46. allobj = models.Host.objects.filter(user_group__user_info__user_type=0)
  47. print(allobj.query)
  48. print(type(allobj))
  49. for i in allobj:
  50. print(i)
  51. print(i.user_group.caption)
  52.  
  53. return render(request,'yiduiduo.html',locals())

一对多:views.py

  1. def duoduiduo(request):
  2.  
  3. # 在关联连表的时候不知道填什么字段,故意填错,django会提示可以填入的字段
  4.  
  5. # 正向添加数据,多对多的第三表存储的是两张表的主键id
  6. user_info_obj = models.UserInfo.objects.get(id=1)
  7. user_info_objs = models.UserInfo.objects.all()
  8. group_obj = models.UserGroup.objects.get(id=1)
  9.  
  10. group_obj.user_info.add(user_info_obj)
  11. group_obj.user_info.add(*user_info_objs)
  12. group_obj.user_info.add(1)
  13. group_obj.user_info.add(*[1,2,4])
  14.  
  15. # 正向删除数据
  16. group_obj.user_info.clear() # 清空所有与第三张表usergroup id=1的所有数据
  17. group_obj.user_info.remove(*[2,3,4]) # 删除,2,3,4条数据
  18.  
  19. # 正向查询数据
  20. group_obj = models.UserGroup.objects.get(id=1)
  21. obj = group_obj.user_info.all()
  22. for i in obj:
  23. print(i.id)
  24. print(i.name)
  25. print(i.email)
  26. print(i.address)
  27. print(i.get_user_type_display())
  28.  
  29. # 正向关联表查询
  30. dic = models.UserGroup.objects.all().values('caption','user_info__name','user_info__address','user_info__email')
  31. print(dic)
  32.  
  33. # 反向添加数据
  34. user_info_obj = models.UserInfo.objects.get(id=1)
  35. group_obj1 = models.UserGroup.objects.get(id=1)
  36. group_obj2 = models.UserGroup.objects.all()
  37. obj2 = user_info_obj.usergroup_set.add(group_obj1)
  38. obj3 = user_info_obj.usergroup_set.add(*group_obj2)
  39. user_info_obj.usergroup_set.add(1)
  40. user_info_obj.usergroup_set.add(*[1,2,3,4])
  41.  
  42. # 反向删除数据
  43. user_info_obj.usergroup_set.clear() # 清空所有第三张表userinfo id=1的所有数据
  44. user_info_obj.usergroup_set.remove(*[2,3,4])
  45.  
  46. # 反向查询
  47. user_info_obj = models.UserInfo.objects.get(id=1)
  48. obj4 = user_info_obj.usergroup_set.all()
  49. print(obj4)
  50. print(type(obj4))
  51. for i in obj4:
  52. print(i.id)
  53. print(i.caption)
  54.  
  55. # 反向连表查询
  56. dic1 = models.UserInfo.objects.all().values('name','email','address','usergroup__caption')
  57. print(dic)
  58.  
  59. return render(request,'duoduiduo.html',locals())

多对多操作:views.py

其他操作中包含:F()和Q查询

  1. # F 使用查询条件的值
  2. #
  3. # from django.db.models import F
  4. # models.Tb1.objects.update(num=F('num')+1)
  5.  
  6. # Q 构建搜索条件
  7. from django.db.models import Q
  8. # con = Q()
  9. #
  10. # q1 = Q()
  11. # q1.connector = 'OR'
  12. # q1.children.append(('id', 1))
  13. # q1.children.append(('id', 10))
  14. # q1.children.append(('id', 9))
  15. #
  16. # q2 = Q()
  17. # q2.connector = 'OR'
  18. # q2.children.append(('c1', 1))
  19. # q2.children.append(('c1', 10))
  20. # q2.children.append(('c1', 9))
  21. #
  22. # con.add(q1, 'AND')
  23. # con.add(q2, 'AND')
  24. #
  25. # models.Tb1.objects.filter(con)
  26.  
  27. #
  28. # from django.db import connection
  29. # cursor = connection.cursor()
  30. # cursor.execute("""SELECT * from tb where name = %s""", ['Lennon'])
  31. # row = cursor.fetchone()

其他操作

注意:xx_set中的【_set】是多对多中的固定搭配,用于反响查询,一对多中反向也可以用_set

自连接F()表达式:

https://docs.djangoproject.com/en/1.9/ref/models/expressions/#

4、扩展:

(1)自定义上传

  1. def upload_file(request):
  2. if request.method == "POST":
  3. obj = request.FILES.get('fafafa')
  4. f = open(obj.name, 'wb')
  5. for chunk in obj.chunks():
  6. f.write(chunk)
  7. f.close()
  8. return render(request, 'file.html')

(2)Form上传文件实例

form.py

  1. class FileForm(forms.Form):
  2. ExcelFile = forms.FileField()

model.py

  1. from django.db import models
  2.  
  3. class UploadFile(models.Model):
  4. userid = models.CharField(max_length = 30)
  5. file = models.FileField(upload_to = './upload/')
  6. date = models.DateTimeField(auto_now_add=True)

view.py

  1. def UploadFile(request):
  2. uf = AssetForm.FileForm(request.POST,request.FILES)
  3. if uf.is_valid():
  4. upload = models.UploadFile()
  5. upload.userid = 1
  6. upload.file = uf.cleaned_data['ExcelFile']
  7. upload.save()
  8.  
  9. print upload.file

更多model相关:https://docs.djangoproject.com/en/1.9/topics/db/models/

七、admin

django amdin是django提供的一个后台管理页面,改管理页面提供完善的html和css,使得你在通过Model创建完数据库表之后,就可以对数据进行增删改查,而使用django admin 则需要以下步骤:

  • 创建后台管理员
  • 配置url
  • 注册和配置django admin后台管理页面
一些常用的设置技巧:
  list_display:指定要显示的字段
  search_fields:指定搜索的字段
  list_filter:指定列表过滤器
  ordering:指定排序字段
  fields\exclude:指定编辑表单需要编辑\不需编辑的字段
  fieldsets:设置分组表单
  filter_horizontal:指定多对多选择
  raw_id_fields:一对多选择

更多:https://docs.djangoproject.com/en/1.11/ref/contrib/admin/

admin基本使用:

1、创建后台管理员

  1. python manage.py createsuperuser
  2. python manage.py changepassword

2、配置后台管理url

  1. url(r'^admin/', include(admin.site.urls))

3、注册和配置django admin 后台管理页面

a、设置数据表名称

  1. class UserType(models.Model):
  2. name = models.CharField(max_length=50,verbose_name='类型的名字')
  3.  
  4. class Meta:
  5. verbose_name = '用户类型'
  6. verbose_name_plural = verbose_name
  7.  
  8. def __str__(self): # __unicode__ on python2
  9. return self.name

b、在admin中执行如下配置

  1. from django.contrib import admin
  2. from app01 import models
  3.  
  4. admin.site.register(models.UserType)

(1)在admin中显示的字段

  1. from django.contrib import admin
  2. from app01 import models
  3.  
  4. class UserInfoAdmin(admin.ModelAdmin):
  5. list_display = ('id','name')
  6.  
  7. admin.site.register(models.UserType,UserInfoAdmin)

(2)为数据表添加搜索功能

  1. from django.contrib import admin
  2. from app01 import models
  3.  
  4. class UserInfoAdmin(admin.ModelAdmin):
  5. list_display = ('id','name')
  6. search_fields = ('name')
  7.  
  8. admin.site.register(models.UserType,UserInfoAdmin)

(3)添加快速过滤、可编辑、分页

  1. from django.contrib import admin
  2. from app01 import models
  3.  
  4. class UserInfoAdmin(admin.ModelAdmin):
  5. list_display = ('id','name')
  6. search_fields = ('name')
  7. list_filter = ('name')
  8. list_editable = ('name')
       list_per_page = 10
  9.  
  10. admin.site.register(models.UserType,UserInfoAdmin)

admin中的action:

models.py
  1. from django.db import models
  2.  
  3. STATUS_CHOICES = (
  4. ('d', 'Draft'),
  5. ('p', 'Published'),
  6. ('w', 'Withdrawn'),
  7. )
  8.  
  9. class Article(models.Model):
  10. title = models.CharField(max_length=100)
  11. body = models.TextField()
  12. status = models.CharField(max_length=1, choices=STATUS_CHOICES)
  13.  
  14. def __str__(self): # __unicode__ on Python 2
  15. return self.title

admin.py

  1. from django.contrib import admin
  2. from myapp.models import Article
  3.  
  4. def make_published(modeladmin, request, queryset):
  5. queryset.update(status='p')
  6. make_published.short_description = "Mark selected stories as published" # 在admin后台action显示的操作
  7.  
  8. class ArticleAdmin(admin.ModelAdmin):
  9. list_display = ['title', 'status']
  10. ordering = ['title']
  11. actions = [make_published] # 将上面定义的action function添加进来
  12.  
  13. admin.site.register(Article, ArticleAdmin)

给状态加上html

  1. from django.db import models
  2. from django.utils.html import format_html
  3.  
  4. STATUS_CHOICES = (
  5. ('d', 'Draft'),
  6. ('p', 'Published'),
  7. ('w', 'Withdrawn'),
  8. )
  9.  
  10. class Article(models.Model):
  11. title = models.CharField(max_length=100)
  12. body = models.TextField()
  13. status = models.CharField(max_length=1, choices=STATUS_CHOICES)
  14.  
  15. def __str__(self): # __unicode__ on Python 2
  16. return self.title
  17.  
  18. def colored_status(self):
  19. if self.status == 'd':
  20. format_td = format_html('<span style="padding:2px;background-color:yellowgreen;color:white">Draft</span>')
  21. elif self.status == 'p':
  22. format_td = format_html('<span style="padding:2px;background-color:green;color:white">Published</span>')
  23. elif self.status == 'w':
  24. format_td = format_html('<span style="padding:2px;background-color:orange;color:white">Withdrawn</span>')
  25.  
  26. return format_td
  27. colored_status.short_description = 'status' # 在admin后台显示字段改名字

models.py

  1. from django.contrib import admin
  2. from myapp.models import Article
  3.  
  4. def make_published(modeladmin, request, queryset):
  5. queryset.update(status='p')
  6. make_published.short_description = "Mark selected stories as published" # 在admin后台action显示的操作
  7.  
  8. class ArticleAdmin(admin.ModelAdmin):
  9. list_display = ['title', 'status','colored_status'] # 这里直接添加一个字段即可
  10. ordering = ['title']
  11. actions = [make_published] # 将上面定义的action function添加进来
  12.  
  13. admin.site.register(Article, ArticleAdmin)

admin.py

更多:https://docs.djangoproject.com/en/1.11/ref/contrib/admin/actions/#writing-actions

Python自动化运维之27、Django(一)的更多相关文章

  1. Python自动化运维:技术与最佳实践 PDF高清完整版|网盘下载内附地址提取码|

    内容简介: <Python自动化运维:技术与最佳实践>一书在中国运维领域将有“划时代”的重要意义:一方面,这是国内第一本从纵.深和实践角度探讨Python在运维领域应用的著作:一方面本书的 ...

  2. 【目录】Python自动化运维

    目录:Python自动化运维笔记 Python自动化运维 - day2 - 数据类型 Python自动化运维 - day3 - 函数part1 Python自动化运维 - day4 - 函数Part2 ...

  3. python自动化运维篇

    1-1 Python运维-课程简介及基础 1-2 Python运维-自动化运维脚本编写 2-1 Python自动化运维-Ansible教程-Ansible介绍 2-2 Python自动化运维-Ansi ...

  4. Day1 老男孩python自动化运维课程学习笔记

    2017年1月7日老男孩python自动化运维课程正式开课 第一天学习内容: 上午 1.python语言的基本介绍 python语言是一门解释型的语言,与1989年的圣诞节期间,吉多·范罗苏姆为了在阿 ...

  5. python自动化运维学习第一天--day1

    学习python自动化运维第一天自己总结的作业 所使用到知识:json模块,用于数据转化sys.exit 用于中断循环退出程序字符串格式化.format字典.文件打开读写with open(file, ...

  6. Python自动化运维的职业发展道路(暂定)

    Python职业发展之路 Python自动化运维工程 Python基础 Linux Shell Fabric Ansible Playbook Zabbix Saltstack Puppet Dock ...

  7. Python自动化运维 技术与最佳实践PDF高清完整版免费下载|百度云盘|Python基础教程免费电子书

    点击获取提取码:7bl4 一.内容简介 <python自动化运维:技术与最佳实践>一书在中国运维领域将有"划时代"的重要意义:一方面,这是国内第一本从纵.深和实践角度探 ...

  8. python自动化运维之CMDB篇-大米哥

    python自动化运维之CMDB篇 视频地址:复制这段内容后打开百度网盘手机App,操作更方便哦 链接:https://pan.baidu.com/s/1Oj_sglTi2P1CMjfMkYKwCQ  ...

  9. python自动化运维之路~DAY5

    python自动化运维之路~DAY5 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.模块的分类 模块,用一砣代码实现了某个功能的代码集合. 类似于函数式编程和面向过程编程,函数 ...

随机推荐

  1. 390. Elimination Game

    正规解法直接跳到代码上面一点的部分就可以了.但我想记录下自己的思考和尝试过程,希望二刷能看到问题所在. 找规律的时候写了好多,虽然规律很简单. 只要随便写3以上的例子,就应该发现,相邻的2个最后结果是 ...

  2. myeclipse svn

    打开myeclipse的help---install from site 点击add弹出对话框 在输入框中输入对应内容 http://subclipse.tigris.org/update_1.10. ...

  3. python google play

    #!/usr/env python #-*- coding: utf-8 -*- import urllib import urllib2 import random import requests ...

  4. Teamcity+SVN+VisualStudio在持续集成简明教程

    Teamcity+SVN+VisualStudio持续集成 简明教程 一.写在最前: 1.      各组件版本号例如以下: Teamcity(简称tc)版本号:8.1.4 SVN版本号:Tortoi ...

  5. C开发之----#if、#ifdef、#if defined之间的区别

    #if的使用说明 #if的后面接的是表达式 #if (MAX==10)||(MAX==20) code... #endif 它的作用是:如果(MAX==10)||(MAX==20)成立,那么编译器就会 ...

  6. Qt 学习之路:QML 组件

    前面我们简单介绍了几种 QML 的基本元素.QML 可以由这些基本元素组合成一个复杂的元素,方便以后我们的重用.这种组合元素就被称为组件.组件就是一种可重用的元素.QML 提供了很多方法来创建组件.不 ...

  7. c#中跨线程调用windows窗体控件

    c#中跨线程调用windows窗体控件解决. 我们在做winform应用的时候,大部分情况下都会碰到使用多线程控制界面上控件信息的问题.然而我们并不能用传统方法来做这个问题,下面我将详细的介绍.首先来 ...

  8. js分家效应

    (原创文章,转载请注明出处) 有继承,那么就有分家.让我们看以下例子. var parents = function(){ } parents.prototype.money = 200; var c ...

  9. 原生JS添加节点方法与jQuery添加节点方法的比较及总结

    一.首先构建一个简单布局,来供下边讲解使用 1.HTML部分代码: <div id="div1">div1</div> <div id="d ...

  10. MEF依赖注入调试小技巧!

    自从哥的项目使用MEF以来,天天那个纠结啊,甭提了.稍有错误,MEF就报错,但就不告诉你哪错了,大爷的. 后来看了MEFX的相关调试方法,感觉也不太理想,根本不够直观的看到错误原因,也许是没有深入学习 ...