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

著名的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=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信息: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=5
{{ value2|add:3 }}
<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='1234'{{ 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-8
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 1 2 3%}
{% 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 %}2,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 %}#         [11, 22, 33, 44, 55]#            0----11#            1----22#            2----33#            3----44#            4----55

{%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():    可以直接将函数中所有的变量传给模板

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏黑泽君的专栏

c语言基础学习02_helloworld

============================================================================= 涉及...

1261
来自专栏风中追风

java类的加载过程和类加载器的分析

我们知道,我们写的java代码保存的格式是 .java, java文件被编译后会转换为字节码,字节码可以在任何平台通过java虚拟机来运行,这也是java能够跨...

5378
来自专栏用户2442861的专栏

Linux下动态库(.so)和静态库(.a) 的区别

动态库(共享库)的代码在可执行程序运行时才载入内存,在编译过程中仅简单的引用,因此代码体积比较小。

6731
来自专栏一个爱瞎折腾的程序猿

常用cmd代码片段及.net core打包脚本分享

保存:set currentPath=%cd% 输出:echo %currentPath

843
来自专栏闪电gogogo的专栏

Python初学——多线程Threading

接着上篇继续跟着沫凡小哥学Python啦 1.1 什么是多线程 Threading 多线程可简单理解为同时执行多个任务。 多进程和多线程都可以执行多个任务,线程...

2015
来自专栏Java技术

Java多线程编程-(18)-等待/通知模式接口Condition接口深入分析

在上述两篇文章中讲解AQS的时候,我们已经知道了同步队列AQS的内部类ConditionObject实现了Condition接口,使用ReentrantLock...

651
来自专栏北京马哥教育

3000 字 Flask 快速学习指南:从入门到开发

作者:过了即是客 Flask是一个Python编写的Web 微框架,让我们可以使用Python语言快速实现一个网站或Web服务。本文参考自Flask官方文档,...

6199
来自专栏V站

PHP中上传图片表单$_FILES为空的解决办法

在文件上传中$_FILES接收不到值的情况有很多种,总结一下常见的错误有下边几种,也是大家在使用中容易犯的错误。 1.在form中忘记加enctype="mul...

3962
来自专栏运维小白

10.7 free命令

监控系统状态 free 查看内存使用情况 free -m / -g / -h buffer/cache区别 公式:total=used+free+buff/ca...

2037
来自专栏python学习路

八、线程和进程 什么是线程(thread)?什么是进程(process)? 线程和进程的区别?Python GIL(Global Interpreter Lock)全局解释器锁

什么是线程(thread)? 线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一...

4197

扫码关注云+社区