zoukankan      html  css  js  c++  java
  • 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})
    View Code

      获取请求匹配成功的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)
    View Code
    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
    View Code
    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)
    View Code
    from django import template
    t = template.Template('My name is {{ name }}.')
    c = template.Context({'name': 'Adrian'})
    print t.render(c)
    View Code
    return render_to_response('Account/Login.html',data,context_instance=RequestContext(request))
    View Code

    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)
    View Code

     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
    View Code

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

     
  • 相关阅读:
    重构该何时登场
    重构
    中国剩余定理
    连分数的应用
    连分数的性质
    有限连分数与欧几里德除法的联系
    连分数
    费马大定理
    P4178 Tree 点分治
    LOJ 6029. 「雅礼集训 2017 Day1」市场
  • 原文地址:https://www.cnblogs.com/guigujun/p/7806620.html
Copyright © 2011-2022 走看看