django基础之二

一、什么是架构?

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

对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端。

最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回。

如果要动态生成HTML,就需要把上述步骤自己来实现。不过,接受HTTP请求、解析HTTP请求、发送HTTP响应都是苦力活,如果我们自己来写这些底层代码,还没开始写动态HTML呢,就得花个把月去读HTTP规范。

正确的做法是底层代码由专门的服务器软件实现,我们用Python专注于生成HTML文档。因为我们不希望接触到TCP连接、HTTP原始请求和响应格式,所以,需要一个统一的接口,让我们专心用Python编写Web业务。

这个接口就是WSGI:Web Server Gateway Interface。

二、MVC和MTV

django基础之二

著名的MVC模式:所谓MVC就是把web应用分为模型(M),控制器(C),视图(V)三层;他们之间以一种插件似的,松耦合的方式连接在一起。

模型负责业务对象与数据库的对象(ORM),视图负责与用户的交互(页面),控制器(C)接受用户的输入调用模型和视图完成用户的请求。

Django的MTV模式本质上与MVC模式没有什么差别,也是各组件之间为了保持松耦合关系,只是定义上有些许不同,Django的MTV分别代表:

Model(模型):负责业务对象与数据库的对象(ORM)

Template(模版):负责如何把页面展示给用户

View(视图):负责业务逻辑,并在适当的时候调用Model和Template

此外,Django还有一个url分发器,它的作用是将一个个URL的页面请求分发给不同的view处理,view再调用相应的Model和Template

三、Django的配置文件

3.1配置静态文件路径,为了django找到本地的文件

STATICFILES_DIRS = (

os.path.join(BASE_DIR,'static'),

)

3.2数据库引擎配置

DATABASES = {

'default': {

'ENGINE': 'django.db.backends.mysql',

'NAME':'数据库名字',

'USER': 'root',

'PASSWORD': 'xxx',

'HOST': '',#默认是本地

'PORT': '3306',

}

}

# 由于Django内部连接MySQL时使用的是MySQLdb模块,而python3中还无此模块,所以需要使用pymysql来代替

# 如下设置放置的与project同名的配置的 __init__.py文件中

import pymysql

pymysql.install_as_MySQLdb()

3.3模板配置路径

TEMPLATE_DIRS = (

os.path.join(BASE_DIR,'templates'),

)

四、路由系统:

URL配置(URLconf)就像Django 所支撑网站的目录。它的本质是URL模式以及要为该URL模式调用的视图函数之间的映射表;你就是以这种方式告诉Django,对于这个URL调用这段代码,对于那个URL调用那段代码。

urlpatterns = [    url(正则表达式, views视图函数,参数,别名),]

参数说明:

一个正则表达式字符串

一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串

可选的要传递给视图函数的默认参数(字典形式)

一个可选的name参数

  4.1、单一路由对应

url(r'^index$', views.index),

4.2、基于正则的路由 1 2

url(r'^index/(\d*)', views.index),

url(r'^manage/(?P<name>\w*)/(?P<id>\d*)', views.manage),

4.3、添加额外的参数

url(r'^manage/(?P<name>\w*)', views.manage,{'id':333}),

4.4、为路由映射设置名称

url(r'^home', views.home, name='h1'),

url(r'^index/(\d*)', views.index, name='h2'),

在使用模板时候使用

   

  设置名称之后,可以在不同的地方调用,如:

  • 模板中使用生成URL     {% url 'h2' 2012 %}
  • 函数中使用生成URL     reverse('h2', args=(2012,))      路径:django.urls.reverse
  • Model中使用获取URL  自定义get_absolute_url() 方法
class NewType(models.Model):
caption = models.CharField(max_length=) 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信息:request.resolver_match

4.5、根据app对路由规则进行分类

url(r'^web/',include('web.urls')),

将路由指定到web项目下的urls文件去再分发

  

  4.6、命名空间

  1.project.urls.py

 

from django.conf.urls import url,include

urlpatterns = [
url(r'^a/', include('app01.urls', namespace='author-polls')),
url(r'^b/', include('app01.urls', namespace='publisher-polls')),
]

 2. 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')
]

3.app01.views.py

def detail(request, pk):
print(request.resolver_match)
return HttpResponse(pk)

