Django基础
一、Django 简介
Django 是一个由 Python 写成的开放源代码的 Web 应用框架。它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的,即是 CMS(内容管理系统)软件。并于2005年7月在 BSD 许可证下发布。这套框架是以比利时的吉普赛爵士吉他手 Django Reinhardt 来命名的。由于 Django 的是在一个快节奏的新闻编辑室环境下开发的,它的目的是使常见的 Web 开发任务,快速和容易。
特点:
mvc 设计模式:
上述图大概是说:
- URL ( urls.py )请求调度,当有缓存页面的时候直接返回内容。
- 视图函数( view.py )执行所请求的操作,通常包括读写数据库。
- 模型( models.py )定义了 Python 中的数据并与之交互。通常包含在一个关系数据库( MySQL、PostgreSQL SQLite 等),其他数据存储是可能的( XML、文本文件、LDAP、等)。
- 请求执行任务后,视图返回一个 HTTP 响应对象(通常是经过数据处理的一个模板)。可选的:视图可以保存一个版本的 HTTP 响应对象,返回携带一个时间戳,来告诉浏览器这个视图的更新时间。
- 模板通常返回 HTML 页面。Django 模板语言提供了 HTML 的语法及逻辑。
二、安装
# pip 安装 pip install Django==1.10 # 克隆下载最新版本 git clone https://github.com/django/django.git # 导入django模块 >>> import django >>> print(django.get_version()) 1.10
三、基本配置
1.创建django程序
终端命令:django-admin startproject sitename IDE创建Django程序时,本质上都是自动执行上述命令 其他常用命令: python 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
2.程序目录
3.setting配置文件
a、静态文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 在settings里修改添加,放css,js,image等文件 # 创建static文件夹 STATIC_URL = '/static/' # 相当于别名 STATICFILES_DIRS = ( os.path.join(BASE_DIR,'static'), ) # 如引用Jquery文件,有俩种形式 1、 直接引入 2、 {% load staticfiles %} {% static '文件名' %} # 推荐使用第二种形式,第一条代码并处理引入文件代码的上方 # 再每个app里面我们可能会有多个文件配置信息,则可以相应的将文件夹放在app的文件夹下,并修改路径。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 注意1: # 为了后端的更改不会影响前端的引入,避免造成前端大量修改 STATIC_URL = '/static/' # 引用名 STATICFILES_DIRS = ( os.path.join(BASE_DIR,"statics"), # 实际名 ,即实际文件夹的名字 ) # django对引用名和实际名进行映射,引用时,只能按照引用名来,不能按实际名去找 # <script src="/statics/jquery-3.1.1.js"></script> # ------error-----不能直接用,必须用STATIC_URL = '/static/': # <script src="/static/jquery-3.1.1.js"></script> # 注意2(statics文件夹写在不同的app下,静态文件的调用): STATIC_URL = '/static/' STATICFILES_DIRS=( ('hello',os.path.join(BASE_DIR,"app01","statics")), ) # <script src="/static/hello/jquery-1.8.2.min.js"></script> # 注意3: STATIC_URL = '/static/' {% load staticfiles %} # <script src={% static "jquery-1.8.2.min.js" %}></script> # 注意4: 配置STATIC路径时,记得要最后一个元组后面加逗号,不然会影响渲染 引入静态文件的注意点
b.、模板
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 在settings里修改,放html文件 TEMPLATE_DIRS = ( os.path.join(BASE_DIR,'templates'), )
c、数据库配置
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# django支持sqlite,mysql, oracle,postgresql数据库 # django默认使用sqlite的数据库,默认自带sqlite的数据库驱动 , 引擎名称:django.db.backends.sqlite3 # 由于Django内部连接MySQL时使用的是MySQLdb模块,而python3中还无此模块,所以需要使用pymysql来代替 # 设置放置的与project同名的配置的 __init__.py文件中 import pymysql pymysql.install_as_MySQLdb() # 在settings 中修改DATABASES DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'dbname', # 数据库名称 'USER': 'root', # 用户名 'PASSWORD': 'xxx', # 密码 'HOST': '', # IP,留空默认localhost 'PORT': '', # 端口 } }
###
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 由于Django内部连接MySQL时使用的是MySQLdb模块,而python3中还无此模块,所以需要使用pymysql来代替
# 如下设置放置的与project同名的配置的 __init__.py文件中
import pymysql
pymysql.install_as_MySQLdb()
四、路由系统
1.URL调度
一个干净,优雅的 URL 方案是一个高质量的 Web 应用程序的一个重要的细节。与 tornado 不同的是一个 url 对应一个函数,而并非一个类。
像是一个新华字典的目录,对应了 views 函数来进行处理,即这个 url 要用某个指定的 views 函数处理。
来看以下示例,如何动态构造
urlpatterns = [
url(正则表达式, views视图函数,参数,别名),
}
# 参数说明
# 一个正则表达式字符串
# 一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串
# 可选的要传递给视图函数的默认参数(字典形式)
# 一个可选的name参数
from app1 import views urlpatterns = [ url(r'^manage1/(\d*)', views.manage1), url(r'^manage2/(?P<name>\w*)/(?P<id>\d*)', views.manage2), url(r'^manage3/(?P<name>\w*)', views.manage3,{'id':333}), ] # 需要注意 # url多传了一个参数,那views函数得多接受一个参数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 对应接收值 def manage1(request, age): print(age) # 18 return HttpResponse('1') def manage2(request, name, id): print(name, id) # nick 18 return HttpResponse('2') def manage3(request, name, id): print(name, id) # nick 666 return HttpResponse('3') 对应 views 函数接收值
二级路由: 那如果映射 url 太多怎么办,全写一个在 urlpatterns 显得繁琐,so 二级路由应用而生
# 一级路由规定 app1 开头的都去 app1.urls 中找 # 二级在详细规定对应 views 函数 # 一级 urlpatterns = [ url(r'^app1/', include('app1.urls')), ] # 二级 urlpatterns = [ url(r'^1$', views.manage1), ]
2、Django是如何处理一个请求***
当用户请求从您的 Django 的网站页面,这是该系统遵循以确定哪些 Python 代码执行的算法:
- Django 请求是 URL 配置模块配置。通常通过值 ROOT_URLCONF 设置,但如果传入 HttpRequest 对象具有 urlconf 属性(由中间件设置),它的值将代替的可以使用 ROOT_URLCONF 的设置。
- Django 的负载是 Python 模块并寻找变量 urlpatterns。这是一个 django.conf.urls.url() 实例。
- Django 的贯穿每个 URL 模式,从而,在所请求的 URL 匹配的第一个停止。
- 一旦某个正则表达式相匹配,就运行相对应的视图函数(或基于类的视图)。该视图被传递以下参数:
- HttpRequest 对象。
- 如果匹配的正则表达式没有返回命名组,然后从正则表达式比赛是作为位置参数。
- 关键词参数是由由正则表达式匹配的任何命名组,由指定的可选参数的任何覆盖的 kwargs参数 django.conf.urls.url()。
- 如果没有正则表达式匹配,或者如果一个异常在这个过程中的任何一点时提出,Django的调用适当的错误处理视图。
3、官方示例
1> 以下代码是官方示例:
from django.conf.urls import url from . import views urlpatterns = [ url(r'^articles/2003/$', views.special_case_2003), url(r'^articles/([0-9]{4})/$', views.year_archive), url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive), url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail), ]
注意事项:
- 要捕获从URL中的值,用括号括起来,会当参数传入 views 视图。
- 没有必要添加一个斜线,因为每个URL都有。例如,它
^articles
不是^/articles
。 - 在
'r'
前面的每个正则表达式字符串中是可选的,但建议。它告诉Python字符串是“原始” -没有什么字符串中应该进行转义。
举例请求:
- 请求
/articles/2005/03/
将匹配列表中的第三项。Django的将调用该函数 。views.month_archive(request,'2005', '03')
/articles/2005/3/
不会匹配任何 URL 模式,因为在列表中的第三项中需要两位数字的月份。/articles/2003/
将匹配的列表,而不是第二个第一图案,因为该图案,以便测试,第一个是在第一测试通过。随意利用顺序插入特殊情况是这样的。在这里,Django的将调用该函数views.special_case_2003(request)
/articles/2003
不匹配任何这些模式,因为每个模式要求 URL 以斜线结束。/articles/2003/03/03/
将匹配的最终格局。Django 的将调用该函数。views.article_detail(request,'2003', '03', '03')
2> 命名组
上面的例子使用了简单的,非命名的正则表达式组(通过括号)来捕获 URL 的位,并通过他们的位置参数的视图。在更高级的用法,它可以使用命名 正则表达式组来捕获 URL 位,将它们作为关键字参数传递给视图。
在 Python 正则表达式,命名正则表达式组的语法(?P<name>pattern)
,这里 name
是组的名称, pattern
就是某种模式相匹配。
下面是上面的例子中的URLconf,改写使用命名组:
from django.conf.urls import url from . import views urlpatterns = [ url(r'^articles/2003/$', views.special_case_2003), url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive), url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive), url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail), ]
这正好完成同样的事情,前面的例子,一个细微的差别:捕获的值传递给查看功能作为关键字参数,而不是位置参数。例如:
- 请求
/articles/2005/03/
会调用函数来代替,views.month_archive(request, year='2005',month='03')
views.month_archive(request, '2005', '03')
- 请求
/articles/2003/03/03/
会调用该函数,views.article_detail(request, year='2003',month='03', day='03')
在实践中,这意味着你的 URLconf 稍微更明确,不容易参数顺序错误 - 你可以在你的意见'函数定义重新排序的参数。当然,这些优点来在简短的费用; 一些开发任务命名组的语法丑陋,太冗长。
匹配/分组算法
这里的URL配置解析器遵循算法,相对于正则表达式命名组与非命名组:
- 如果有任何命名参数,它会使用这些,而忽略非命名参数。
- 否则,它会通过所有非命名参数作为位置参数。
在这两种情况下,被赋予按任何额外的关键字参数传递额外的选项来查看功能也将被传递给视图
3> What the URLconf searches against
The URLconf searches against the requested URL, as a normal Python string. This does not include GET or POST parameters, or the domain name.
For example, in a request to https://www.example.com/myapp/
, the URLconf will look for myapp/
.
In a request to https://www.example.com/myapp/?page=3
, the URLconf will look for myapp/
.
该URL配置不看请求方法。换言之,所有的请求的方法,GET,POST 等将被路由到为相同的URL,相同的功能。
4> 捕获的参数总是字符串
每个捕获的参数发送到视图作为普通的 Python 字符串,无论什么样的匹配正则表达式匹配。
例如,在该URL配置行:
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
...的 year
参数传递给 views.year_archive()
将是一个字符串,
不是一个整数,即使 [0-9]{4}
将只匹配整数字符串。
5> 指定view的默认设置
一个方便的技巧是你的观点的论据指定默认参数。下面是一个例子的 RLconf 和看法:
# URLconf 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), ] # View (in blog/views.py) def page(request, num="1"): # Output the appropriate page of blog entries, according to num. ...
在上述的例子中,两个 URL 模式指向同一个视图 views.page
但第一图案不捕获从 URL 任何东西。如果第一个模式匹配,该 page()
函数将使用它的默认参数 num
,"1"
。如果第二图案相匹配时, page()
将使用任何 num
值由正则表达式捕获。
6> 包括其他的URLconf
在任何时候,你urlpatterns
可以“include”其他的URLconf模块。这实质上是“roots”的一套低于其他的网址。
例如,这里的URL配置为节选的Django网站 本身。它包括许多其他的URLconf的:
from django.conf.urls import include, url urlpatterns = [ # ... snip ... url(r'^community/', include('django_website.aggregator.urls')), url(r'^contact/', include('django_website.contact.urls')), # ... snip ... ]
请注意,在这个例子中,正则表达式没有一个$
(结束字符串匹配字符),但包括尾随斜线。每当 Django 的遇到 include()
(django.conf.urls.include()
),它扒关闭任何匹配到该点的URL的一部分,并将剩余的字符串所包含的URL配置用于进一步的处理。
另一种可能性是通过使用的列表,以包括另外的网址格式 url()
实例。例如,考虑这个 URL 配置:
from django.conf.urls import include, url from apps.main import views as main_views from credit import views as credit_views extra_patterns = [ url(r'^reports/$', credit_views.report), url(r'^reports/(?P<id>[0-9]+)/$', credit_views.report), url(r'^charge/$', credit_views.charge), ] urlpatterns = [ url(r'^$', main_views.homepage), url(r'^help/', include('apps.help.urls')), url(r'^credit/', include(extra_patterns)), ]
在这个例子中,/credit/reports/
URL将被处理 credit_views.report()
的Django图。
从其中单个图案前缀被重复使用的URLconf去除冗余。
我们可以通过声明的共同路径前缀只有一次,分组,例如这个URL配置:
from django.conf.urls import include, url from . import views urlpatterns = [ url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/', include([ url(r'^history/$', views.history), url(r'^edit/$', views.edit), url(r'^discuss/$', views.discuss), url(r'^permissions/$', views.permissions), ])), ]
7> 传递额外的选项来查看功能
URLconf 有一个挂钩,可以传递额外的参数给您的视图功能,作为一个 Python 字典。
该django.conf.urls.url()
功能可以采取这应该是额外的参数的字典传递给视图功能可选的第三个参数。
例如:
from django.conf.urls import url from . import views urlpatterns = [ url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}), ]
在这个例子中,用于向请求/blog/2005/
,Django会调用 。views.year_archive(request, year='2005',foo='bar')
# 处理冲突 这可能有它可以捕获一个名为关键字参数的URL模式,并且还传递参数,在其额外的参数字典相同的名称。
发生这种情况时,在字典中的参数将被用来代替在URL捕获的参数。
传递额外的选项来 include()
同样,您可以通过额外的选项include()
。当你通过额外的选项include()
,每个中所包含的URL配置线将通过额外的选项。
例如,这两个URL配置集在功能上是相同的:
# 设置一个: # main.py from django.conf.urls import include, url urlpatterns = [ url(r'^blog/', include('inner'), {'blogid': 3}), ] # inner.py from django.conf.urls import url from mysite import views urlpatterns = [ url(r'^archive/$', views.archive), url(r'^about/$', views.about), ] # 设置两个 # main.py from django.conf.urls import include, url from mysite import views urlpatterns = [ url(r'^blog/', include('inner')), ] # inner.py from django.conf.urls import url urlpatterns = [ url(r'^archive/$', views.archive, {'blogid': 3}), url(r'^about/$', views.about, {'blogid': 3}), ]
五、视图层view(处理用户请求的逻辑)***
对逻辑负责处理用户的请求并返回响应。反回可以是HTML内容的网页,或重定向,或404错误,或一个XML文件,或一个形象......此代码可以住在任何你想去的地方,只要它在你的Python路径。
在一个文件中称将视图views.py
,放在项目或应用程序目录。
http请求中产生两个核心对象:http请求:HttpRequest对象 http响应:HttpResponse对象 所在位置:django.http
1、返回快捷功能
a、render()
render(request, template_name, context=None, content_type=None, status=None, using=None)[source]结合给定的模板与一个给定的上下文,返回一个字典HttpResponse在渲染文本对象
所需的参数
template_name 一个模板的使用或模板序列名称全称。如果序列是给定的,存在于第一个模板将被使用。
可选参数
context 一组字典的值添加到模板中。默认情况下,这是一个空的字典。
content_type MIME类型用于生成文档。
status 为响应状态代码。默认值为
200
using 这个名字一个模板引擎的使用将模板。
例子
from django.shortcuts import render def my_view(request): # View code here... return render(request, 'myapp/index.html', { 'foo': 'bar', }, content_type='application/xhtml+xml')
等价于
from django.http import HttpResponse from django.template import loader def my_view(request): # View code here... t = loader.get_template('myapp/index.html') c = {'foo': 'bar'} return HttpResponse(t.render(c, request), content_type='application/xhtml+xml')
b、redirect()
redirect(to, permanent=False, *args, **kwargs)[source]
默认情况下,为临时重定向;通过 permanent=True
设置永久重定向
def my_view(request): ... return redirect('/some/url/') def my_view(request): ... object = MyModel.objects.get(...) return redirect(object, permanent=True)
2、求和响应对象
Django 使用请求和响应对象在系统间传递状态。
当请求一个页面时,Django 创建一个 HttpRequest
对象包含原数据的请求。然后 Django 加载适当的视图,通过 HttpRequest
作为视图函数的第一个参数。每个视图负责返回一个HttpResponse
目标。
HttpRequest对象
HttpRequest.scheme一个字符串表示请求的方案(HTTP或HTTPS)通常HttpRequest.path
一个字符串的完整路径的请求HttpRequest.method
请求的HTTP方法。这是保证要大写 if request.method == 'GET': do_something() elif request.method == 'POST': do_something_else()HttpRequest.GET
字典像包含所有给定的HTTP GET参数对象。HttpRequest.POST
字典像包含所有给定的HTTP POST参数对象,提供请求包含表单数据。HttpRequest.COOKIES
一个标准的Python字典,包含了所有的COOKIES,key和values都是字符串HttpRequest.FILES
字典像对象包含所有上传的文件。 html 标签 <input type="file" name="" /> filename # 上传的文件名 content_type # 上传文件的类型 content # 上传文件的内容HttpRequest.META
一个标准的Python字典包含所有可用的HTTP头。可用标题取决于客户端和服务器,但这里是一些例子: CONTENT_LENGTH – 请求体的长度(一个字符串)。 CONTENT_TYPE – 请求体的类型。 HTTP_ACCEPT - 为响应–可以接受的内容类型。 HTTP_ACCEPT_ENCODING – 接受编码的响应 HTTP_ACCEPT_LANGUAGE – 接受语言的反应 HTTP_HOST – 客户端发送的HTTP主机头。 HTTP_REFERER – 参考页面 HTTP_USER_AGENT – 客户端的用户代理字符串。 QUERY_STRING – 查询字符串,作为一个单一的(分析的)字符串。 REMOTE_ADDR – 客户端的IP地址 REMOTE_HOST – 客户端的主机名 REMOTE_USER – 用户通过Web服务器的身份验证。 REQUEST_METHOD – 字符串,如"GET"或"POST" SERVER_NAME – 服务器的主机名 SERVER_PORT – 服务器的端口(一个字符串)。
HttpResponse对象
对于HttpRequest 对象来说,是由django自动创建的,但是,HttpResponse 对象就必须我们自己创建。每个 view 请求处理方法必须返回一个 HttpResponse 对象。
HttpResponse 类在 django.http.HttpResponse
字符串使用:
典型的用法是通过页面的内容,为一个字符串
>>> from django.http import HttpResponse >>> response = HttpResponse("Here's the text of the Web page.") >>> response = HttpResponse("Text only, please.", content_type="text/plain") # 如果你想添加内容的增量 >>> response = HttpResponse() >>> response.write("<p>Here's the text of the Web page.</p>") >>> response.write("<p>Here's another paragraph.</p>")
特性与方法:
HttpResponse.content一个bytestring代表内容HttpResponse.charset
一个字符串的字符集表示的响应将编码HttpResponse.status_code
HTTP状态代码为响应码HttpResponse.streaming
这个属性永远为假,一般用于中间件HttpResponse.closed
关闭方法:
HttpResponse.__init__(content='', content_type=None, status=200, reason=None, charset=None)[source]
实例化类自动执行的方法HttpResponse.__setitem__(header, value)
为给定值给定的标题名称。都是字符串HttpResponse.__delitem__(header)
删除标题的名称。不区分大小写。HttpResponse.__getitem__(header)
获取给定标题名称。不区分大小写。HttpResponse.has_header(header)
检查是否具有给定名称的一个标题HttpResponse.setdefault(header, value)
设置一个标题,除非它已经设置。HttpResponse.set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=None, httponly=False)
设置一个cookie。参数跟标准库的Cookie对象差不多HttpResponse.set_signed_cookie(key, value, salt='', max_age=None, expires=None, path='/', domain=None, secure=None, httponly=True)
加密cookice,可以用 HttpRequest.get_signed_cookie() 获取,当然你也可以加盐HttpResponse.delete_cookie(key, path='/', domain=None)
删除Cookie与给定键。HttpResponse子类:
class HttpResponseRedirect[source]
构造函数的第一个参数是必需的–路径redirectto。这是一个完全合格的URL(例如“https://www.yahoo.com /搜索/),没有一个绝对的路径(例如域搜索/ /),甚至是相对路径(如“/”)。在最后的情况下,客户端浏览器将重建完整的URL本身的电流路径。看到HttpResponse其他optionalconstructor参数。请注意,这将返回一个HTTP状态代码302。class HttpResponsePermanentRedirect[source]
像httpresponseredirect,但它返回一个永久重定向(HTTP状态代码301)而不是“发现”的重定向(状态代码302)class HttpResponseNotModified[source]
构造函数不带任何参数和NO含量应该被添加到这一反应。使用指定一个页面没有被modifiedsince用户的最后一个请求(状态代码304)。class HttpResponseBadRequest[source]
就像HttpResponse但使用400状态码class HttpResponseNotFound[source]
就像HttpResponse但使用404状态码class HttpResponseForbidden[source]
就像HttpResponse但使用403状态码class HttpResponseNotAllowed[source]
像HttpResponse,但使用405状态码。第一argumentto构造函数要求准许清单的方法(如(get,后])class HttpResponseGone[source]
就像HttpResponse但使用410状态码class HttpResponseServerError[source]
就像HttpResponse但使用500状态码
六、模板层***
作为一个Web框架,Django 需要模板。模板包含所需的 HTML 输出静态部分以及动态内容插入。
1、模版的执行
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def current_datetime(request): now = datetime.datetime.now() html = "<html><body>It is now %s.</body></html>" % now return HttpResponse(html) from django import template t = template.Template('My name is {{ name }}.') c = template.Context({'name': 'Adrian'}) print t.render(c) import datetime from django import template import DjangoDemo.settings now = datetime.datetime.now() fp = open(settings.BASE_DIR+'/templates/Home/Index.html') t = template.Template(fp.read()) fp.close() html = t.render(template.Context({'current_date': now})) return HttpResponse(html from django.template.loader import get_template from django.template import Context from django.http import HttpResponse import datetime def current_datetime(request): now = datetime.datetime.now() t = get_template('current_datetime.html') html = t.render(Context({'current_date': now})) return HttpResponse(html) return render_to_response('Account/Login.html',data,context_instance=RequestContext(request)) 示例
2、模版语言
模板中也有自己的语言,该语言可以实现数据展示
- {{ item }}
- {% for item in item_list %} <a>{{ item }}</a> {% endfor %}
forloop.counter
forloop.first
forloop.last - {% if ordered_warranty %} {% else %} {% endif %}
- 母板:{% block title %}{% endblock %}
子板:{% extends "base.html" %}
{% block title %}{% endblock %} - 帮助方法:
{{ item.event_start|date:"Y-m-d H:i:s"}}
{{ bio|truncatewords:"30" }}
{{ my_list|first|upper }}
{{ name|lower }}
3、自定义simple_tag
a、在app中创建templatetags模块
b、创建任意 .py 文件,如:xx.py
#!/usr/bin/env python #coding:utf-8 from django import template from django.utils.safestring import mark_safe from django.template.base import resolve_variable, Node, TemplateSyntaxError register = template.Library() @register.simple_tag def my_simple_time(v1,v2,v3): return v1 + v2 + v3 @register.simple_tag def my_input(id,arg): result = "<input type='text' id='%s' class='%s' />" %(id,arg,) return mark_safe(result)
c、在使用自定义simple_tag的html文件中导入之前创建的 xx.py 文件名
{% load xx %}
d、使用simple_tag
{% my_simple_time 1 2 3%} {% my_input 'id_username' 'hide'%}
e、在settings中配置当前app,不然django无法找到自定
INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01', )
六、Model 层
Django提供了一个抽象层(“Model”)的构建和管理Web应用程序的数据。
- 每个模型是一个Python类,子类
d jango.db.models.model
- 模型中的每个属性代表一个数据库字段。
1.简单的例子
from django.db import models class Person(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30)
2.参数与字段
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1、models.AutoField 自增列 = int(11) 如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True。 2、models.CharField 字符串字段 必须 max_length 参数 3、models.BooleanField 布尔类型=tinyint(1) 不能为空,Blank=True 4、models.ComaSeparatedIntegerField 用逗号分割的数字=varchar 继承CharField,所以必须 max_lenght 参数 5、models.DateField 日期类型 date 对于参数,auto_now = True 则每次更新都会更新这个时间;auto_now_add 则只是第一次创建添加,之后的更新不再改变。 6、models.DateTimeField 日期类型 datetime 同DateField的参数 7、models.Decimal 十进制小数类型 = decimal 必须指定整数位max_digits和小数位decimal_places 8、models.EmailField 字符串类型(正则表达式邮箱) =varchar 对字符串进行正则表达式 9、models.FloatField 浮点类型 = double 10、models.IntegerField 整形 11、models.BigIntegerField 长整形 integer_field_ranges = { 'SmallIntegerField': (-32768, 32767), 'IntegerField': (-2147483648, 2147483647), 'BigIntegerField': (-9223372036854775808, 9223372036854775807), 'PositiveSmallIntegerField': (0, 32767), 'PositiveIntegerField': (0, 2147483647), } 12、models.IPAddressField 字符串类型(ip4正则表达式) 13、models.GenericIPAddressField 字符串类型(ip4和ip6是可选的) 参数protocol可以是:both、ipv4、ipv6 验证时,会根据设置报错 14、models.NullBooleanField 允许为空的布尔类型 15、models.PositiveIntegerFiel 正Integer 16、models.PositiveSmallIntegerField 正smallInteger 17、models.SlugField 减号、下划线、字母、数字 18、models.SmallIntegerField 数字 数据库中的字段有:tinyint、smallint、int、bigint 19、models.TextField 字符串=longtext 20、models.TimeField 时间 HH:MM[:ss[.uuuuuu]] 21、models.URLField 字符串,地址正则表达式 22、models.BinaryField 二进制 23、models.ImageField 图片 24、models.FilePathField 文件 更多字段
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1、null=True 数据库中字段是否可以为空 2、blank=True django的 Admin 中添加数据时是否可允许空值 3、primary_key = False 主键,对AutoField设置主键后,就会代替原来的自增 id 列 4、auto_now 和 auto_now_add auto_now 自动创建---无论添加或修改,都是当前操作的时间 auto_now_add 自动创建---永远是创建时的时间 5、choices GENDER_CHOICE = ( (u'M', u'Male'), (u'F', u'Female'), ) gender = models.CharField(max_length=2,choices = GENDER_CHOICE) 6、max_length 7、default 默认值 8、verbose_name Admin中字段的显示名称 9、name|db_column 数据库中的字段名称 10、unique=True 不允许重复 11、db_index = True 数据库索引 12、editable=True 在Admin里是否可编辑 13、error_messages=None 错误提示 14、auto_created=False 自动创建 15、help_text 在Admin中提示帮助信息 16、validators=[] 17、upload-to 更多参数
3.连表结构
- 一对多:models.ForeignKey(其他表)
- 多对多:models.ManyToManyField(其他表)
- 一对一:models.OneToOneField(其他表)
4.操作表
1>、基本操作
# 增 models.Tb1.objects.create(c1='xx', c2='oo') # 增加一条数据,可以接受字典类型数据 **kwargs obj = models.Tb1(c1='xx', c2='oo') obj.save() # 查 models.Tb1.objects.get(id=123) # 获取单条数据,不存在则报错(不建议) models.Tb1.objects.all() # 获取全部 models.Tb1.objects.filter(name='seven') # 获取指定条件的数据 # 删 models.Tb1.objects.filter(name='nick').delete() # 删除指定条件的数据 # 改models.Tb1.objects.filter(name='nick').update(gender='0') # 将指定条件的数据更新,均支持 **kwargs obj = models.Tb1.objects.get(id=1) obj.c1 = '111' obj.save() # 修改单条数据
2>、进阶操作(了不起的双下划线)
利用双下划线将字段和对应的操作连接起来
# 获取个数 models.Tb1.objects.filter(name='nick').count() # 大于,小于 models.Tb1.objects.filter(id__gt=1) # 获取id大于1的值 models.Tb1.objects.filter(id__lt=10) # 获取id小于10的值 models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值 # in models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据 models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in # contains models.Tb1.objects.filter(name__contains="ven") models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感 models.Tb1.objects.exclude(name__icontains="ven") # range models.Tb1.objects.filter(id__range=[1, 2]) # 范围bettwen and # 其他类似 # startswith,istartswith, endswith, iendswith, # order by models.Tb1.objects.filter(name='nick').order_by('id') # asc models.Tb1.objects.filter(name='nick').order_by('-id') # desc # limit 、offset models.Tb1.objects.all()[10:20] # group by from django.db.models import Count, Min, Max, Sum models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num')) # SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"
3>、连表操作(了不起的双下划线)
利用双下划线和 _set 将表之间的操作连接起来
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class UserProfile(models.Model): user_info = models.OneToOneField('UserInfo') username = models.CharField(max_length=64) password = models.CharField(max_length=64) def __unicode__(self): return self.username class UserInfo(models.Model): user_type_choice = ( (0, u'普通用户'), (1, u'高级用户'), ) user_type = models.IntegerField(choices=user_type_choice) name = models.CharField(max_length=32) email = models.CharField(max_length=32) address = models.CharField(max_length=128) def __unicode__(self): return self.name class UserGroup(models.Model): caption = models.CharField(max_length=64) user_info = models.ManyToManyField('UserInfo') def __unicode__(self): return self.caption class Host(models.Model): hostname = models.CharField(max_length=64) ip = models.GenericIPAddressField() user_group = models.ForeignKey('UserGroup') def __unicode__(self): return self.hostname 表结构实例
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
user_info_obj = models.UserInfo.objects.filter(id=1).first() print user_info_obj.user_type print user_info_obj.get_user_type_display() print user_info_obj.userprofile.password user_info_obj = models.UserInfo.objects.filter(id=1).values('email', 'userprofile__username').first() print user_info_obj.keys() print user_info_obj.values() 一对一操作
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 添加一对多 dic = { "hostname": "名字1", "ip": "192.168.1.1", "user_group_id": 1, # 加对象则为"user_group" } models.Host.objects.create(**dic) # 正向查一对多 host_obj = models.Host.objects.all() print(type(host_obj), # <class 'django.db.models.query.QuerySet'> host_obj) # <QuerySet [<Host: 名字1>]> for item in host_obj: print(item.hostname) print(item.user_group.caption) print(item.user_group.user_info.values()) # <QuerySet [{'name': 'nick', 'user_type': 1, 'id': 1, 'email': '630571017@qq.com', 'address': '128号'}]> usergroup_obj = models.Host.objects.filter(user_group__caption='标题1') print(usergroup_obj) # 反向查一对多 usergroup_obj = models.UserGroup.objects.get(id=1) print(usergroup_obj.caption) ret = usergroup_obj.host_set.all() # 所有关于id=1的host print(ret) obj = models.UserGroup.objects.filter(host__ip='192.168.1.1').\ values('host__id', 'host__hostname') print(obj) # <QuerySet [{'host__id': 1, 'host__hostname': '名字1'}]> 一对多
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
user_info_obj = models.UserInfo.objects.get(name='nick') user_info_objs = models.UserInfo.objects.all() group_obj = models.UserGroup.objects.get(caption='CTO') group_objs = models.UserGroup.objects.all() # 添加数据 #group_obj.user_info.add(user_info_obj) #group_obj.user_info.add(*user_info_objs) # 删除数据 #group_obj.user_info.remove(user_info_obj) #group_obj.user_info.remove(*user_info_objs) # 添加数据 #user_info_obj.usergroup_set.add(group_obj) #user_info_obj.usergroup_set.add(*group_objs) # 删除数据 #user_info_obj.usergroup_set.remove(group_obj) #user_info_obj.usergroup_set.remove(*group_objs) # 获取数据 #print group_obj.user_info.all() #print group_obj.user_info.all().filter(id=1) # 获取数据 #print user_info_obj.usergroup_set.all() #print user_info_obj.usergroup_set.all().filter(caption='CTO') #print user_info_obj.usergroup_set.all().filter(caption='DBA') # 添加多对多 # userinfo_id_1 = models.UserInfo.objects.filter(id=1) # usergroup_id_1 = models.UserGroup.objects.filter(id=1).first() # usergroup_id_1.user_info.add(*userinfo_id_1) 多对多操作
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# F 使用查询条件的值(用原来的值操作) # # from django.db.models import F # models.Tb1.objects.update(num=F('num')+1) # Q 构建搜索条件 from django.db.models import Q # con = Q() # # q1 = Q() # q1.connector = 'OR' # q1.children.append(('id', 1)) # q1.children.append(('id', 10)) # q1.children.append(('id', 9)) # # q2 = Q() # q2.connector = 'OR' # q2.children.append(('c1', 1)) # q2.children.append(('c1', 10)) # q2.children.append(('c1', 9)) # # con.add(q1, 'AND') # con.add(q2, 'AND') # # models.Tb1.objects.filter(con) F & Q
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.db import connection cursor = connection.cursor() cursor.execute("""SELECT * from app1_userinfo where name = %s""", ['nick']) row = cursor.fetchone() print(row)
注意:xx_set中的【_set】是多对多中的固定搭配
补充
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# values 取到的是字典集合 # values_list 取到的是没有键的元祖形式 # get 只有在能取到一条数据的时候才不会报错(不推荐) # filter([筛选条件]) # all() 俩者取到的都是Query set集合对象 是可迭代、可切片、索引取值 # iterator() ORM的惰性机制 # Publisher.objects.all()或者.filter()等都只是返回了一个QuerySet # 并不会马上执行sql,而是当调用QuerySet的时候才执行。
七、admin
Django Amdin是Django提供的一个后台管理页面,改管理页面提供完善的html和css,在通过Model创建完数据库表之后,就可以对数据进行增删改查,而使用Django Admin 则需要以下步骤:
- 创建后台管理员
- 配置url
- 注册和配置Django Admin后台管理页面
1、创建后台管理员
python manage.py createsuperuser
2、配置后台管理url
url(r'^admin/', include(admin.site.urls))
3、注册和配置django admin 后台管理页面
A,注册表
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.contrib import admin from app01 import models admin.site.register(models.UserType) admin.site.register(models.UserInfo) admin.site.register(models.UserGroup) admin.site.register(models.Asset)
B,设置数据表显示名称
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class UserType(models.Model): name = models.CharField(max_length=50) class Meta: verbose_name = '用户类型' verbose_name_plural = '用户类型'
C,打开表之后想要看哪些字段作出如下配置
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.contrib import admin from app01 import models class UserInfoAdmin(admin.ModelAdmin): list_display = ('username', 'password', 'email') # 放置对应表字段 admin.site.register(models.UserInfo,UserInfoAdmin)
D,数据表添加过滤功能(模糊输入查询)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.contrib import admin from app01 import models class UserInfoAdmin(admin.ModelAdmin): list_display = ('username', 'password', 'email') search_fields = ('username', 'email') # 定义它 admin.site.register(models.UserInfo,UserInfoAdmin)
E,快速过滤
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.contrib import admin from app01 import models class UserInfoAdmin(admin.ModelAdmin): list_display = ('username', 'password', 'email') search_fields = ('username', 'email') list_filter = ('username', 'email') admin.site.register(models.UserInfo,UserInfoAdmin)
F,设置分页和只读字段
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.contrib import admin from repository import models class CustomerInfoAdmin(admin.ModelAdmin): list_display = ['name', 'source', 'contact_type', 'contact', 'consultant', 'status', 'date'] list_filter = ['source', 'consultant', 'status', 'date'] search_fields = ['contact', 'consultant__name'] readonly_fields = ['status','contact'] # 只读字段 filter_horizontal = ['consult_courses',] # 出现炫酷的select切换 list_per_page = 2 # 设置分页,每页显示多少条 admin.site.register(models.UserProfile) admin.site.register(models.Role) admin.site.register(models.CustomerInfo, CustomerInfoAdmin)