视图函数: request对象 request.path 请求路径 request.GET GET请求数据 QueryDict {} request.POST POST请求数据 QueryDict {} request.method 请求方式 "GET" "POST" request.is_ajax() 是不是Ajax请求 request.get_full_path() 包含请求数据的路径 return HttpResponse("响应体字符串") render : 渲染 render(request, "index.html") render(request, "index.html", {"name": name}) redirect : 重定向 两次请求
render没有第3个参数时,直接读取文件;有第3个参数时,判断有没有{}语法,而后替换。css
redirect是服务器向浏览器发送302指令,它是2次请求;form表单提交时,url变更了。由于它必然会发生一次请求!当form表单的action属性为空时,单击提交。它会获取当前url做为action的属性,它和当前url没有任何关系。html
思考题:前端
假设访问的是login,login的视图函数代码为:python
def login(request): return render(request,'login.html')
访问页面是正常的:mysql
若是改成这样呢?git
def login(request): return redirect('/login/')
分析一下:ajax
如今直接访问login页面,看看会不会一直跳转。正则表达式
页面提示:google浏览器提示重定向次数过多sql
Edge浏览器是直接提示数据库
一 变量{{ }} 1 深度查询 2 过滤器 {{ now|date:"Y-m-d" }} {{ file_size:filesizeformat }} {{ link|safe }} 二 标签{% %} 1. {% for i in [] %} {{ forloop.counter }} {{ forloop.last }} {% endfor %} 2. {% if 条件 %} <p>1111</p> {% elif %} <p>2222</p> {% else %} <p>3333</p> {% endif %} 3. with 4. url {% url '别名' 参数 %} 5. {% csrf_token %}
注意:datetime也能够作格式化,好比:
def login(request): import datetime now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") return HttpResponse(now)
访问页面输出:
也就是说,后端能够定义格式,前端也能够定义格式,看你喜欢哪一种。
重点掌握if和for语法,还有csrf_token
标签,是为了作一些功能。过滤器,是对斜杠前面的数据作过滤。
为何要自定义标签和过滤器?由于字典的不够用,须要结合需求,来自定义。
自定义标签和过滤器须要执行3个步骤:
一、在setting中的INSTALLED_APPS配置当前app,否则django没法找到自定义的simple_tag。 二、在app中建立templatetags模块(模块名必须是templatetags) 三、建立任意.py文件,如:my_tags.py
举例:增长一个乘法过滤器
修改settings.py中的INSTALLED_APPS,最后一行添加当前的app。
django开头的,都是一些自带的app。它内置在django源码里面!
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app1.apps.App1Config', ]
在app1目录里面新建一个templateages目录,目录名必须是这个!!!不然django找不到。
目录里面建立my_filter_tag.py这个py文件,能够随便定义。内容以下:
from django import template from django.utils.safestring import mark_safe register = template.Library() @register.filter def multi_filter(x, y): return x * y
注意:头部的3行,是固定写法,不能改变。
增长@register.filter,是为了将函数转换成过滤器。函数的名字,能够自定义。
修改views.py里面的index函数,内容以下:
def index(request): num = 100 return render(request,'index.html',{'num': num})
修改index.html,修改body部分
注意:在使用自定义标签和过滤器,必须在html文件中,导入以前建立的my_filter_tag
{% load my_filter_tag %} <p>{{ num|multi_filter:5 }}</p>
load表示导入模块。p标签中的内容,是执行了multi_filter过滤器。
注意:它接收了2个参数。一个是num,一个是5。由于multi_filter过滤器,定义了2个形参,使用它必须传2个参数才行。
访问index页面,输出:
是由于自定义的模块,没有导入成功,提示找不到!为啥呢?由于django项目启动时,会导入settings定义的模块,因为app1的自定义模块是启动以后加的,因此它并无加载进去。
重启django项目,就能够加载了。再次访问index,页面输出:
若是要完成3个数的乘法呢?过滤器能够增长一个形参,可是index.html怎么加第3个参数呢?
答案是,它不能加第3个参数。因此只能在后端,将参数形式修改为列表、元组、字典等方式,就能够了。
举例1:计算4*5*6
修改index视图函数
def index(request): num1 = 4 num2 = 5 num3 = 6 num_list = [num1,num2,num3] return render(request,'index.html',{'num_list': num_list})
修改my_filter_tag.py中的过滤器
@register.filter def multi_filter(num_list): res = 1 for i in num_list: res *= i return res
修改index.html,修改body部分
{% load my_filter_tag %} <p>{{ num_list|multi_filter }}</p>
访问网页,输出:
举例2:显示a标签
修改my_filter_tag.py文件,增长link_tag过滤器
@register.filter def link_tag(href): return "<a href=%s>click</a>" % href
修改index视图函数
def index(request): link = "http://www.py3study.com/" return render(request,'index.html',{'link': link})
修改index.html,修改body部分
{% load my_filter_tag %} <p>{{ link|link_tag }}</p>
访问网页,输出:
发现结果不是咱们想要的,查看浏览器控制台,查看响应体,发现被转义了
由于django遇到html或者js标签,会转义,它认为是不安全的!那么如何告诉它,是安全的呢?
须要在过滤器中导入make_safe模块
修改my_filter_tag.py文件中的link_tag过滤器,完整代码以下:
使用make_safe方法,告诉django是安全的,不须要转义
from django import template from django.utils.safestring import mark_safe register = template.Library() @register.filter def link_tag(href): return mark_safe("<a href=%s>click</a>" % href)
重启django项目,由于网页有缓存,懒得清理了,因此直接重启django项目,见效快!
再次访问效果就出来了。
标签,是为了作一些功能
举例:4个参数的乘法运算
修改my_filter_tag.py,增长multi_tag函数
@register.simple_tag def multi_tag(x,y,z): return x*y*z
@register.simple_tag表示将函数转换为自定义标签
修改index.html,修改body部分
注意:调用标签,使用{% 标签过滤器名 参数1,参数2,参数3... %}
参数不限,但不能放在if for语句中
{% load my_filter_tag %} <p>{% multi_tag 7 8 9 %}</p>
重启django项目,访问网页,输出:
自定义标签和自定义过滤器的区别:
1. 标签,是为了作一些功能。过滤器,是对斜杠前面的数据作过滤
2. 标签能够写任意个形参,而过滤器最大只能写2个形参。若是过滤器须要接收多个参数,须要将参数存放在列表,元组,字典等数据中。
3. 过滤器能够用在if等语句后,标签不能够
Django模板引擎中最强大也是最复杂的部分就是模板继承了。模板继承可让您建立一个基本的“骨架”模板,它包含您站点中的所有元素,而且能够定义可以被子模版覆盖的blocks。
经过从下面的例子开始,能够容易的理解模板继承:
新建advertise.html,使用Bootstrap构建2个面板
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"> </head> <body> <div class="row"> <div class="col-md-4"> <div class="advertise"> <div class="panel panel-danger"> <div class="panel-heading">菜单一</div> <div class="panel-body"> Panel content </div> </div> <div class="panel panel-success"> <div class="panel-heading">菜单一</div> <div class="panel-body"> Panel content </div> </div> </div> </div> </div> </body> </html>
修改urls.py,增长advertise路径
urlpatterns = [ path('admin/', admin.site.urls), path('index/', views.index), path('advertise/', views.advertise), ]
修改views.py,增长advertise视图函数
def advertise(request): return render(request, 'advertise.html')
访问url:http://127.0.0.1:8000/advertise/
若是首页,也想显示左边的菜单栏呢?代码复制一遍?
这样代码就重复了,使用include,就能够了。
修改advertise.html,将相同的部分分离处理
<div class="row"> <div class="col-md-4"> <div class="advertise"> <div class="panel panel-danger"> <div class="panel-heading">菜单一</div> <div class="panel-body"> Panel content </div> </div> <div class="panel panel-success"> <div class="panel-heading">菜单一</div> <div class="panel-body"> Panel content </div> </div> </div> </div> </div>
修改index.html,使用include导入advertise.html文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"> </head> <body> {% include 'advertise.html' %} </body> </html>
访问首页,效果同上。
访问博客园的我的博客,发现不少页面,有几处相同的部分。好比右侧的侧边栏,顶部的导航栏,尾部部分...等等。那么公共区域,不须要本身重复写,继承下来就能够了!
举例:图书网页
编辑index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"> <style> * { margin: 0; padding: 0; } .header { width: 100%; height: 60px; background-color: #369; } .title { line-height: 60px; color: white; font-weight: 100; margin-left: 20px; font-size: 20px; } .container{ margin-top: 20px; } </style> </head> <body> <div class="header"> <p class="title"> 路飞学诚 </p> </div> <div class="container"> <div class="row"> <div class="col-md-3"> <div class="panel panel-danger"> <div class="panel-heading">菜单一</div> <div class="panel-body"> Panel content </div> </div> <div class="panel panel-success"> <div class="panel-heading">菜单二</div> <div class="panel-body"> Panel content </div> </div> <div class="panel panel-warning"> <div class="panel-heading">菜单三</div> <div class="panel-body"> Panel content </div> </div> </div> <div class="col-md-9"> <div class="jumbotron"> <h1>Hello, INDEX!</h1> <p>...</p> <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p> </div> </div> </div> </div> </body> </html>
访问index页面,输出:
若是要访问子页面,好比书籍管理和做者管理?
修改urls.py,增长articles、authors路径
urlpatterns = [ path('admin/', admin.site.urls), path('index/',views.index), path('articles/',views.articles), path('authors/',views.authors), ]
修改views.py,增长2个视图函数
def articles(request): return render(request, 'articles.html') def authors(request): return render(request, 'authors.html')
新建articles.html,将index.html的代码所有复制粘贴过来,修改中间内容
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"> <style> * { margin: 0; padding: 0; } .header { width: 100%; height: 60px; background-color: #369; } .title { line-height: 60px; color: white; font-weight: 100; margin-left: 20px; font-size: 20px; } .container{ margin-top: 20px; } </style> </head> <body> <div class="header"> <p class="title"> 路飞学诚 </p> </div> <div class="container"> <div class="row"> <div class="col-md-3"> <div class="panel panel-danger"> <div class="panel-heading">菜单一</div> <div class="panel-body"> Panel content </div> </div> <div class="panel panel-success"> <div class="panel-heading">菜单二</div> <div class="panel-body"> Panel content </div> </div> <div class="panel panel-warning"> <div class="panel-heading">菜单三</div> <div class="panel-body"> Panel content </div> </div> </div> <div class="col-md-9"> <div class="article_list"> <ul> <li>红楼梦</li> <li>三国演义</li> <li>西游记</li> <li>水浒传</li> </ul> </div> </div> </div> </div> </body> </html>
访问articles页面,效果以下:
新建authors.html,将index.html的代码所有复制粘贴过来,修改中间内容
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"> <style> * { margin: 0; padding: 0; } .header { width: 100%; height: 60px; background-color: #369; } .title { line-height: 60px; color: white; font-weight: 100; margin-left: 20px; font-size: 20px; } .container{ margin-top: 20px; } </style> </head> <body> <div class="header"> <p class="title"> 路飞学诚 </p> </div> <div class="container"> <div class="row"> <div class="col-md-3"> <div class="panel panel-danger"> <div class="panel-heading">菜单一</div> <div class="panel-body"> Panel content </div> </div> <div class="panel panel-success"> <div class="panel-heading">菜单二</div> <div class="panel-body"> Panel content </div> </div> <div class="panel panel-warning"> <div class="panel-heading">菜单三</div> <div class="panel-body"> Panel content </div> </div> </div> <div class="col-md-9"> <div class="author_list"> <ul> <li>曹雪芹</li> <li>罗贯中</li> <li>吴承恩</li> <li>施耐庵</li> </ul> </div> </div> </div> </div> </body> </html>
访问authors页面,效果以下:
问题来了,菜单和导航,都是重复的。有了继承,就能够解决这个问题。公共部分有,继承的子页面就会哟。没有的部分,子页面也不会有。
这个模板,咱们把它叫作base.html,它定义了一个能够用于两列排版页面的简单HTML骨架。“子模版”的工做是用它们的内容填充空的blocks。
在这个例子中,block标签订义了三个能够被子模版内容填充的block。block告诉模板引擎:子模版可能会覆盖模板中的这些位置。
子模版可能看起来是这样的:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>title</title> <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <style> * { margin: 0; padding: 0; } .header { width: 100%; height: 60px; background-color: #369; } .title { line-height: 60px; color: white; font-weight: 100; margin-left: 20px; font-size: 20px; } .container{ margin-top: 20px; } </style> </head> <body> <div class="header"> <p class="title"> 路飞学诚 </p> </div> <div class="container"> <div class="row"> <div class="col-md-3"> <div class="panel panel-danger"> <div class="panel-heading"><a href="http://127.0.0.1:8008/index/">首页</a></div> <div class="panel-body"> Panel content </div> </div> <div class="panel panel-success"> <div class="panel-heading"><a href="http://127.0.0.1:8008/authors/">做者</a></div> <div class="panel-body"> Panel content </div> </div> <div class="panel panel-warning"> <div class="panel-heading"><a href="http://127.0.0.1:8008/articles/">文章管理</a></div> <div class="panel-body"> Panel content </div> </div> </div> <div class="col-md-9"> {% block content %} {% endblock %} </div> </div> </div> </body> </html>
修改index.html,删除多余的代码。继承base.html
它是先继承,再填充内容。
extends标签是这里的关键,它告诉模板引擎,这个模板“继承”了另外一个模板,当模板系统处理这个模板时,首先,它将定位父模板——在此例中,就是“base.html”。
那时,模板引擎将注意到base.html中的三个block标签,并用子模版中的内容来替换这些block。根据blog_entries的值,输出可能看起来是这样的:
{% extends 'base.html' %} {% block content %} <div class="jumbotron"> <h1>Hello, INDEX!</h1> <p>...</p> <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p> </div> {% endblock %}
访问index页面,效果以下:
修改articles.html,继承base.html
{% extends 'base.html' %} {% block content %} <div class="article_list"> <ul> <li>红楼梦</li> <li>三国演义</li> <li>西游记</li> <li>水浒传</li> </ul> </div> {% endblock %}
访问articles页面,效果以下:
修改authors.html,继承base.html
{% extends 'base.html' %} {% block content %} <div class="author_list"> <ul> <li>曹雪芹</li> <li>罗贯中</li> <li>吴承恩</li> <li>施耐庵</li> </ul> </div> {% endblock %}
访问authors页面,效果以下:
这样,就解决了代码重复问题
需求,访问不一样页面时,更改title标签的属性
怎么作呢?很简单,在base.html里面的title标签位置,定义一个block
在花括号中间的title标签,表示默认值。若是子页面不设置block title,那么显示默认值。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> {% block title %} <title>title</title> {% endblock title %} <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <style> * { margin: 0; padding: 0; } .header { width: 100%; height: 60px; background-color: #369; } .title { line-height: 60px; color: white; font-weight: 100; margin-left: 20px; font-size: 20px; } .container{ margin-top: 20px; } </style> </head> <body> <div class="header"> <p class="title"> 路飞学诚 </p> </div> <div class="container"> <div class="row"> <div class="col-md-3"> <div class="panel panel-danger"> <div class="panel-heading"><a href="http://127.0.0.1:8008/index/">首页</a></div> <div class="panel-body"> Panel content </div> </div> <div class="panel panel-success"> <div class="panel-heading"><a href="http://127.0.0.1:8008/authors/">做者</a></div> <div class="panel-body"> Panel content </div> </div> <div class="panel panel-warning"> <div class="panel-heading"><a href="http://127.0.0.1:8008/articles/">文章管理</a></div> <div class="panel-body"> Panel content </div> </div> </div> <div class="col-md-9"> {% block content %} {% endblock %} </div> </div> </div> </body> </html>
修改articles.html,增长一个block
{% extends 'base.html' %} {% block content %} {{ block.super }} <div class="article_list"> <ul> <li>红楼梦</li> <li>三国演义</li> <li>西游记</li> <li>水浒传</li> </ul> </div> {% endblock %} {% block title %} <title>Article</title> {% endblock %}
访问articles页面,标题就出来了,效果以下:
访问authors页面,因为没有设置block title,它显示默认值,效果以下:
如今有一个问题,右侧内容,写死了。好比文章页中的内容
修改views.py,2个视图,分别增长一个列表
def articles(request): acticle_list = ['红楼梦','三国演义','西游记','水浒传'] return render(request, 'articles.html',{'acticle_list':acticle_list}) def authors(request): author_list = ['曹雪芹','罗贯中','吴承恩','施耐庵'] return render(request, 'authors.html',{'author_list':author_list})
修改articles.html,增长一个for循环
{% extends 'base.html' %} {% block content %} <div class="article_list"> <ul> {% for article in acticle_list %} <li>{{ article }}</li> {% endfor %} </ul> </div> {% endblock %} {% block title %} <title>Article</title> {% endblock %}
修改authors.html,增长一个for循环
{% extends 'base.html' %} {% block content %} <div class="author_list"> <ul> {% for author in author_list %} <li>{{ author }}</li> {% endfor %} </ul> </div> {% endblock %} {% block title %} <title>Author</title> {% endblock %}
从新访问2个页面,效果同上。
请注意,子模板并无定义sidebar block,因此系统使用了父模板中的值。父模板的{% block %}标签中的内容老是被用做备选内容(fallback)。
这种方式使代码获得最大程度的复用,而且使得添加内容到共享的内容区域更加简单,例如,部分范围内的导航。
这里是使用继承的一些提示:
举例:下面这种写法是错误的。extends必须在block上面才行。
{% block content %} <div class="jumbotron"> <h1>Hello, INDEX!</h1> <p>...</p> <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p> </div> {% endblock %} {% extends 'base.html' %}
访问网页,就会报错
好比:base.html虽然定义了2个blocks,authors页面能够只继承一个。
{{ block.super }}
variable will do the trick. This is useful if you want to add to the contents of a parent block instead of completely overriding it. Data inserted using {{ block.super }}
will not be automatically escaped (see the next section), since it was already escaped, if necessary, in the parent template.翻译:
若是您须要从父模板获取块的内容,则{{block.super}}变量将执行该操做。若是你想添加父块的内容而不是彻底覆盖父块的内容,这颇有用。使用{{block.super}}插入的数据不会自动转义(请参阅下一节),由于它已经在父模板中被转义(若有必要)。
举例:
在base.html中block content里面增长一个h3标签。即系统子页面显示h3标签,同时子标签填充block content里面的内容时,h3标签不会被覆盖。加入一个{{ block.super}} 就能够了。
修改base.html,加入h3标签。修改block content部分
{% block content %} <h3>详细内容</h3> {% endblock %}
修改articles.html,在block content下面一行,增长{{ block.super }}
{% extends 'base.html' %} {% block content %} {{ block.super }} <div class="article_list"> <ul> {% for article in acticle_list %} <li>{{ article }}</li> {% endfor %} </ul> </div> {% endblock %} {% block title %} <title>Article</title> {% endblock %}
访问articles页面,效果以下
注意:若是子页面没有写{{ block.super }},那么h3标签就会被覆盖!
{% block content %} ... {% endblock content %}
在大型模板中,这个方法帮你清楚的看到哪个{% block %}标签被关闭了。
好比base.html中的block title,就是遵循这种写法。
需求:如今的页面是手动跳转的,须要点击菜单时,自动跳转页面。
修改base.html,增长3个a标签。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> {% block title %} <title>title</title> {% endblock title %} <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <style> * { margin: 0; padding: 0; } .header { width: 100%; height: 60px; background-color: #369; } .title { line-height: 60px; color: white; font-weight: 100; margin-left: 20px; font-size: 20px; } .container{ margin-top: 20px; } </style> </head> <body> <div class="header"> <p class="title"> 路飞学诚 </p> </div> <div class="container"> <div class="row"> <div class="col-md-3"> <div class="panel panel-danger"> <div class="panel-heading"><a href="/index/">首页</a></div> <div class="panel-body"> Panel content </div> </div> <div class="panel panel-success"> <div class="panel-heading"><a href="/authors/">做者</a></div> <div class="panel-body"> Panel content </div> </div> <div class="panel panel-warning"> <div class="panel-heading"><a href="/articles/">文章管理</a></div> <div class="panel-body"> Panel content </div> </div> </div> <div class="col-md-9"> {% block content %} <h3>详细内容</h3> {% endblock %} </div> </div> </div> </body> </html>
效果以下:
ORM,全称是boject relation mapping。翻译过来,就是对象关系映射。
主要来学习MySQL操做,MySQL是一个软件。它的优势:1.免费 2.开源
pymysql,就是Mysql给python提供的接口。早期的接口叫mysqldb
ORM能够实现不写sql语句,就能够实现操做数据库。
核心是:用python类操做表,用对象操做记录。
ORM把对相应的类和属性操做,转换为sql语句,来操做数据库。它作了一个翻译的过程!
学习ORM,就是用什么语法,能翻译成什么样的sql语句。
看下图:
ORM的优势:
1. 符合python语法。
2. 本身写的sql语句,效率不够高。由于它直接传参,就可使用了。
3. 它不属于硬编码,不针对于MySQL。一样适用于oracle等等数据库。
若是项目中的sql语句写死了,只要一涉及到换数据库,那么项目中的全部sql语句,逗得更换。若是用了ORM,只须要改一处,直接修改settings.py中的数据库引擎,换成oracle,就能够了。这样,方便数据库迭代,这时它最大的优势。
ORM的缺点:
1. 执行效率低。看上图,它是从上层到下层的操做。
它有一个翻译的过程。因此不如直接写sql操做的执行效率高。
可是影响不大。真遇到这种状况,优化SQL就能够了。
效率问题,跟SQL有很大的关系。
如今不关心ORM效率问题。除非SQL语句的造诣达到了必定级别的时候,就须要使用原生SQL语句。
orm还提供了,执行原生SQL的接口。能够直接执行原生SQL。
刚开始写ORM时,必定要对应SQL语句,去写ORM
上图有一个错误,不是DATA而是DATE。
sql中的表
#sql中的表 #建立表: CREATE TABLE employee( id INT PRIMARY KEY auto_increment , name VARCHAR (20), gender BIT default 1, birthday DATA , department VARCHAR (20), salary DECIMAL (8,2) unsigned, ); #sql中的表纪录 #添加一条表纪录: INSERT employee (name,gender,birthday,salary,department) VALUES ("alex",1,"1985-12-12",8000,"保洁部"); #查询一条表纪录: SELECT * FROM employee WHERE age=24; #更新一条表纪录: UPDATE employee SET birthday="1989-10-24" WHERE id=1; #删除一条表纪录: DELETE FROM employee WHERE name="alex" #python的类 class Employee(models.Model): id=models.AutoField(primary_key=True) name=models.CharField(max_length=32) gender=models.BooleanField() birthday=models.DateField() department=models.CharField(max_length=32) salary=models.DecimalField(max_digits=8,decimal_places=2) #python的类对象 #添加一条表纪录: emp=Employee(name="alex",gender=True,birthday="1985-12-12",epartment="保洁部") emp.save() #查询一条表纪录: Employee.objects.filter(age=24) #更新一条表纪录: Employee.objects.filter(id=1).update(birthday="1989-10-24") #删除一条表纪录: Employee.objects.filter(name="alex").delete()
class类的属性和字段是对应的。
decimal(10,2)表示最大长度为10位,小数点2位。那么整数部分,最大只能由8位。
ORM引擎 python ---------------> sql 类名 表名 属性变量 字段 属性值 约束条件 对象 一条记录
好比save(),就能够增长一条记录。因此是对象对应一条记录。
写项目的注意点:
写任何一个项目, 第一件事情,就是产品经理给你提需求。 最关键的时候,了解产品需求,逻辑关系。判断中途是否有bug! 若是作不了,必定要直接说,不能藏着。不然后期拖进度,就麻烦了。 一开始作宏观的梳理,不然后面会出现bug。致使项目推到重构!!! 对于表的设计,要慎重考虑。 早期,会经历不少碰壁的过程,这样你就能成长! 先建立表,分模块来建立表。 到了写代码的时候,反而是最简单的。 好比一个商城项目,设计表,梳理流程,花了2个月。写代码,几个星期就完成了。
默认在应用文件下,有一个models.py文件,好比app01应用。
在app01下的models.py中建立模型:
from django.db import models # Create your models here. class Book(models.Model): id=models.AutoField(primary_key=True) title=models.CharField(max_length=32) state=models.BooleanField() pub_date=models.DateField() price=models.DecimalField(max_digits=8,decimal_places=2) publish=models.CharField(max_length=32)
ORM无法建立数据库,它只能操做表!
类名,首先字母要大写,它必须继承models.Model。这是固定写法!
每一个字段有一些特有的参数,例如,CharField须要max_length参数来指定VARCHAR数据库字段的大小。还有一些适用于全部字段的通用参数。这些参数在文档中有详细定义,这里咱们只简单介绍一些最经常使用的:
更多字段:
<1> CharField 字符串字段, 用于较短的字符串. CharField 要求必须有一个参数 maxlength, 用于从数据库层和Django校验层限制该字段所容许的最大字符数. <2> IntegerField #用于保存一个整数. <3> FloatField 一个浮点数. 必须 提供两个参数: 参数 描述 max_digits 总位数(不包括小数点和符号) decimal_places 小数位数 举例来讲, 要保存最大值为 999 (小数点后保存2位),你要这样定义字段: models.FloatField(..., max_digits=5, decimal_places=2) 要保存最大值一百万(小数点后保存10位)的话,你要这样定义: models.FloatField(..., max_digits=19, decimal_places=10) admin 用一个文本框(<input type="text">)表示该字段保存的数据. <4> AutoField 一个 IntegerField, 添加记录时它会自动增加. 你一般不须要直接使用这个字段; 自定义一个主键:my_id=models.AutoField(primary_key=True) 若是你不指定主键的话,系统会自动添加一个主键字段到你的 model. <5> BooleanField A true/false field. admin 用 checkbox 来表示此类字段. <6> TextField 一个容量很大的文本字段. admin 用一个 <textarea> (文本区域)表示该字段数据.(一个多行编辑框). <7> EmailField 一个带有检查Email合法性的 CharField,不接受 maxlength 参数. <8> DateField 一个日期字段. 共有下列额外的可选参数: Argument 描述 auto_now 当对象被保存时,自动将该字段的值设置为当前时间.一般用于表示 "last-modified" 时间戳. auto_now_add 当对象首次被建立时,自动将该字段的值设置为当前时间.一般用于表示对象建立时间. (仅仅在admin中有意义...) <9> DateTimeField 一个日期时间字段. 相似 DateField 支持一样的附加选项. <10> ImageField 相似 FileField, 不过要校验上传对象是不是一个合法图片.#它有两个可选参数:height_field和width_field, 若是提供这两个参数,则图片将按提供的高度和宽度规格保存. <11> FileField 一个文件上传字段. 要求一个必须有的参数: upload_to, 一个用于保存上载文件的本地文件系统路径. 这个路径必须包含 strftime #formatting, 该格式将被上载文件的 date/time 替换(so that uploaded files don't fill up the given directory). admin 用一个<input type="file">部件表示该字段保存的数据(一个文件上传部件) . 注意:在一个 model 中使用 FileField 或 ImageField 须要如下步骤: (1)在你的 settings 文件中, 定义一个完整路径给 MEDIA_ROOT 以便让 Django在此处保存上传文件. (出于性能考虑,这些文件并不保存到数据库.) 定义MEDIA_URL 做为该目录的公共 URL. 要确保该目录对 WEB服务器用户账号是可写的. (2) 在你的 model 中添加 FileField 或 ImageField, 并确保定义了 upload_to 选项,以告诉 Django 使用 MEDIA_ROOT 的哪一个子目录保存上传文件.你的数据库中要保存的只是文件的路径(相对于 MEDIA_ROOT). 出于习惯你必定很想使用 Django 提供的 get_<#fieldname>_url 函数.举例来讲,若是你的 ImageField 叫做 mug_shot, 你就能够在模板中以 {{ object.#get_mug_shot_url }} 这样的方式获得图像的绝对路径. <12> URLField 用于保存 URL. 若 verify_exists 参数为 True (默认), 给定的 URL 会预先检查是否存在( 即URL是否被有效装入且 没有返回404响应). admin 用一个 <input type="text"> 文本框表示该字段保存的数据(一个单行编辑框) <13> NullBooleanField 相似 BooleanField, 不过容许 NULL 做为其中一个选项. 推荐使用这个字段而不要用 BooleanField 加 null=True 选项 admin 用一个选择框 <select> (三个可选择的值: "Unknown", "Yes" 和 "No" ) 来表示这种字段数据. <14> SlugField "Slug" 是一个报纸术语. slug 是某个东西的小小标记(短签), 只包含字母,数字,下划线和连字符.#它们一般用于URLs 若你使用 Django 开发版本,你能够指定 maxlength. 若 maxlength 未指定, Django 会使用默认长度: 50. #在 之前的 Django 版本,没有任何办法改变50 这个长度. 这暗示了 db_index=True. 它接受一个额外的参数: prepopulate_from, which is a list of fields from which to auto-#populate the slug, via JavaScript,in the object's admin form: models.SlugField (prepopulate_from=("pre_name", "name"))prepopulate_from 不接受 DateTimeFields. <13> XMLField 一个校验值是否为合法XML的 TextField,必须提供参数: schema_path, 它是一个用来校验文本的 RelaxNG schema #的文件系统路径. <14> FilePathField 可选项目为某个特定目录下的文件名. 支持三个特殊的参数, 其中第一个是必须提供的. 参数 描述 path 必需参数. 一个目录的绝对文件系统路径. FilePathField 据此获得可选项目. Example: "/home/images". match 可选参数. 一个正则表达式, 做为一个字符串, FilePathField 将使用它过滤文件名. 注意这个正则表达式只会应用到 base filename 而不是 路径全名. Example: "foo.*\.txt^", 将匹配文件 foo23.txt 却不匹配 bar.txt 或 foo23.gif. recursive可选参数.要么 True 要么 False. 默认值是 False. 是否包括 path 下面的所有子目录. 这三个参数能够同时使用. match 仅应用于 base filename, 而不是路径全名. 那么,这个例子: FilePathField(path="/home/images", match="foo.*", recursive=True) ...会匹配 /home/images/foo.gif 而不匹配 /home/images/foo/bar.gif <15> IPAddressField 一个字符串形式的 IP 地址, (i.e. "24.124.1.30"). <16> CommaSeparatedIntegerField 用于存放逗号分隔的整数值. 相似 CharField, 必需要有maxlength参数.
更多参数 :
(1)null 若是为True,Django 将用NULL 来在数据库中存储空值。 默认值是 False. (1)blank 若是为True,该字段容许不填。默认为False。 要注意,这与 null 不一样。null纯粹是数据库范畴的,而 blank 是数据验证范畴的。 若是一个字段的blank=True,表单的验证将容许该字段是空值。若是字段的blank=False,该字段就是必填的。 (2)default 字段的默认值。能够是一个值或者可调用对象。若是可调用 ,每有新对象被建立它都会被调用。 (3)primary_key 若是为True,那么这个字段就是模型的主键。若是你没有指定任何一个字段的primary_key=True, Django 就会自动添加一个IntegerField字段作为主键,因此除非你想覆盖默认的主键行为, 不然不必设置任何一个字段的primary_key=True。 (4)unique 若是该值设置为 True, 这个数据字段的值在整张表中必须是惟一的 (5)choices 由二元组组成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项。 若是设置了choices ,默认的表单将是一个选择框而不是标准的文本框,<br>并且这个选择框的选项就是choices 中的选项。
首先是注册app:
修改mysite下的settings.py文件里面的INSTALLED_APPS。注册你的app,最后一行添加,我用的app名是app01
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01', ]
不注册它,你的数据库就不知道该给哪一个app建立表。
若想将模型转为mysql数据库中的表,须要在settings中配置:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', # 数据库引擎mysql 'NAME': 'book', # 你要存储数据的库名,事先要建立之 'USER': 'root', # 数据库用户名 'PASSWORD': '', # 密码 'HOST': 'localhost', # 主机 'PORT': '3306', # 数据库使用的端口 } }
注意1:NAME即数据库的名字,在mysql链接前该数据库必须已经建立,而上面的sqlite数据库下的db.sqlite3则是项目自动建立USER和PASSWORD分别是数据库的用户名和密码。
因为ORM不能建立数据库,须要手动建立。
进入mysql,建立数据库book。
C:\Users\xiao>mysql -u root Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 9 Server version: 5.7.22-log MySQL Community Server (GPL) Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> CREATE DATABASE book DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; Query OK, 1 row affected (0.01 sec) mysql>
django链接MySQL,使用的是pymysql模块,必须得安装2个模块。不然后面会建立表不成功!或者提示no module named MySQLdb
pip3 install pymysql pip3 install mysqlclient
接下来要在pycharm的teminal中经过命令建立数据库的表。有2条命令,分别是:
python manage.py makemigrations
它的做用至关于在该app下创建migrations目录,并记录下你全部的关于modes.py的改动,好比0001.initial.py,可是这个改动尚未做用到数据库文件
再输入命令:
python manage.py migrate
它是将该改动做用到数据库文件,好比建立表,修改表字段之类的操做。
注意2:若是想打印orm转换过程当中的sql,须要在settings中进行以下配置:
位置无所谓,但建议最后一行添加!
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, } }