以上定义带命名空间的url之后,使用name生成URL时候,应该如下:

  • v = reverse('app01:detail', kwargs={'pk':11})
  • {% url 'app01:detail' pk=12 pp=99 %}

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

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

  

五、模板:

1、模版的执行

模版的创建过程,对于模版,其实就是读取模版(其中嵌套着模版标签),然后将 Model 中获取的数据插入到模版中,最后将信息返回给用户

def current_datetime(request):
now = datetime.datetime.now()
html = "<html><body>It is now %s.</body></html>" % now
return HttpResponse(html)
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)
from django import template
t = template.Template('My name is {{ name }}.')
c = template.Context({'name': 'Adrian'})
print t.render(c)
return render_to_response('Account/Login.html',data,context_instance=RequestContext(request))

2模板的写法

5.2.1 使用双大括号来引用变量

{{ name }}    {{ age }}

深度变量的查找(万能的句点号)

{{ list.0 }}   {{ dic.name }}

变量的过滤器(filter)的使用

{{obj|filter:param}}

1  add          :   给变量加上相应的值

2  addslashes   :    给变量中的引号前加上斜线

3  capfirst     :    首字母大写

4  cut          :   从字符串中移除指定的字符

5  date         :   格式化日期字符串

6  default      :   如果值是False,就替换成设置的默认值,否则就是用本来的值

7  default_if_none:  如果值是None,就替换成设置的默认值,否则就使用本来的值

#实例:
#value1="aBcDe"
{{ value1|upper }}
<br>
#value2=
{{ value2|add: }}
<br>
#value3='he llo wo r ld'
{{ value3|cut:' ' }}
<br>
#import datetime
#value4=datetime.datetime.now()
{{ value4|date:'Y-m-d' }}
<br>
#value5=[]
{{ value5|default:'空的' }}
<br>
#value6='<a href="#">跳转</a>'
{{ value6 }}{% autoescape off %} {{ value6 }}{% endautoescape %}{{ value6|safe }}
<br>
{{ value6|striptags }}
#value7=''{{ value7|filesizeformat }}
<br>
{{ value7|first }}
<br>
{{ value7|length }}
<br>{{ value7|slice:":-1" }}
<br>
#value8='http://www.baidu.com/?a=1&b=3'{{ value8|urlencode }}
<br>
value9='hello I am yuan'

如果默认的filter不能满足使用,可以自定义.

a、在app中创建templatetags模块(必须的)

b、创建任意 .py 文件,如:my_tags.py

#!/usr/bin/env python
#coding:utf-
from django import template
from django.utils.safestring import mark_safe 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和filter的html文件中导入之前创建的 my_tags.py :

 {% load my_tags %}    

d、使用simple_tag和filter(如何调用)

{% my_simple_time   %}
{% my_input 'id_username' 'hide'%}

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

INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01',
)

更多见文档:https://docs.djangoproject.com/en/1.11/ref/templates/language/

  {% if %} 条件语句

{% if num >= 100 and 8 %}
{% if num > 200 %}
<p>num大于200</p>
{% else %}
<p>num大于100小于200</p>
{% endif %}
{% elif num < 100%}
<p>num小于100</p>
{% else %}
<p>num等于100</p>
{% endif %}{% if %} 标签接受and,or或者not来测试多个变量值或者否定一个给定的变量
{% if %} 标签不允许同一标签里同时出现and和or,否则逻辑容易产生歧义,
例如下面的标签是不合法的:{% if obj1 and obj2 or obj3 %}

{% for %}

{% for %}标签允许你按顺序遍历一个序列中的各个元素,每次循环模板系统都会渲染{% for %}和{% endfor %}之间的所有内容

