Django
安装
- 安装:pip install django,默认安装在python 的 Scripts 目录下
- 将Script添加至环境变量:如C:DprogramPython354Scripts
- CMD中运行,创建Django工程:django-admin.exe startproject mysite(或者 django-admin startproject mysite) 创建工程mysite目录;mysite可以换成其他目录名
- 在CMD中运行manage.py,启动Django功能:python manage.py runserver 127.0.0.1:8001
运行
- 专业版pycharm:可以直接创建django项目,然后可以选择django项目运行
- 非专业版pycharm:不能直接创建django项目,在run图标左侧,选择manage点击可看见Edit Configurations,点击后可看见Parameters,只需配置“runserver 127.0.0.1:8001”,然后保存即可运行manage.
project目录
mysite - mysite # 对整个程序进行配置 - init - settings # 配置文件 - url # URL对应关系 - wsgi # 遵循WSIG规范,uwsgi + nginx - manage.py # 管理Django程序:
manage命令
manage.py runserver 0.0.0.0 python manage.py startapp appname python manage.py syncdb python manage.py makemigrations python manage.py migrate python manage.py createsuperuser
APP 目录
创建app:python manage.py startapp app_name
migrations: 数据库操作记录,只记录修改表结构记录,不包括插入等 admin: django提供的后台管理 apps: 配置当前app models: ORM,写指定的类,通过命令可以创建数据结构 tests: 单元测试 views: 业务代码
配置
创建完project,做如下配置
1、配置模板的路径
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ],},},]
2、配置静态目录,在setting文件最下面
STATICFILES_DIRS = ( os.path.join(BASE_DIR, 'static'),) <!-- 引用静态文件--> <img class="logo left" src='/static/in.png' alt="Logo">
3、数据库
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME':'dbname', 'USER': 'root', 'PASSWORD': 'xxx', 'HOST': '', 'PORT': '', } } # 由于Django内部连接MySQL时使用的是MySQLdb模块,而python3中还无此模块,所以需要使用pymysql来代替 # 如下设置放置的与project同名的配置的 __init__.py文件中 import pymysql pymysql.install_as_MySQLdb()
MTV模式
Model:数据库,负责业务对象与数据库的对象(ORM) Template: 模板文件,负责如何把页面展示给用户 View: 业务处理,负责业务逻辑,并在适当的时候调用Model和Template urls分发器:将一个个URL的页面请求分发给不同的view处理,view再调用相应的Model和Template
实例
1 from django.shortcuts import render 2 from django.shortcuts import HttpResponse 3 from django.shortcuts import render 4 from django.shortcuts import redirect 5 # Create your views here. 6 7 user_list = [ 8 {'username':'a','email':'aaaaaa','gender':'M'}, 9 {'username':'b','email':'bbbbbb','gender':'M'}, 10 {'username':'c','email':'cccccc','gender':'F'} 11 ] 12 13 14 def home(request): 15 if request.method == "POST": 16 u = request.POST.get('username') 17 e = request.POST.get('email') 18 g = request.POST.get('gender') 19 temp = {"username":u,"email":e,"gender":g} 20 user_list.append(temp) 21 return render(request,'home.html',{'user_list':user_list}) 22 23 def login(request): 24 # 'django.middleware.csrf.CsrfViewMiddleware' 在setting中需要注释掉这一项,否则提交表单时会出错 25 #第一种打开html文件方式 26 # f = open('templates/login.html','r',encoding='utf-8') 27 # data = f.read() 28 # f.close() 29 # return HttpResponse(data) 30 31 # 第2种打开html文件方式: 注意在setting需要配置template路径DIRS, 32 # TEMPLATES = [ 33 # { 34 # 'BACKEND': 'django.template.backends.django.DjangoTemplates', 35 # 'DIRS': [os.path.join(BASE_DIR, 'templates')], 36 # }, 37 # ] 38 error_msg = '' 39 if request.method=="POST": 40 user = request.POST.get('user',None) 41 pwd = request.POST.get("password",None) 42 if user=='root' and pwd == '123': 43 # 跳转到百度 44 # return redirect('www.baidu.com') 45 return redirect('/home') 46 else: 47 # 用户密码不匹配 48 error_msg = 'user or password error' 49 50 51 return render(request, 'login.html',{'error_msg':error_msg})
1 from django.contrib import admin 2 from django.urls import path 3 from django.shortcuts import HttpResponse 4 5 from cmdb import views 6 7 8 9 10 urlpatterns = [ 11 path('admin/', admin.site.urls), 12 path('login', views.login), 13 path('home', views.home), 14 ]
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <link rel="stylesheet" href="/static/comments.css"/> <title>Title</title> <style> label{ width:80px; text-align:right; display:inline-block; } </style> </head> <body> <form action="/login" method="post"> <p> <label for="username">用户名:</label> <input id="username" type="text" name="user" /> </p> <p> <label for="password">密 码:</label> <input id="password" type="text" name="password" /> <input type="submit" value="提交"/> <span style="color: red;">{{error_msg}}</span> </p> </form> <script src="/static/jquery-1.12.4.js"></script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div> <form action="/home" method="post"> <input type="text" name="username" /> <input type="text" name="email" /> <input type="text" name="gender" /> <input type="submit" value="添加" /> </form> </div> <div> <table> {% for row in user_list %} <tr> <td>{{row.username}}</td> <td>{{row.gender}}</td> <td>{{row.email}}</td> </tr> {% endfor %} </table> </div> </body> </html>
注:
- 'django.middleware.csrf.CsrfViewMiddleware' 在setting中需要注释掉这一项,否则提交表单时会出错
- redirect('http://www.baidu.com') 重定向,只能填url;如果填本地url,则为/login,加斜杠
- render(request, 'login.html',{'error_msg':error_msg}) 返回HTML文件
- <span style="color: red;">{{error_msg}}</span> error_msg相当于一个变量
- <form action="/login" method="post"> 和 path('login',views.login): login后面要一样,要不都为login/,要不都为login
路由系统
https://docs.djangoproject.com/en/1.11/topics/http/urls/
https://docs.djangoproject.com/en/2.0/topics/http/urls/
URL配置(URLconf)就像Django 所支撑网站的目录,是URL与视图函数之间的映射表。
语法
# Django 1.1 from django.conf.urls import url urlpatterns = [ url(正则表达式, views视图函数,参数,别名), ] # Django 2.0 from django.urls import path urlpatterns = [ path(正则表达式, views视图函数,参数,别名), ] # 正则表达式: 一个正则表达式字符串 # views视图函数: 一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串 # 参数: 可选的要传递给视图函数的默认参数(字典形式) # 别名: 一个可选的name参数
单一路由对应
from django.urls import path from cmdb import views urlpatterns = [ path('teststate',views.testState), ]
基于正则的路由
path('^index/(d*)', views.index), path('^manage/(?Pw*)/(?Pd*)', views.manage), # urlpatterns中的元素按照书写顺序从上往下逐一匹配正则表达式,一旦匹配成功则不再继续。 # 不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles。
APPEND_SLASH配置
Django settings.py配置文件中默认没有 APPEND_SLASH 这个参数,但 Django 默认这个参数为 APPEND_SLASH = True。 其作用就是自动在网址结尾加 '/' 。
from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^blog/$', views.blog), ] # 访问 http://www.example.com/blog 时,默认将网址自动转换为 http://www.example/com/blog/ 。 # 如果在settings.py中设置了 APPEND_SLASH=False,此时我们再请求 http://www.example.com/blog 时就会提示找不到页面。
分组命名匹配
使用分组命名匹配的正则表达式组来捕获URL中的值并以关键字参数形式传递给视图。
# 在Python的正则表达式中,分组命名正则表达式组的语法是(?P<name>pattern), # name是组的名称 # pattern是要匹配的模式。 path('^manage/(?Pw*)/(?Pd*)', views.manage),
对于Django2.0以后,urls.py配置不同,如果使用正则匹配,需要导入re_path
from django.urls import path, re_path urlpatterns = [ path(r'admin/', admin.site.urls), re_path(r'test/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})', views.test),]
正则表达式分组匹配(通过圆括号)来捕获URL中的值并以位置参数形式传递给视图。
url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
在views 函数中,应当注意形参
def testState(request, *args, **kwagrs):
URLconf 在请求的URL 上查找,将它当做一个普通的Python 字符串。不包括GET和POST参数以及域名。
# http://www.example.com/myapp/ 请求中,URLconf 将查找myapp/。 # 在http://www.example.com/myapp/?page=3 请求中,URLconf 仍将查找myapp/。 # URLconf 不检查请求的方法。换句话讲,所有的请求方法 —— 同一个URL的POST、GET、HEAD等等 —— 都将路由到相同的函数
捕获的参数是字符串
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive), # 传递到视图函数views.year_archive() 中的year 参数永远是一个字符串类型。
视图函数中指定默认值
from django.conf.urls import url from . import views urlpatterns = [ url(r'^blog/$', views.page), url(r'^blog/page(?P<num>[0-9]+)/$', views.page), ] # views.py中,可以为num指定默认值 def page(request, num="1"): pass # 第一个模式并没有从URL中捕获任何东西。 # 如果第一个模式匹配上了,page()函数将使用其默认参数num=“1”,如果第二个模式匹配,page()将使用正则表达式捕获到的num值。
添加额外的参数
django.conf.urls.url() 函数可以接收一个可选的第三个参数,它是一个字典,表示想要传递给视图函数的额外关键字参数。
path(r'^manage/(?P<name>w*)', views.manage,{'id':333}), # Django 将调用views.manage(request, name=string, id=333')。
路由映射设置名称
pathl(r'^home', views.home, name='home'), # url匹配模式起名为 home pathl(r'^index/(d*)', views.index, name='index'), # url匹配模式起名为index
设置名称后,通过如下方式调用:
# 模板中使用生成URL {% url 'index' 2012 %} 固定URL:2012 或 {{request.path_info}} 提交表单后返回当前url路径 # 函数中使用生成URL reverse('index', args=(2012,)) 路径:django.urls.reverse # Model中使用获取URL 自定义get_absolute_url() 方法 class NewType(models.Model): caption = models.CharField(max_length=16) def get_absolute_url(self): """ 为每个对象生成一个URL 应用:在对象列表中生成查看详细的URL,使用此方法即可!!! :return: """ # return '/%s/%s' % (self._meta.db_table, self.id) # 或 from django.urls import reverse return reverse('NewType.Detail', kwargs={'nid': self.id}) # 使用获取URL 自定义get_absolute_url() 方法
生成路径:
url(r'^test1',views.test, name='t1') url(r'^test2/(d+)/(d+)/',views.test, name='t2') url(r'^test3/(?P(pid)d+)/(?P(nid)d+)/',views.test, name='t3') def func(request, *args, **kwargs): from django.urls import reverse url1 = reverse('t1') # test1/ url2 = reverse('t2', args=(1,2,)) # test2/1/2/ url3 = reverse('t3', kwagrs=('pid':1, 'nid':2)) # test3/1/2/ # html # {% url 't1' %} # {% url 't2' 1,2 %} # {% url 't3' pid=1 nid=2%}
获取请求匹配成功的URL信息: request.resolver_match
对路由进行分类
根据app对路由规则进行分类
url(r'^web/',include('web.urls')), # 可以包含其他的URLconfs文件
命名空间
即使不同的APP使用相同的URL名称,URL的命名空间模式也可以让你唯一反转命名的URL。
# project中的urls.py from django.conf.urls import url, include urlpatterns = [ url(r'^app01/', include('app01.urls', namespace='app01')), url(r'^app02/', include('app02.urls', namespace='app02')), ] # app01中的urls.py from django.conf.urls import url from app01 import views app_name = 'app01' urlpatterns = [ url(r'^(?P<pk>d+)/$', views.detail, name='detail') ] # app02中的urls.py from django.conf.urls import url from app02 import views app_name = 'app02' urlpatterns = [ url(r'^(?P<pk>d+)/$', views.detail, name='detail') ]
以上定义带命名空间的url之后,使用name生成URL时候,应该如下:
# 模板中使用: {% url 'app01:detail' pk=12 %} # views中的函数中使用 v = reverse('app01:detail', kwargs={'pk':11})
视图
request.GET request.POST request.FILES return HttpResponse("字符串") return render(request, "HTML模板的路径") return redirect('/只能填URL')
获取单选框内容
获取input radio 等单选的内容:
request.POST.get("radio_name")
获取复选框内容
获取checkbox等多选的内容,内容为一个列表:
request.POST.getlist('checkbox_name')
上传文件
上传文件,form标签做特殊设置:加上属性enctype="multipart/form-data",如果不加这项属性,默认发的不是文件,则request.FILES.get()为None.
obj = request.FILES.get() obj.name f = open(obj.name, 'wb') for item in obj.chunks(): f.write(item) f.close
实例
views:
def login(request): if request.method == "GET": return render(request, 'login.html') elif request.method == "POST": v = request.POST.get('gender')
v = request.POST.getlist('favor')
obj = request.FILES.get('fa') print(obj,type(obj),obj.name) import os file_path = os.path.join('upload', obj.name) f = open(file_path, mode="wb") for i in obj.chunks(): f.write(i) f.close() return render(request, 'login.html') else: return redirect('/index/')
HTML
<form action="/login/" method="POST" enctype="multipart/form-data"> <p> <input type="text" name="user" placeholder="用户名" /> </p> <p> <input type="password" name="pwd" placeholder="密码" /> </p> <p> 男:<input type="radio" name="gender" value="1"/> 女:<input type="radio" name="gender" value="2"/> </p> <p> 男:<input type="checkbox" name="favor" value="11"/> 女:<input type="checkbox" name="favor" value="22"/> </p> <p> <select name="city" multiple> <option value="sh">上海</option> <option value="bj">北京</option> <option value="tj">天津</option> </select> </p> <p> <input type="file" name="fa"/> </p> <input type="submit" value="提交"/> </form>
FBV
FBV:function base view
url.py: index => 函数名 view.py: def 函数(request)
CBV
CBV:class base view
url.py: index => 类 匹配到url后,先调用dispatch方法,再判断get or post继续执行
views:接收到请求后,会先调用dispach方法
from django.views import View class Home(View): def dispatch(self, request, *args, **kwargs): result = super(Home,self).dispatch(request, *args, **kwargs) return result def get(self,request): return render(request,'home.html') def post(self,request): return render(request, 'home.html')
url:
from cmdb import views urlpatterns = [ path('home', views.Home.as_view()), ]
模板
https://docs.djangoproject.com/en/1.11/ref/templates/builtins/#std:templatetag-for
两个符号
<!-- {{}}: 变量相关 --> <!-- {% %}: 逻辑相关 -->
变量
1、在Django的模板语言中按此语法使用:{{ 变量名 }}。 2、当模版引擎遇到一个变量,它将计算这个变量,然后用结果替换掉它本身。 3、变量的命名包括任何字母数字以及下划线 ("_")的组合。 变量名称中不能有空格或标点符号。 4、点(.)在模板语言中有特殊的含义。当模版系统遇到点("."),它将以这样的顺序查询: 字典查询 属性或方法查询 数字索引查询 1、如果计算结果的值是可调用的,它将被无参数的调用。 调用的结果将成为模版的值。 2、如果使用的变量不存在, 模版系统将插入 string_if_invalid 选项的值, 它被默认设置为'' (空字符串) 。
实例
def template_test(request):
l = [11, 22, 33]
d = {"name": "alex"}
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def dream(self):
return "{} is dream...".format(self.name)
Alex = Person(name="Alex", age=34)
Egon = Person(name="Egon", age=9000)
Eva_J = Person(name="Eva_J", age=18)
person_list = [Alex, Egon, Eva_J]
return render(request, "template_test.html", {"l": l, "d": d, "person_list": person_list})
1 <body> 2 <!--{# 取l中的第一个参数 #}--> 3 {{ l.0 }} 4 <br /> 5 {# 取字典中key的值 #} 6 {{ d.name }} 7 <br /> 8 {# 取对象的name属性 #} 9 {{ person_list.0.name }} 10 <br /> 11 {# .操作只能调用不带参数的方法 #} 12 {{ person_list.0.dream }} 13 </body>
Filters:过滤器
在Django的模板语言中,通过使用过滤器来改变变量的显示。
语法:使用管道符"|"来应用过滤器。
# {{ value|filter_name:参数 }} {{ name|lower }} # 会将name变量应用lower过滤器之后再显示它的值。lower在这里的作用是将文本全都变成小写。
注意
- 过滤器支持“链式”操作。即一个过滤器的输出作为另一个过滤器的输入。
- 过滤器可以接受参数,例如:{{ sss|truncatewords:30 }},这将显示sss的前30个词。
- 过滤器参数包含空格的话,必须用引号包裹起来。比如使用逗号和空格去连接一个列表中的元素,如:{{ list|join:', ' }}
- '|'左右没有空格没有空格没有空格
Django内置过滤器
default
# 如果一个变量是false或者为空,使用给定的默认值。 否则,使用变量的值。 {{ value|default:"nothing"}}
length
# 返回值的长度,作用于字符串和列表。 {{ value|length }} # 返回value的长度,如 value=['a', 'b', 'c', 'd']的话,就显示4.
filesizeformat
# 将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等)。 {{ value|filesizeformat }} # 如果 value 是 123456789,输出将会是 117.7 MB。
slice
# 切片 {{value|slice:"2:-1"}}
date
# 格式化时间 {{ value|date:"Y-m-d H:i:s"}}
truncatechars
# 如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。 # 参数:截断的字符数 {{ value|truncatechars:9}}
truncatewords
# 在一定数量的字后截断字符串。 {{ value|truncatewords:9}}
cut
# 移除value中所有的与给出的变量相同的字符串 {{ value|cut:' ' }} # 如果value为'i love you',那么将输出'iloveyou'.
join
# 使用字符串连接列表,例如Python的str.join(list)
自定义filter
自定义过滤器只是带有一个或两个参数的Python函数:
# 变量(输入)的值 - -不一定是一个字符串 # 参数的值 - 这可以有一个默认值,或完全省略 # 例如,在过滤器{{var | foo:'bar'}}中,过滤器foo将传递变量var和参数“bar”。
在哪定义filter代码:
app01/ __init__.py models.py templatetags/ # 在app01下面新建一个package package __init__.py app01_filters.py # 建一个存放自定义filter的文件 views.py
如何编写自定义filter
from django import template register = template.Library() @register.filter(name="say_hello") def say_hello(value): return "hello {}".format(value)
如何使用自定义filter
{# 先导入我们自定义filter那个文件 #} {% load app01_filters %} {# 使用我们自定义的filter #} {{ d.name|say_hello }}
for循环
<ul> {% for user in user_list %} <li>{{ user.name }}</li> {% endfor %} </ul>
for ... empty
<ul> {% for user in user_list %} <li>{{ user.name }}</li> {% empty %} <li>空空如也</li> {% endfor %} </ul>
for语句在模板里的应用
for循环与table结合使用:在html中获取字典或列表里面的值,可以通过row.key或row.1等方式获得
# views代码 user_list = [ {'username':'a','email':'aaaaaa','gender':'M'}, {'username':'b','email':'bbbbbb','gender':'M'}, {'username':'c','email':'cccccc','gender':'F'} ] return render(request,'home.html',{'user_list':user_list}) # HTML <table> {% for row in user_list %} <tr> <td>{{row.username}}</td> <td>{{row.gender}}</td> <td>{{row.email}}</td> </tr> {% endfor %} </table>
模板语言访问字典
USER_DICT = { '1': {'name': 'root1', 'email': 'root@live.com'}, '2': {'name': 'root2', 'email': 'root@live.com'}, } # HTML {{user_dict.k1}} {%for k,v in user_dict.items%} <li><{{k}}-{{v}}/li> {%endfor%} {%for k in user_dict.keys%} <li><{{k}}/li> {%endfor%} {%for v in user_dict.values%} <li><{{v}}/li> {%endfor%}
条件判断
if ... else/ if ... elif ... else
{% if user_list %}
用户人数:{{ user_list|length }}
{% elif black_list %}
黑名单数:{{ black_list|length }}
{% else %}
没有用户
{% endif %}
注: if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断。
with
定义一个中间变量,多用于给一个复杂的变量起别名。
{% with total=business.employees.count %}
{{ total }} employee{{ total|pluralize }}
{% endwith %}
{% with business.employees.count as total %}
{{ total }} employee{{ total|pluralize }}
{% endwith %}
注: 等号左右不要加空格。
注释
{# ... #}
模板语言注意事项
1. Django的模板语言不支持连续判断,即不支持以下写法 {% if a > b > c %} ... {% endif } % 2. Django的模板语言中属性的优先级大于方法 def xx(request): d = {"a": 1, "b": 2, "c": 3, "items": "100"} return render(request, "xx.html", {"data": d}) 如上,我们在使用render方法渲染一个页面的时候,传的字典d有一个key是items并且还有默认的 d.items() 方法,此时在模板语言中: {{ data.items }}{{ data.items }},默认会取d的items key的值。
ORM操作
对象关系映射(Object Relational Mapping,简称ORM)模式通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。
ORM在业务逻辑层和数据库层之间充当了桥梁的作用。
Django中ORM的配置
https://docs.djangoproject.com/en/2.0/topics/db/queries/
setting.py文件配置:
DATABASES = { "default": { "ENGINE": "django.db.backends.mysql", "NAME": "你的数据库名称", # 需要自己手动创建数据库 "USER": "数据库用户名", "PASSWORD": "数据库密码", "HOST": "数据库IP", "POST": 3306 } }
Django项目的__init__.py文件配置:
# 由于Django内部连接MySQL时使用的是MySQLdb模块,而python3中还无此模块,所以需要使用pymysql来代替 # 如下设置放置的与project同名的配置的 __init__.py文件中 import pymysql pymysql.install_as_MySQLdb()
字段
AutoField: int自增列,必须填入参数 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=True BigAutoField(AutoField) - bigint自增列,必须填入参数 primary_key=True 注:当model中如果没有自增列,则自动会创建一个列名为id的列 from django.db import models class 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 ~ 32767 PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) - 正小整数 0 ~ 32767 IntegerField(Field) - 整数列(有符号的) -2147483648 ~ 2147483647 PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) - 正整数 0 ~ 2147483647 BigIntegerField(IntegerField): - 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807 自定义无符号整数字段 class UnsignedIntegerField(models.IntegerField): def db_type(self, connection): return 'integer UNSIGNED' PS: 返回值为字段在数据库中的属性,Django字段默认的值为: '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)', BooleanField(Field) - 布尔值类型 NullBooleanField(Field): - 可以为空的布尔值 CharField(Field) - 字符类型 - 必须提供max_length参数, 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, 'both',"ipv4","ipv6" unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启刺功能,需要protocol="both" URLField(CharField) - 字符串类型,Django Admin以及ModelForm中提供验证 URL SlugField(CharField) - 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号) CommaSeparatedIntegerField(CharField) - 字符串类型,格式必须为逗号分割的数字 UUIDField(Field) - 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证 FilePathField(Field) - 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能 - 参数: path, 文件夹路径 match=None, 正则匹配 recursive=False, 递归下面的文件夹 allow_files=True, 允许文件 allow_folders=False, 允许文件夹 FileField(Field) - 字符串,路径保存在数据库,文件上传到指定目录 - 参数: upload_to = "" 上传文件的保存路径 storage = None 存储组件,默认django.core.files.storage.FileSystemStorage ImageField(FileField) - 字符串,路径保存在数据库,文件上传到指定目录 - 参数: upload_to = "" 上传文件的保存路径 storage = None 存储组件,默认django.core.files.storage.FileSystemStorage width_field=None, 上传图片的高度保存的数据库字段名(字符串) height_field=None 上传图片的宽度保存的数据库字段名(字符串) DateTimeField(DateField) - 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] DateField(DateTimeCheckMixin, Field) - 日期格式 YYYY-MM-DD TimeField(DateTimeCheckMixin, Field) - 时间格式 HH:MM[:ss[.uuuuuu]] DurationField(Field) - 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型 FloatField(Field) - 浮点型 DecimalField(Field) - 10进制小数 - 参数: max_digits,小数总长度 decimal_places,小数位长度 BinaryField(Field) - 二进制类型
参数
null 用于表示某个字段可以为空。 unique 如果设置为unique=True 则该字段在此表中必须是唯一的 。 db_index 如果db_index=True 则代表着为此字段设置数据库索引。 default 为该字段设置默认值。
其他参数:
null 数据库中字段是否可以为空 db_column 数据库中字段的列名 db_tablespace default 数据库中字段的默认值 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': '格式错误'} validators 自定义错误验证(列表类型),从而定制想要的验证规则 from django.core.validators import RegexValidator from django.core.validators import EmailValidator,URLValidator,DecimalValidator, MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator 如: test = models.CharField( max_length=32, error_messages={ 'c1': '优先错信息1', 'c2': '优先错信息2', 'c3': '优先错信息3', }, validators=[ RegexValidator(regex='root_d+', message='错误了', code='c1'), RegexValidator(regex='root_112233d+', message='又错误了', code='c2'), EmailValidator(message='又错误了', code='c3'), ] )
元信息
class UserInfo(models.Model): nid = models.AutoField(primary_key=True) username = models.CharField(max_length=32) class Meta: # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名 db_table = "table_name" # 联合索引 index_together = [ ("pub_date", "deadline"), ] # 联合唯一索引 unique_together = (("driver", "restaurant"),) # admin中显示的表名称 verbose_name # verbose_name加s verbose_name_plural
拓展
1.触发Model中的验证和错误提示有两种方式: a. Django Admin中的错误信息会优先根据Admiin内部的ModelForm错误信息提示,如果都成功,才来检查Model的字段并显示指定错误信息 b. 调用Model对象的 clean_fields 方法,如: # models.py class UserInfo(models.Model): nid = models.AutoField(primary_key=True) username = models.CharField(max_length=32) email = models.EmailField(error_messages={'invalid': '格式错了.'}) # views.py def index(request): obj = models.UserInfo(username='11234', email='uu') try: print(obj.clean_fields()) except Exception as e: print(e) return HttpResponse('ok') # Model的clean方法是一个钩子,可用于定制操作,如:上述的异常处理。 2.Admin中修改错误提示 # admin.py from django.contrib import admin from model_club import models from django import forms class UserInfoForm(forms.ModelForm): username = forms.CharField(error_messages={'required': '用户名不能为空.'}) email = forms.EmailField(error_messages={'invalid': '邮箱格式错误.'}) age = forms.IntegerField(initial=1, error_messages={'required': '请输入数值.', 'invalid': '年龄必须为数值.'}) class Meta: model = models.UserInfo # fields = ('username',) fields = "__all__" class UserInfoAdmin(admin.ModelAdmin): form = UserInfoForm admin.site.register(models.UserInfo, UserInfoAdmin)
对应关系: '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)',
时间字段
DatetimeField、DateField、TimeField 这个三个时间字段,都可以设置如下属性。 auto_now_add 配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。 auto_now 配置上auto_now=True,每次更新数据记录的时候会更新该字段。 1. 下面方式修改数据auto_now不生效 # obj = UserGroup.objects.filter(id=1).update(caption='CEO') 2. 使auto_now生效使用如下: # obj = UserGroup.objects.filter(id=1).first() # obj.caption = "CEO" # obj.save()
连表结构
一对多:models.ForeignKey(其他表) user_group=models.ForeignKey('UserGroup',to_field='uid',default=1) 关联UserGroup表的uid字段 创建用户: models.UserInfo.objects.create(user_group=models.UserGroup.objects.filter(id=1).frist()) 或: models.UserInfo.objects.create(user_group_id=1) 外键查找关联表数据: uid=models.UserInfo.objects.filter(id=1).first().user_group_id 查找组id user_group=models.UserInfo.objects.filter(id=1).first().user_group 返回一个UserGroup对象,可查找UserGroup表的所有信息 多对多:models.ManyToManyField(其他表) 一对一:models.OneToOneField(其他表)
表的基本操作
# 增 # models.Tb1.objects.create(c1='xx', c2='oo') 增加一条数据,可以接受字典类型数据 **kwargs # obj = models.Tb1(c1='xx', c2='oo') # obj.save() # 查 # models.Tb1.objects.get(id=123) # 获取单条数据,不存在则报错(不建议) # data= models.Tb1.objects.all() # 获取全部数据,QuerySet类型,[obj1,obj2....]
data.query() # 将查询语句翻译成SQL查询语句 select * from tb # models.Tb1.objects.filter(name='seven') # 获取指定条件的数据 # models.Tb1.objects.all().values('字段1','字段2'...) # 获取全部数据,返回QuerySet类型[{'字段1':value,'字段2':value},{},{}] # models.Tb1.objects.all().values_list('字段1','字段2'..) # 获取全部数据,返回QuerySet类型[(value1,value2..),()...] # 删 # models.Tb1.objects.filter(name='seven').delete() # 删除指定条件的数据 # 改 # models.Tb1.objects.filter(name='seven').update(gender='0') # 将指定条件的数据更新,均支持 **kwargs # obj = models.Tb1.objects.get(id=1) # obj.c1 = '111' # obj.save() # 修改单条数据
操作表常用属性
all(): 查询所有结果 filter(**kwargs): 它包含了与所给筛选条件相匹配的对象 get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。 exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象 values(*field): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列 values_list(*field): 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列 order_by(*field): 对查询结果排序 reverse(): 对查询结果反向排序,请注意reverse()通常只能在具有已定义顺序的QuerySet上调用(在model类的Meta中指定ordering或调用order_by()方法)。 distinct(): 从返回结果中剔除重复纪录(如果你查询跨越多个表,可能在计算QuerySet时得到重复的结果。此时可以使用distinct(),注意只有在PostgreSQL中支持按字段去重。) count(): 返回数据库中匹配查询(QuerySet)的对象数量。 first(): 返回第一条记录,若没有则为None。可以和filter结合起来使用 last(): 返回最后一条记录 exists(): 如果QuerySet包含数据,就返回True,否则返回False
参考:
https://www.cnblogs.com/liwenzhou/p/9959979.html