微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!
Django 系列博客二
Django 系列博客(二)前言今天博客的内容为使用 Django 完成第一个 Django 页面,并进行一些简单页面的搭建和转跳。命令行搭建 Django 项目创建纯净虚拟环境在上一篇博客中已经安装好了虚拟环境,所以用虚拟环境来安装指定版本的 Django。为了可以从头到尾的走一遍流程,我重新创建了一个虚拟环境。激活虚拟环境并安装 Django首先进入虚拟环境路径下的 bin 目录使用命令激活虚拟环境安装指定版本 Django首先使用 pip3 list 命令查看可以看到都是创建虚拟环境时安装的依赖包,现在使用 pip 命令安装指定 django 版本,因为做项目需要稳定,所以安装的版本不是最新的。可以看到新安装了2个包,pytz 是 python time zone 的缩写,是用来转换时区的包。创建项目前往目标路径创建项目,在这里我的 django 项目都在我的家目录下面的 django_project里面。进入要创建项目的路径下,使用下面的命令创建一个 django 项目。django-admin startproject project_name可以看到多了个文件夹。查看项目结构创建应用进入项目根目录使用下面命令创建一个 app。python3 manage.py startapp app_name创建成功并查看项目结构。启动项目使用下面命令python3 manage.py runserver 127.0.0.1:8888成功后会在本机上的8888端口开启 django 服务访问8888端口会显示下图页面好了,到现在你已经开启了第一个 django 服务,并且还是使用了命令行。pycharm 创建 Django 项目其实会使用命令行创建项目那么使用 pycharm 应该是手到擒来,毕竟 pycharm 已经做了很多工作了。不过也有点麻烦。。。在虚拟环境下使用 pycharm 安装指定django 版本创建项目项目目录结构及作用项目目录:包含项目最基本的一些配置-- __init__.py:模块的配置文件,将blog_proj文件夹变成了模块-- settings.py:配置总文件-- urls.py:url配置文件,django项目中的所有页面都需要对其配置url地址-- wsgi.py:(web server gateway interface),服务器网关接口,python应用与web服务器直接通信的接口templates:模板文件夹,存放html文件的(页面),支持使用Django模板语言(DTL),也可以使用第三方(jinja2)manage.py:项目管理器,与项目交互的命令行工具集的入口,查看支持的所有命令python3 manage.pysettings.py结构import os# 项目根目录BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))# 项目安全码SECRET_KEY = 'guwba1u$18=&*8kf44_u&swqb@xlwgel7n$0rs=(+f10yvz)p0'# 调试模式,上线项目要关闭debug模式,不然后台出现异常会直接抛给前台展现给用户看了DEBUG = True# 在上线项目中,规定只能以什么ip地址来访问django项目# DEBUG = FALSE# ALLOWED_HOSTS = ['localhost']ALLOWED_HOSTS = []# 项目自带的应用# 我们创建了自己的应用就要将自定义应用添加到该配置INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles',]# 中间件# django自带的工具集MIDDLEWARE = ['django.middleware.security.SecurityMiddleware','django.contrib.sessions.middleware.SessionMiddleware','django.middleware.common.CommonMiddleware','django.middleware.csrf.CsrfViewMiddleware','django.contrib.auth.middleware.AuthenticationMiddleware','django.contrib.messages.middleware.MessageMiddleware','django.middleware.clickjacking.XFrameOptionsMiddleware',]# 配置url配件文件的根文件,执行urls.pyROOT_URLCONF = '项目目录.urls'# 模板,一个个html文件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',],},},]# 服务器网关接口应用WSGI_APPLICATION = '项目目录.wsgi.application'# 数据库配置# 要配置自定义数据库去下面链接去查询详细配置# https://docs.djangoproject.com/en/1.11/ref/settings/#databasesDATABASES = {'default': {'ENGINE': 'django.db.backends.sqlite3','NAME': os.path.join(BASE_DIR, 'db.sqlite3'),}}# 密码认证配置# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validatorsAUTH_PASSWORD_VALIDATORS = [{'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',},{'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',},{'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',},{'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',},]# 国际化相关配置# https://docs.djangoproject.com/en/1.11/topics/i18n/LANGUAGE_CODE = 'en-us'TIME_ZONE = 'UTC'USE_I18N = TrueUSE_L10N = TrueUSE_TZ = True# 静态文件地址 (CSS, JavaScript, Images)# https://docs.djangoproject.com/en/1.11/howto/static-files/STATIC_URL = '/static/'创建项目应用使用 pycharm 自带的命令行工具来创建应用应用创建完后将应用名添加到 settings.py文件中INSTALLED_APPS = ['django.contrib.admin',...'django.contrib.staticfiles',# 添加的自定义应用'app',]app目录结构创建后的 app 目录结构和使用命令行创建的一样,下面来看看具体都有什么作用migrations:数据迁移(移植)模块,内容都是由Django自动生成-- __init__.py__init__.pyadmin.py:应用的后台管理系统配置apps.py:django 1.9后,本应用的相关配置models.py:数据模型模块,使用ORM框架,类似于MVC模式下的Model层tests.py:自动化测试模块,可以写自动化测试脚本views.py:执行相应的逻辑代码模块(相应什么,如何相应),代码逻辑处理的主要地点,项目的大部分代码所在位置页面响应第一个响应通过配置路由和视图文件来响应第一次连接请求。配置路由from django.conf.urls import urlfrom django.contrib import admin# 导入应用视图import app.views as app_view # 取别名# 配置路由urlpatterns = [url(r'^admin/', admin.site.urls),# 为指定函数配置 urlurl(r'^index/&', app_view.index)]配置视图# 导入处理请求的 http 相应功能from django.http import HttpResponse# django中每一个请求都会设置相应函数来进行处理# 函数的参数约定为 requestdef index(request):return HttpResponse('index page!')启动服务启动服务后访问 localhost:8000/index/,可以看到响应为 index 函数里填写的响应,说明服务成功启动并且响应了自己想要的响应字符串。第一个模板页面项目目录下有个 templates 文件夹是专门用于存放页面资源的,比如index.htmlfrom django.shortcuts import renderdef index(request):# 参数:请求对象 request,模板 html 文件,传给前台的资源return render(request, 'index.html')index.html 文件<!DOCTYPE html><html><head><meta charset="UTF-8"><title>主页</title></
Django 系列博客七
Django 系列博客(七)前言本篇博客介绍 Django 中的视图层中的相关参数,HttpRequest 对象、HttpResponse 对象、JsonResponse,以及视图层的两种响应方式 CBV 和 FBV,还有简单的文件上传。视图函数一个视图函数,简称视图,是一个简单的Python 函数,它接受Web请求并且返回Web响应。响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片. . . 是任何东西都可以。无论视图本身包含什么逻辑,都要返回响应。代码写在哪里也无所谓,只要它在你的Python目录下面。除此之外没有更多的要求了——可以说“没有什么神奇的地方”。为了将代码放在某处,约定是将视图放置在项目或应用程序目录中的名为views.py的文件中。下面是一个返回当前日期和时间作为 HTML 文档的视图:from django.shortcuts import render, HttpResponse, HttpResponseRedirect, redirectimport datetimedef current_datetime(request):now = datetime.datetime.now()html = "<html><body>It is now %s.</body></html>" % nowreturn HttpResponse(html)这段代码解析:从 django.shortcuts模块导入了HttpResponse类,以及Python的datetime库;定义了current_datetime函数。它就是视图函数。每个视图函数都使用HttpRequest对象作为第一个参数,并且通常称之为request;注意,视图函数的名称并不重要;不需要用一个统一的命名方式来命名,以便让Django识别它。我们将其命名为current_datetime,是因为这个名称能够精确地反映出它的功能。会返回一个HttpResponse对象,其中包含生成的响应。每个视图函数都负责返回一个HttpResponse对象。在视图层最重要的就是要熟悉两个对象:请求对象(request)和响应对象(HttpResponse)。HttpRequest 对象request 属性Django 将请求报文中的请求行、请求头、请求体封装成 HttpRequest 类中的属性。除了特殊说明之外,其他的均为只读属性。1.HttpRequest.GET一个类似于字典的对象,包含 HTTP GET 的所有参数。详情请参考 QueryDict 对象。2.HttpRequest.POST一个类似于字典的对象,如果请求中包含表单数据,则将这些数据封装成 QueryDict 对象。POST 请求可以带有空的 POST 字典 —— 如果通过 HTTP POST 方法发送一个表单,但是表单中没有任何的数据,QueryDict 对象依然会被创建。因此,不应该使用 if request.POST 来检查使用的是否是POST 方法;应该使用 if request.method == "POST"另外:如果使用 POST 上传文件的话,文件信息将包含在 FILES 属性中。注意:键值对的值是多个的时候,比如checkbox类型的input标签,select标签,需要用:request.POST.getlist("hobby")3.HttpRequest.body一个字符串,代表请求报文的主体。在处理非 HTTP 形式的报文时非常有用,例如:二进制图片、XML,Json等。但是,如果要处理表单数据的时候,推荐还是使用 HttpRequest.POST 。4.HttpRequest.path一个字符串,表示请求的路径组件(不含域名)。例如:"/music/bands/the_beatles/"5.HttpRequest.method一个字符串,表示请求使用的HTTP 方法。必须使用大写。例如:"GET"、"POST"6.HttpRequest.encoding一个字符串,表示提交的数据的编码方式(如果为 None 则表示使用 DEFAULT_CHARSET 的设置,默认为 'utf-8')。这个属性是可写的,你可以修改它来修改访问表单数据使用的编码。接下来对属性的任何访问(例如从 GET 或 POST 中读取数据)将使用新的 encoding 值。如果你知道表单数据的编码不是 DEFAULT_CHARSET ,则使用它。7.HttpRequest.META一个标准的Python 字典,包含所有的HTTP 首部。具体的头部信息取决于客户端和服务器,下面是一些示例:取值:CONTENT_LENGTH —— 请求的正文的长度(是一个字符串)。CONTENT_TYPE —— 请求的正文的MIME 类型。HTTP_ACCEPT —— 响应可接收的Content-Type。HTTP_ACCEPT_ENCODING —— 响应可接收的编码。HTTP_ACCEPT_LANGUAGE —— 响应可接收的语言。HTTP_HOST —— 客服端发送的HTTP Host 头部。HTTP_REFERER —— Referring 页面。HTTP_USER_AGENT —— 客户端的user-agent 字符串。QUERY_STRING —— 单个字符串形式的查询字符串(未解析过的形式)。REMOTE_ADDR —— 客户端的IP 地址。REMOTE_HOST —— 客户端的主机名。REMOTE_USER —— 服务器认证后的用户。REQUEST_METHOD —— 一个字符串,例如"GET" 或"POST"。SERVER_NAME —— 服务器的主机名。SERVER_PORT —— 服务器的端口(是一个字符串)。从上面可以看到,除 CONTENT_LENGTH 和 CONTENT_TYPE 之外,请求中的任何 HTTP 首部转换为 META 的键时,都会将所有字母大写并将连接符替换为下划线最后加上 HTTP_ 前缀。所以,一个叫做 X-Bender 的头部将转换成 META 中的 HTTP_X_BENDER 键。8.HttpRequest.FILES一个类似于字典的对象,包含所有的上传文件信息。FILES 中的每个键为<input type="file" name="" /> 中的name,值则为对应的数据。注意,FILES 只有在请求的方法为POST 且提交的<form> 带有enctype="multipart/form-data" 的情况下才会包含数据。否则,FILES 将为一个空的类似于字典的对象。9.HttpRequest.COOKIES一个标准的Python 字典,包含所有的cookie。键和值都为字符串。10.HttpRequest.session一个既可读又可写的类似于字典的对象,表示当前的会话。只有当Django 启用会话的支持时才可用。完整的细节参见会话的文档。11.HttpRequest.user(用户认证组件下使用)一个 AUTH_USER_MODEL 类型的对象,表示当前登录的用户。如果用户当前没有登录,user 将设置为 django.contrib.auth.models.AnonymousUser 的一个实例。你可以通过 is_authenticated() 区分它们。例如:if request.user.is_authenticated():# Do something for logged-in users.else:# Do something for anonymous users.user 只有当Django 启用 AuthenticationMiddleware 中间件时才可用。-------------------------------------------------------------------------------------匿名用户class models.AnonymousUserdjango.contrib.auth.models.AnonymousUser 类实现了django.contrib.auth.models.User 接口,但具有下面几个不同点:id 永远为None。username 永远为空字符串。get_username() 永远返回空字符串。is_staff 和 is_superuser 永远为False。is_active 永远为 False。groups 和 user_permissions 永远为空。is_anonymous() 返回True 而不是False。is_authenticated() 返回False 而不是True。set_password()、check_password()、save() 和delete() 引发 NotImplementedError。New in Django 1.8:新增 AnonymousUser.get_username() 以更好地模拟 django.contrib.auth.models.User。request常用方法1.HttpRequest.get_full_path()返回 path,如果可以将加上查询字符串。例如:"/music/bands/the_beatles/?print=true"注意和path的区别:http://127.0.0.1:8001/order/?name=lqz&age=102.HttpRequest.is_ajax()如果请求是通过XMLHttpRequest 发起的,则返回True,方法是检查 HTTP_X_REQUESTED_WITH 相应的首部是否是字符串'XMLHttpRequest'。大部分现代的 JavaScript 库都会发送这个头部。如果你编写自己的 XMLHttpRequest 调用(在浏览器端),你必须手工设置这个值来让 is_ajax() 可以工作。如果一个响应需要根据请求是否是通过AJAX 发起的,并且你正在使用某种形式的缓存例如Django 的 cache middleware,你应该使用 vary_on_headers('HTTP_X_REQUESTED_WITH') 装饰你的视图以让响应能够正确地缓存。HttpResponse 对象响应对象主要有三种形式:前面的博客有相关介绍HttpResponse();render();redirect().HttpResponse()括号内直接跟一个具体的字符串作为响应体,比较直接和简单,所以这里介绍后两种render()render(request, template_name[, context])结合给定的模板和一个上下文字典,返回一个经过 Django渲染后的HttpResponse 对象到前端。参数:request:用于生成响应的请求对象;template_name:要使用的模板的完整名称,可选的参数;context:添加到模板上下文的一个字典。默认是一个空字典,如果字典中的某个值是可调用的,视图将在渲染模板之前调用它;render 方法就是将一个模板页面中的模板语法进行渲染,最终渲染成一个 HTML 页面作为响应返回给前端。redirect()传递要重定向的一个硬编码的URLdef my_view(request):...return redirect('/some/url/')也可以是一个完成的 urldef my_view(request):...return redirect('http://www.baidu.com/')JsonResponse对象向前端返回一个 json 格式的字符串,有两种方式:第一种方式import jsondata = {'nam
Django 系列博客八
Django 系列博客(八)前言本篇博客介绍 Django 中的模板层,模板都是Django 使用相关函数渲染后传输给前端在显式的,为了想要渲染出我们想要的数据,需要学习模板语法,相关过滤器、标签。模板简介你可能注意到下面的例子返回文本的方式有点特别。当我们使用相关函数来渲染模板的时候,首先是打开了模板文件,然后将需要传入的参数填到文件中在返回给前端。def current_datetime(request):now = datetime.datetime.now()html = '<html><body>It is now %s.</body></html>' % nowreturn HttpResponse(html)尽管这很能直观的解释视图层的工作方式,但直接将 HTML 硬编码到你的视图里却不是个好主意。对页面设计进行的任何改变都必须对python代码进行相应的更改。站点设计的修改往往比底层python代码的修改要频繁的多,因此如何可以在不进行python代码修改的情况下变更设计,那将会方便的多。python代码编写和html设计是两项不同的工作,大多数专业的网站开发环境都会分配不同的部分或者开发人员来完成。设计者和html/css的编码人员不应该被要求去编辑python的代码来完成他们的工作。程序员编写python代码和设计人员制作模板两项工作同时进行的效率是最高的,远胜于让一个人等待另一个人完成对某个既包含python又包含html的文件的编辑工作。基于上述这些原因,将页面的设计和 Python 的代码分离开来会更干净简洁更易维护。可以使用 Django 的模板系统(Templates System)来实现这种模式。def current_time(req):import datetimenow = datetime.datetime.now()html = '<html><body>It is now %s.</body></html>' % now# django模板修改的视图函数from django.template import Template, Contextnow = datetime.datetime.now()t = '<html><body>It is now %s.</body></html>' % nowc = Context({'current_date': str(now)})html = t.render(c)return HttpResponse(html)# 另一种写法import datetimenow = datetime.datetime.now()return render(req, 'current_datetime.html', {'current_date': str(now)[:19]})模板语法终点:变量:{{ 变量名 }}深度查询,用点语法过滤器标签:{{ % % }}模板语法变量在 Django 模板中遍历复杂数据结构的关键是点语法views.pydef template_test(request):name = 'lqz'li = ['lqz', 1, '18']dic = {'name': 'lqz', 'age': 18}ll2 = [{'name': 'lqz', 'age': 18},{'name': 'lqz2', 'age': 19},{'name': 'egon', 'age': 20},{'name': 'kevin', 'age': 23}]ll3=[]class Person:def __init__(self, name):self.name = namedef test(self):print('test函数')return 11@classmethoddef test_classmethod(cls):print('类方法')return '类方法'@staticmethoddef static_method():print('静态方法')return '静态方法'lqz = Person('lqz')egon = Person('egon')person_list = [lqz, egon]bo = Truete = test()import datetimenow=datetime.datetime.now()link1='<a href="https://www.baidu.com">点我<a>'from django.utils import safestringlink=safestring.mark_safe(link1)# html特殊符号对照表(http://tool.chinaz.com/Tools/htmlchar.aspx)# 这样传到前台不会变成特殊字符,因为django给处理了dot='&spades;'# return render(request, 'template_index.html', {'name':name,'person_list':person_list})return render(request, 'template_index.html', locals())html文件<p>{{ name }}</p><p>{{ li }}</p><p>{{ dic }}</p><p>{{ lqz }}</p><p>{{ person_list }}</p><p>{{ bo }}</p><p>{{ te }}</p><hr><h3>深度查询句点符</h3><p>{{ li.1 }}</p><p>{{ dic.name }}</p><p>{{ lqz.test }}</p><p>{{ lqz.name }}</p><p>{{ person_list.0 }}</p><p>{{ person_list.1.name }}</p><hr><h3>过滤器</h3>{#注意:冒号后面不能加空格#}<p>{{ now | date:"Y-m-d H:i:s" }}</p>{#如果变量为空,设置默认值,空数据,None,变量不存在,都适用#}<p>{{ name |default:'数据为空' }}</p>{#计算长度,只有一个参数#}<p>{{ person_list |length }}</p>{#计算文件大小#}<p>{{ 1024 |filesizeformat }}</p>{#字符串切片,前闭后开,前面取到,后面取不到#}<p>{{ 'hello world lqz' |slice:"2:-1" }}</p><p>{{ 'hello world lqz' |slice:"2:5" }}</p>{#截断字符,至少三个起步,因为会有三个省略号(传负数,1,2,3都是三个省略号)#}<p>{{ '刘清政 world lqz' |truncatechars:"4" }}</p>{#截断文字,以空格做区分,这个不算省略号#}<p>{{ '刘清政 是 大帅比 谢谢' |truncatewords:"1" }}</p><p>{{ link1 }}</p><p>{{ link1|safe }}</p><p>{{ link }}</p><p>&spades;</p><p>{{ dot }}</p>{#add 可以加负数,传数字字符串都可以#}<p>{{ "10"|add:"-2" }}</p><p>{{ li.1|add:"-2" }}</p><p>{{ li.1|add:2 }}</p><p>{{ li.1|add:"2" }}</p><p>{{ li.1|add:"-2e" }}</p>{#upper#}<p>{{ name|upper }}</p><p>{{ 'LQZ'|lower }}</p><hr><h3>模版语法之标签</h3>{#for 循环 循环列表,循环字典,循环列表对象#}<ui>{% for foo in dic %}{{ foo }}{% endfor %}{#也可以混用html标签#}{% for foo in li %}<ul>foo</ul>{% endfor %}</ui>{#表格#}<table border="1">{% for foo in ll2 %}<tr><td>{{ foo.name }}</td><td>{{ foo.age }}</td></tr>{% endfor %}</table><table border="1">{#'parentloop': {}, 'counter0': 0, 'counter': 1, 'revcounter': 4, 'revcounter0': 3, 'first': True, 'last': False}#}{% for foo in ll2 %}<tr><td>{{ forloop.counter }}</td><td>{{ foo.name }}</td><td>{{ foo.age }}</td></tr>{% endfor %}</table>{% for foo in ll5 %}<p>foo.name</p>{% empty %}<p>空的</p>{% endfor %}<hr><h3>if判断</h3>{% if nam
Django 系列博客九
Django 系列博客(九)前言本篇博客介绍 Django 模板的导入与继承以及导入导入静态文件的几种方式。模板导入模板导入语法:``{% include '模板名称' %}如下:<!-- base.html --><!DOCTYPE html><html><head><meta charset="UTF-8"><title>index</title><link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.css"><style>.head {height: 100px;background-color: #2aabd2;text-align: center;line-height: 100px;font-size: 25px;}.container-fluid {text-align: center;}a {list-style: none;text-decoration: none !important;}</style></head><body><div class="head">图书管理系统</div><div class="container-fluid"><div class="row"><div class="col-md-3">{% include 'left.html' %}</div><div class="col-md-9"><div class="pull-right">{% block right %}{% endblock %}</div>{% block content %}{% endblock %}</div></div></div></body></html><!-- left.html --><div><div class="panel panel-danger"><div class="panel-heading"><h3 class="panel-title"><a href="/book/">图书列表</a></h3></div></div><div class="panel panel-danger"><div class="panel-heading"><h3 class="panel-title"><a href="/author/">作者列表</a></h3></div></div><div class="panel panel-danger"><div class="panel-heading"><h3 class="panel-title"><a href="/publish/">出版社列表</a></h3></div></div></div><!-- other.html -->{% extends 'base.html' %}{% block content %}{{ blcok.super }}{% endblock content %}模板继承Django 模板引擎中最强大的也是最复杂的除了 orm 就是模板继承了。模板继承可以让您创建一个基本的‘’骨架‘’模板,它包含您站点的全部元素,并且可以定义可以被子模板覆盖的 blocks。通过下面的例子,可以容易的理解模板继承:<!DOCTYPE html><html lang="en"><head><link rel="stylesheet" href="style.css"/><title>{% block title %}My amazing site{% endblock %}</title></head><body><div id="sidebar">{% block sidebar %}<ul><li><a href="/">Home</a></li><li><a href="/blog/">Blog</a></li></ul>{% endblock %}</div><div id="content">{% block content %}{% endblock %}</div></body></html>这个模版,我们把它叫作 base.html, 它定义了一个可以用于两列排版页面的简单HTML骨架。“子模版”的工作是用它们的内容填充空的blocks。在这个例子中, block 标签定义了三个可以被子模版内容填充的block。 block 告诉模版引擎: 子模版可能会覆盖掉模版中的这些位置。子模版可能看起来是这样的:{% extends "base.html" %}{% block title %}My amazing blog{% endblock %}{% block content %}{% for entry in blog_entries %}<h2>{{ entry.title }}</h2><p>{{ entry.body }}</p>{% endfor %}{% endblock %}extends 标签是这里的关键。它告诉模版引擎,这个模版“继承”了另一个模版。当模版系统处理这个模版时,首先,它将定位父模版——在此例中,就是“base.html”。那时,模版引擎将注意到 base.html 中的三个 block 标签,并用子模版中的内容来替换这些block。根据 blog_entries 的值,输出可能看起来是这样的:<!DOCTYPE html><html lang="en"><head><link rel="stylesheet" href="style.css" /><title>My amazing blog</title></head><body><div id="sidebar"><ul><li><a href="/">Home</a></li><li><a href="/blog/">Blog</a></li></ul></div><div id="content"><h2>Entry one</h2><p>This is my first entry.</p><h2>Entry two</h2><p>This is my second entry.</p></div></body></html>请注意,子模版并没有定义 sidebar block,所以系统使用了父模版中的值。父模版的 {% block %} 标签中的内容总是被用作备选内容(fallback)。这种方式使代码得到最大程度的复用,并且使得添加内容到共享的内容区域更加简单,例如,部分范围内的导航。注意:如果在模板中使用{% extends %}标签,它必须是模板中的第一个标签。其他的任何情况下,模板继承都将无法工作。在base模板中设置越多的{% block %}标签越好。请记住,子模板不必定义全部父模板中的blocks,所以,你可以在大多数blocks中填充合理的默认内容,然后,只定义你需要的那一个。多一点钩子总比少一点好。如果你发现在大量的模板中复制内容,那可能意味着你应该把内容移到父模板中的一个{% block %}。如果需要从父模板中获取块的内容,{{ block.super }}变量可以完成这个任务。如果要添加父块的内容而不是完全覆盖它,这将非常有用。使用{{ block.super }}插入数据将不会自动转义,因为它已经在父模板中进行了必要的转义。为了更好地可读性,你也可以给你的{& endblock %}标签一个名字。例如:{% block content %}{% endblock content %}​ 在大型模板中,这个方法可以让你清楚地看到哪个标签被关闭了。不能在一个模板中定义多个相同名字的block标签。静态文件settings.py中的静态文件设置STATIC_URL = '/static/'STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]在模板中加载静态文件{% load static %}<img src="{% static "images/hi.jpg" %}" alt="Hi!" />引用 js 文件{% load static %}<script src="{% static "mytest.js" %}"></script>多个文件使用多次取别名{% load static %}{% static "images/hi.jpg" as myphoto %}<img src="{{ myphoto }}"></img>使用 get_static_prefix{% load static %}<img src="{% get_static_prefix %}images/hi.jpg" alt="Hi!" />或{% load static %}{% get_static_prefix as STATIC_PREFIX %}<img src="{{ STATIC_PREFIX }}images/hi.jpg" alt="Hi!" /><img src="{{ STATIC_PREFIX }}images/hi2.jpg" alt="Hello!" />使用 inclusion_tag返回 html 代码片段my_inclusion.pyfrom django.template import Libraryregister = Library()# @regist
Django 系列博客十
Django 系列博客(十)前言本篇博客介绍在 Django 中如何对数据库进行增删查改,主要为对单表进行操作。ORM简介查询数据层次图解:如果操作 mysql,ORM 是在 pymysql 之上又进行了一层封装。MVC 或者 MTV 框架中包括一个重要的部分,就是 ORM,它实现了数据模型与数据库的解耦合,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,极大地减轻了工作量,不需要面对因数据变更而导致的无效劳动。ORM 是‘’对象-关系-映射‘’的简称通过 ORM 可以简化甚至不需要在写 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()单表操作创建表首先在 settings.py中配置好 mysql参数。DATABASES = {'default': {'ENGINE': 'django.db.backends.mysql','NAME': 'friday_work','HOST': '127.0.0.1','PORT': 3306,'USER': 'root','PASSWORD': 'password','ATOMIC_REQUEST': True,'OPTIONS': {"init_command": "SET storage_engine=MyISAM",}}}'NAME':要连接的数据库,连接前需要创建好'USER':连接数据库的用户名'PASSWORD':连接数据库的密码'HOST':连接主机,默认本机'PORT':端口 默认3306'ATOMIC_REQUEST': True,设置为True统一个http请求对应的所有sql都放在一个事务中执行(要么所有都成功,要么所有都失败)。是全局性的配置, 如果要对某个http请求放水(然后自定义事务),可以用non_atomic_requests修饰器'OPTIONS': {"init_command": "SET storage_engine=MyISAM",}设置创建表的存储引擎为MyISAM,INNODB**注意:NAME 即数据库的名字,在 mysql 连接前该数据库必须已经创建,而上面的 sqlite 数据库下的db.sqlite3则是项目自动 创建 USER 和 PASSWORD 分别是数据库的用户名和密码。设置完后,再启动我们的 django 项目前,我们需要激活 mysql。然后,启动项目会报错:no module named MySQLdb 。这是因为django默认你导入的驱动是MySQLdb,可是MySQLdb 对于py3有很大问题,所以我们需要的驱动是PyMySQL 所以,我们只需要找到项目名文件下的__init__,在里面写入下面的代码:**在一个模块中设置 mysql 引擎import pymysqlpymysql.install_as_MySQLdb()在 models.py中创建数据模型from django.db import models# Create your models here.class Book(models.Model):id = models.AutoField(primary_key=True)name = models.CharField(max_length=64)pub_data = models.DateField()price = models.DecimalField(max_digits=5, decimal_places=2)publish = models.CharField(max_length=12)def __str__(self):return self.name数据迁移python manage.py makemigrationspython manage.py migrate想打印 ORM 转换过程中的 sql,在 settings.py中进行如下设置:LOGGING = {'version': 1,'disable_existing_loggers': False,'handlers': {'console':{'level':'DEBUG','class':'logging.StreamHandler',},},'loggers': {'django.db.backends': {'handlers': ['console'],'propagate': True,'level':'DEBUG',},}}增加删除字段删除,直接注释掉字段,重新执行数据库迁移命令即可;新增字段,在类里直接新增字段,直接执行数据库迁移命令会提示输入默认值,此时需要在字段里面设置:null=True注意:​ 1. 数据库迁移记录都在 application 下面的 migrations 里面的 py 文件中;​ 2. 使用 showmigrations 命令可以查看没有执行 migrate 的文件;​ 3. makemigrations 是生成一个创建表的记录,migrate 是将更改提交到数据库。在 python 中调用 Django 环境import osif __name__ == '__main__':os.environ.setdefault("DJANGO_SETTINGS_MODULE", "untitled15.settings")import djangodjango.setup()from app01 import modelsbooks = models.Book.objects.all()print(books)更多字段和参数每个字段有一些特有的参数,例如,CharField 需要 max_length参数来指定 VARCHAR 数据库字段的大小。还有一些适用于所有字段的通用参数。这些参数在文档中有详细定义,这里简单介绍一些常用字段含义:AutoField(Field):int自增列,必须填入参数primary_key=TrueBigAutoField(AutoField):bigint 自增列,必须填入参数primary_key=True注:当 model 中没有自增列,则自动会创建一个列名为 id 的字段SmallIntegerField(IntegerField):小整数,-32768 ~ 32767PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField):正小整数 0 ~ 32767IntegerField(Field):整数列(有符号)-2147483648 ~ 2147483647PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField):正整数 0 ~ 2147483647BigIntegerField(IntegerField):长整型(有符号)-9223372036854775808 ~ 9223372036854775807自定义无符号整数字段class UnsignedIntegerField(models.IntegerField):def db_type(self, connection):return 'integer UNSIGNED'BooleanField(Field):布尔值类型NullBooleanField(Field):可以为空的布尔值CharField(Field):字符类型。必须设置 max_length参数,表示字符长度TextField(Field):文本类型EmailField(CharField):字符串类型,Django admin 以及 ModelForm 中提供验证机制IPAddressField(Field):字符串类型,Django Admin 以及 ModelForm 中提供验证 IPV4机制GenericIPAddressField(Field):字符串类型,Django Admin 以及 ModelFOrm 中提供验证 IPV4和 IPV6,参数:protocol,用于指定 IPV4或 IPV6,URLField(CharField):字符串类型,Django Admin 以及ModelForm 中提供验证 URLSlugField(CharField):字符串类型,Django Admin 以及 ModelForm 中提供验证支持字母、数字、下划线、连接符(减号)CommaSeparatedIntegerField(CharField):字符串类型,格式必须为逗号分隔的数字UUIDField(Field):字符串类型,Django Admin 以及 ModelForm 中提供对 UUID 格式的验证FilePathField(Field):字符串,Django A
Django 系列博客十一
Django 系列博客(十一)前言本篇博客介绍使用 ORM 来进行多表的操作,当然重点在查询方面。创建表实例:作者模型:一个作者有姓名和年龄。作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息。作者详情模型和作者模型之间是一对一的关系(one-to-one)。出版商模型:出版商有名称,所在城市。书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many);一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系(one-to-many)。建表语句from django.db import models# Create your models here.class Book(models.Model):id = models.AutoField(primary_key=True)name = models.CharField(max_length=32)price = models.DecimalField(max_digits=5, decimal_places=2)publish = models.ForeignKey(to='Publish', to_field='id', on_delete=models.CASCADE)pub_date = models.DateField()authors = models.ManyToManyField(to='Author')class Author(models.Model):id = models.AutoField(primary_key=True)name = models.CharField(max_length=32)age = models.IntegerField(default=18)class Publish(models.Model):id = models.AutoField(primary_key=True)name = models.CharField(max_length=32)addr = models.CharField(max_length=32)class AuthorDetail(models.Model):id = models.AutoField(primary_key=True)addr = models.CharField(max_length=32)author = models.OneToOneField(to=Author, to_field='id')表关联关系如下注意:表的名称为 app名字_modelName,是根据模型中的元数据自动生成的,也可以重写为别的名称;id 字段如果没有定义,会自动添加;对于外键字段,Django 会自动在字段名前面加上‘’_id‘’来创建数据库中的列名;这个例子中的 CREATE TABLE SQL语句使用 PostgreSQL 语法格式,要注意的是 Django 会根据 settings 中指定的数据库类型来使用相应的 sql 语句;定义好模型后,需要告诉 Django 使用这些模型,你要做的是修改配置文件中的 INSTALL_APPSZ 中设置,在其中添加 models.py所在应用的名称;外键字段 ForeignKey 有一个 null=True的设置(允许外键接受空值 NULL),你可以赋给它空值 None。添加表记录一对多方式一:publish_obj=Publish.objects.get(nid=1)book_obj=Book.objects.create(title="",publishDate="2012-12-12",price=100,publish=publish_obj)方式二:book_obj=Book.objects.create(title="",publishDate="2012-12-12",price=100,publish_id=1)注意:关键点:一 book_obj.publish=Publish.objects.filter(id=book_obj.publish_id).first()二 book_obj.authors.all()关键点:book.authors.all() # 与这本书关联的作者集合1 book.id=32 book_authorsid book_id author_ID3 3 14 3 23 authorid name1 musibii2 thalesbook_obj.authors.all() -------> [musibii,thales]# -----一对多添加pub=Publish.objects.create(name='北京出版社',email='[email protected]',city='北京')print(pub)# 为book表绑定和publish的关系import datetime,timenow=datetime.datetime.now().__str__()now = datetime.datetime.now().strftime('%Y-%m-%d')print(type(now))print(now)# 日期类型必须是日期对象或者字符串形式的2018-09-12(2018-9-12),其它形式不行Book.objects.create(name='海燕3',price=333.123,publish_date=now,publish_id=2)Book.objects.create(name='海3燕3',price=35.123,publish_date='2018/02/28',publish=pub)pub=Publish.objects.filter(nid=1).first()book=Book.objects.create(name='测试书籍',price=33,publish_date='2018-7-28',publish=pub)print(book.publish.name)# 查询出版了红楼梦这本书出版社的邮箱book=Book.objects.filter(name='红楼梦').first()print(book.publish.email)多对多# 当前生成的书籍对象book_obj=Book.objects.create(title="追风筝的人",price=200,publishDate="2012-11-12",publish_id=1)# 为书籍绑定的做作者对象yuan=Author.objects.filter(name="shao").first() # 在Author表中主键为2的纪录egon=Author.objects.filter(name="zuan").first() # 在Author表中主键为1的纪录# 绑定多对多关系,即向关系表book_authors中添加纪录book_obj.authors.add(shao,zuan) # 将某些特定的 model 对象添加到被关联对象集合中。 ======= book_obj.authors.add(*[])book = Book.objects.filter(name='红楼梦').first()musibii=Author.objects.filter(name='musibii').first()eureka=Author.objects.filter(name='eureka').first()# 1 没有返回值,直接传对象book.authors.add(musibii,eureka)# 2 直接传作者idbook.authors.add(1,3)# 3 直接传列表,会打散book.authors.add(*[1,2])# 解除多对多关系book = Book.objects.filter(name='红楼梦').first()# 1 传作者idbook.authors.remove(1)# 2 传作者对象egon = Author.objects.filter(name='musibii').first()book.authors.remove(musibii)#3 传*列表book.authors.remove(*[1,2])#4 删除所有book.authors.clear()# 5 拿到与 这本书关联的所有作者,结果是queryset对象,作者列表ret=book.authors.all()# print(ret)# 6 queryset对象,又可以继续点(查询红楼梦这本书所有作者的名字)ret=book.authors.all().values('name')print(ret)# 以上总结:# (1)# book=Book.objects.filter(name='红楼梦').first()# print(book)# 在点publish的时候,其实就是拿着publish_id又去app01_publish这个表里查数据了# print(book.publish)# (2)book.authors.all()多对多关系常用 APIbook_obj.authors.remove() # 将某个特定的对象从被关联对象集合中去除。 ====== book_obj.authors.remove(*[])book_obj.authors.clear() #清空被关联对象集合book_obj.authors.set() #先清空再设置基于对象的跨表查询一对多查询正向查询按字段# 查询主键为1的书籍的出版社所在的城市book_obj=Book.objects.filter(pk=1).first()# book_obj.publish 是主键为1的书籍对象关联的出版社对象print(book_obj.publish.city)反向查询按表名小写_setpublish=Publish.objects.get(name="苹果出版社")#publish.book_set.all() : 与苹果出版社关联的所有书籍对象集合book_list=publish.book_set.all()for book_obj in book_list:print(book_obj.title)例子:# 一对多正向查询book=Book.objects.filter(name='红楼梦').first()print(book.publish)#与这本书关联的出版社对象print(book.publish.name)# 一对多反向查询# 人民出版社出版过的书籍名称pub=Publish.objects.filter(name='人民出版社').first()ret=pub.book_set.all()print(ret)一对一查询正向查询按字段egon=Author.objects.filter(name="egon").first()print(egon.authorDetail.telephone)反向查询按表名# 查询所有住址在北京的作者的姓名authorDetail_list=AuthorDetail.objects.filter(addr="beijing")for obj in authorDetail
Django 系列博客十二
Django 系列博客(十二)前言本篇博客继续介绍 Django 中的查询,分别为聚合查询和分组查询,以及 F 和 Q 查询。聚合查询语法:aggregate(*args, **kwargs)# 计算所有图书的平均价格from django.db.models import AvgBook.objects.all().aggregate(Avg('price'))aggregate()是 QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。键的名称是聚合值得标识符,值是计算出来的聚合值。建的名称是按照字段和聚合函数的名称自动生成出来的。如果你想要为聚合值指定个名称,可以向聚合子句提供它。Book.objects.aggregate(average_price=Avg('price'))如果你希望生成不止一个聚合值,你可以向 aggregate()子句中添加另一个参数。所以如果想知道所有图书价格的最大值和最小值,可以这样查询:from django.db.models import Avg, Max, MinBook.objects.aggregate(Avg('price'), Max('price'), Min('price'))具体例子:# 查询所有书籍的平均价格from django.db.models import Avg,Count,Max,Minret=Book.objects.all().aggregate(Avg('price'))# {'price__avg': 202.896}# 可以改名字ret=Book.objects.all().aggregate(avg_price=Avg('price'))# 统计平均价格和最大价格ret=Book.objects.all().aggregate(avg_price=Avg('price'),max_price=Max('price'))# 统计最小价格ret = Book.objects.all().aggregate(avg_price=Avg('price'), min_price=Min('price'))# 统计个数和平均价格ret = Book.objects.all().aggregate(avg_price=Avg('price'), max_price=Max('price'),count=Count('price'))ret = Book.objects.all().aggregate(avg_price=Avg('price'), max_price=Max('price'),count=Count('nid'))print(ret)分组查询总结:group by 那个表就以那个表作为基表values 在前:表示 group byvalues 在后:表示取值filter 在前:表示 where 条件filter 在后:表示 having分组查询案例# 查询所有作者写的书的总价格大于26的# filter()在annotate后面,表示对分组后的结果进行筛选,相当于having# annotate前的values()表示按该字段分组,相当于group by,可以省略,默认会按Author的id分组# 后面的values()表示取值ret=Author.objects.all().values('pk').annotate(s=Sum('book__price')).filter(s__gt=26).values('name','s')等价于ret=Author.objects.all().annotate(s=Sum('book__price')).filter(s__gt=26).values('name','s')# 查询各个作者出的书的总价格# s相当于给求和结果取名字,在vlaues取值中,可以引用ret = Author.objects.all().annotate(s=Sum('price')).values('name','s')print(ret)# 统计不止一个作者的图书ret=Book.objects.all().values('pk').annotate(c=Count('authors')).filter(c__gt=1).values('name','c')print(ret)等价于ret = Book.objects.annotate(author_num=Count("authors")).filter(author_num__gt=1).values('name','author_num')print(ret)F 查询什么是 F 查询如果要对两个字段的值作比较,就不能直接比较,必须借助 F()的实例,可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。语法from django.db.models import Ffliter(commit_num_gt=F('read_num'))F 查询的使用# 查询评论数大于阅读数的书book = models.Book.objects.filter(commit_num__gt=F('read_num')).values('name')# 把所有书的评论数加1models.Book.objects.all().update(commit_num=F('commit_num')+1)Q 查询什么是 Q 查询对两个字段的值进行或、与、非运算,不能直接运算,需要用 Q()的实例。语法# 且 -----> &# 或 -----> |# 非 -----> ~from django.db.models import Qfliter(Q(name='tom')|Q(name='tony'))Q 查询的使用# 查询不是tom写的书的名字ret = models.Book.objects.filter(~Q(authors__name='tom')).values('name')# 查询作者名字是tom或者名字是tony的书ret = models.Book.objects.filter(Q(authors__name='tom')|Q(authors__name='tony')).values('name')补充:在实际开发中,外键通常不用:约束性太强查询效率低可以通过db_constraint=False来取消外键约束,在 orm 创建表的时候,外键的约束不会存在,但是这样会产生脏数据。建外键约束,包括 unique 都是为了不产生脏数据。
Django 系列博客十三
Django 系列博客(十三)前言本篇博客介绍 Django 中的常用字段和参数。ORM 字段AutoFieldint 自增列,必须填入参数 primary_key=True。当 model 中如果没有自增列,则会自动创建一个列名为 id 的列。IntegerField一个整数类型,范围在-2147483648 to 2147483647。CharField字符类型,必须提供max_length参数, max_length表示字符长度。DateField日期字段,日期格式 YYYY-MM-DD,相当于Python中的datetime.date()实例。DateTimeField日期时间字段,格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],相当于Python中的datetime.datetime()实例。常用和非常用字段AutoField(Field)- int自增列,必须填入参数primary_key = TrueBigAutoField(AutoField)- bigint自增列,必须填入参数primary_key = True注:当model中如果没有自增列,则自动会创建一个列名为id的列from django.db import modelsclass UserInfo(models.Model):# 自动创建一个列名为id的且为自增的整数列username = models.CharField(max_length=32)class Group(models.Model):# 自定义自增列nid = models.AutoField(primary_key=True)name = models.CharField(max_length=32)SmallIntegerField(IntegerField):- 小整数 - 32768 ~ 32767PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)- 正小整数0 ~ 32767IntegerField(Field)- 整数列(有符号的) - 2147483648 ~ 2147483647PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)- 正整数0 ~ 2147483647BigIntegerField(IntegerField):- 长整型(有符号的) - 9223372036854775808 ~ 9223372036854775807BooleanField(Field)- 布尔值类型NullBooleanField(Field):- 可以为空的布尔值CharField(Field)- 字符类型- 必须提供max_length参数, max_length表示字符长度TextField(Field)- 文本类型EmailField(CharField):- 字符串类型,DjangoAdmin以及ModelForm中提供验证机制IPAddressField(Field)- 字符串类型,DjangoAdmin以及ModelForm中提供验证IPV4机制GenericIPAddressField(Field)- 字符串类型,DjangoAdmin以及ModelForm中提供验证Ipv4和Ipv6- 参数:protocol,用于指定Ipv4或Ipv6, 'both', "ipv4", "ipv6"unpack_ipv4, 如果指定为True,则输入::ffff: 192.0.2.1时候,可解析为192.0.2.1,开启此功能,需要protocol = "both"URLField(CharField)- 字符串类型,DjangoAdmin以及ModelForm中提供验证URLSlugField(CharField)- 字符串类型,DjangoAdmin以及ModelForm中提供验证支持字母、数字、下划线、连接符(减号)CommaSeparatedIntegerField(CharField)- 字符串类型,格式必须为逗号分割的数字UUIDField(Field)- 字符串类型,DjangoAdmin以及ModelForm中提供对UUID格式的验证FilePathField(Field)- 字符串,DjangoAdmin以及ModelForm中提供读取文件夹下文件的功能- 参数:path, 文件夹路径match = None, 正则匹配recursive = False, 递归下面的文件夹allow_files = True, 允许文件allow_folders = False, 允许文件夹FileField(Field)- 字符串,路径保存在数据库,文件上传到指定目录- 参数:upload_to = ""上传文件的保存路径storage = None存储组件,默认django.core.files.storage.FileSystemStorageImageField(FileField)- 字符串,路径保存在数据库,文件上传到指定目录- 参数:upload_to = ""上传文件的保存路径storage = None存储组件,默认django.core.files.storage.FileSystemStoragewidth_field = None, 上传图片的高度保存的数据库字段名(字符串)height_field = None上传图片的宽度保存的数据库字段名(字符串)DateTimeField(DateField)- 日期 + 时间格式YYYY - MM - DDHH: MM[:ss[.uuuuuu]][TZ]DateField(DateTimeCheckMixin, Field)- 日期格式YYYY - MM - DDTimeField(DateTimeCheckMixin, Field)- 时间格式HH: MM[:ss[.uuuuuu]]DurationField(Field)- 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型FloatField(Field)- 浮点型DecimalField(Field)- 10进制小数- 参数:max_digits,小数总长度decimal_places,小数位长度BinaryField(Field)- 二进制类型ORM字段与数据库实际字段的对应关系对应关系:'AutoField': 'integer AUTO_INCREMENT','BigAutoField': 'bigint AUTO_INCREMENT','BinaryField': 'longblob','BooleanField': 'bool','CharField': 'varchar(%(max_length)s)','CommaSeparatedIntegerField': 'varchar(%(max_length)s)','DateField': 'date','DateTimeField': 'datetime','DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)','DurationField': 'bigint','FileField': 'varchar(%(max_length)s)','FilePathField': 'varchar(%(max_length)s)','FloatField': 'double precision','IntegerField': 'integer','BigIntegerField': 'bigint','IPAddressField': 'char(15)','GenericIPAddressField': 'char(39)','NullBooleanField': 'bool','OneToOneField': 'integer','PositiveIntegerField': 'integer UNSIGNED','PositiveSmallIntegerField': 'smallint UNSIGNED','SlugField': 'varchar(%(max_length)s)','SmallIntegerField': 'smallint','TextField': 'longtext','TimeField': 'time','UUIDField': 'char(32)',ORM字段参数null用于表示某个字段可以为空。unique如果设置 unique=True,则该字段在此表中必须是惟一的。db_index如果 db_index=True, 则代表着为此字段设置索引。default为该字段设置默认值。auto_now_add配置 auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。auto_now配置 auto_now=True,每次更新数据记录的时候会更新该字段。具体意思null 数据库中字段是否可以为空db_column 数据库中字段的列名db_tablespacedefault 数据库中字段的默认值primary_key 数据库中字段是否为主键db_index 数据库中字段是否可以建立索引unique 数据库中字段是否可以建立唯一索引unique_for_date 数据库中字段【日期】部分是否可以建立唯一索引unique_for_month 数据库中字段【月】部分是否可以建立唯一索引unique_for_year 数据库中字段【年】部分是否可以建立唯一索引verbose_name Admin中显示的字段名称blank Admin中是否允许用户输入为空editable Admin中是否可以编辑help_text Admin中该字段的提示信息choices Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1)error_messages 自定义错误信息(字典类型),从而定制想要显示的错误信息;字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date如:{'null': "不能为空.", 'invalid': '格式错误'}validator