<ul>{% for obj in list %}
<li>{{ obj.name }}</li>{% endfor %}</ul>
#在标签里添加reversed来反序循环列表:
{% for obj in list reversed %} ... {% endfor %}
#{% for %}标签可以嵌套:
{% for country in countries %}
<h1>{{ country.name }}</h1>
<ul> {% for city in country.city_list %}
<li>{{ city }}</li> {% endfor %} </ul> {% endfor %}
#系统不支持中断循环,系统也不支持continue语句,{% for %}标签内置了一个forloop模板变量,
#这个变量含有一些属性可以提供给你一些关于循环的信息1,forloop.counter表示循环的次数,它从1开始计数,第一次循环设为1: {% for item in todo_list %} <p>{{ forloop.counter }}: {{ item }}</p> {% endfor %},forloop.counter0 类似于forloop.counter,但它是从0开始计数,第一次循环设为03,forloop.revcounter4,forloop.revcounter05,forloop.first当第一次循环时值为True,在特别情况下很有用: {% for object in objects %} {% if forloop.first %}<li class="first">{% else %}<li>{% endif %} {{ object }} </li> {% endfor %}
# 富有魔力的forloop变量只能在循环中得到,当模板解析器到达{% endfor %}时forloop就消失了# 如果你的模板context已经包含一个叫forloop的变量,Django会用{% for %}标签替代它
# Django会在for标签的块中覆盖你定义的forloop变量的值# 在其他非循环的地方,你的forloop变量仍然可用
#{% empty %}{{li }} {% for i in li %} <li>{{ forloop.counter0 }}----{{ i }}</li> {% empty %} <li>this is empty!</li> {% endfor %}# [, , , , ]# ----# ----# ----# ----# ----

{%csrf_token%}:csrf_token标签

用于生成csrf_token的标签,用于防治跨站攻击验证。注意如果你在view的index里用的是render_to_response方法,不会生效

其实,这里是会生成一个input标签,和其他表单标签一起提交给后台的。

{% url %}:  引用路由配置的地址

{% with %}:用更简单的变量名替代复杂的变量名

{% load %}: 加载标签库

六、模板继承

我们制作某个页面,想让其他页面也继承一些样式,可以将此页面设置成模板。

将需要修改的内容

{%  block  模块名称  %}

内容

{% endblock %}

在需要继承模板的页面第一行添加以下内容才可以继承

{% extends "base.html" %}

模板使用方式:

直接写需要修改的块,不写默认全部继承模板的内容

{% block  模块名称 %}

修改的内容

{% endblock %}

如果需要使用模板的内容,又想添加一些内容,可以如下设置

{% block  模块名称 %}

{% include %}

修改的内容

{% endblock %}

七、视图 views.py

http请求中产生两个核心对象:

http请求:HttpRequest对象

http响应:HttpResponse对象

path:请求页面的全路径,不包括域名
         method:请求中使用的HTTP方法的字符串表示。全大写表示。例如
                if  req.method=="GET":
                     do_something()
                    elseif req.method=="POST":
                    do_something_else()
         GET:         包含所有HTTP GET参数的类字典对象
         POST:       包含所有HTTP POST参数的类字典对象
             服务器收到空的POST请求的情况也是可能发生的,也就是说,表单form通过
              HTTP POST方法提交请求,但是表单中可能没有数据,因此不能使用
              if req.POST来判断是否使用了HTTP POST 方法;应该使用  if req.method=="POST"
    
        COOKIES:     包含所有cookies的标准Python字典对象;keys和values都是字符串。
        FILES:包含所有上传文件的类字典对象;FILES中的每一个Key都是<input type="file" name="" />标签中name属性的值,FILES中的每一个value同时也是一个标准的python字典对象,包含下面三个Keys:
                  filename:      上传文件名,用字符串表示
                  content_type:   上传文件的Content Type
                  content:       上传文件的原始内容
        user:

是一个django.contrib.auth.models.User对象,代表当前登陆的用户。如果访问用户当前
                  没有登陆,user将被初始化为django.contrib.auth.models.AnonymousUser的实例。你
                  可以通过user的is_authenticated()方法来辨别用户是否登陆:
                  if req.user.is_authenticated();只有激活Django中的AuthenticationMiddleware
                  时该属性才可用

session:

唯一可读写的属性,代表当前会话的字典对象;自己有激活Django中的session支持时该属性才可用。
      HttpResponse对象

render()(推荐)

render_to_response(),

redirect("路径")

locals():    可以直接将函数中所有的变量传给模板

 
上一篇:亲手搭建一个基于Asp.Net WebApi的项目基础框架1


下一篇:eShopOnContainers 是一个基于微服务的.NET Core示例框架