美文网首页
【二】MyFirstDjango

【二】MyFirstDjango

作者: 一个无趣的人W | 来源:发表于2019-06-15 11:09 被阅读0次

    我不介意忍受孤独,也不害怕日复一日的坚持,会坦白承认自己技不如人,而后虚心学习。我都可以,只要能去到想去的地方。

    1、安装

    两种方式:
       --命令行安装:pip3 install django==1.11.11
       --在pycharm中安装(导入django模块)
    ps:pip3环境有问题用 python -m pip 命令替换 pip3命令或者重新安装pip3,或是更新pip版本:python3 -m pip install --upgrade pip

    验证是否安装成功:django-admin
    ps:安装出错——> 采用管理员命令行

    2、创建Django项目

    方式1(命令行创建):
       先前往目标文件夹下
       创建django项目 django-admin startproject 项目名
    方式2(pycharm中创建):
       file>>>new project 选择第二个django
    ps:需要注意项目名字路径中不能有中文

    3、创建app应用

       app概念:一个项目中有许多功能,而app就是这些一个一个不同作用的功能体,就好比项目是一所大学,而app就是大学里的各个系。

    方式1(命令行创建):
       进入项目根目录
       创建app应用: python3 manage.py startapp app名
    方式2(pycharm中创建):
       创建app应用 python3 manage.py startapp app名 或者Tools-->run managepath-->startapp app名

    4、启动服务

    启动django项目: python3 manage.py runserver
    ps:start your first app by running python manage.py startapp [app_label].


    ️强调与注意:
       a、用django一定要保证只有一个项目在运行状态;
       b、一定记得清浏览器的缓存(用google浏览器,右击检查);


    清除缓存

       c、计算机的名称不能有中文;
       d、以后一个pycharm窗口就是一个项目,不要多个项目放在一个窗口;
       e、项目名不能起中文;
       f、用命令行创建django默认不会自动创建templates文件夹,需要手动自己创建(注意该文件夹路径是否被添加到配置文件中


    5、项目及应用目录详解

    应用名下
       migrations   数据库迁移(移植)记录相关记录,内容都是由Django自动生成
       admin.py     django后台管理系统配置
       models.py   存放模型表相关,数据模型模块,使用ORM框架,类似于MVC模式下的Model层
       views.py      视图函数相关,执行相应的逻辑代码模块

    项目名下
       _ init _.py     模块的配置文件
       settings.py    配置文件
       urls.py      路由与视图函数的映射关系,django项目中的所有页面都需要对其配置url地址
       wsgi.py       (web server gateway interface),服务器网关接口,python应用与web服务器直接通信的接口,拆包解包

    templates
       模板文件夹,项目用到的所有的html文件(页面)
    manage.py
       项目管理器,与项目交互的命令行工具集的入口,查看支持的所有命令python3 manage.py

    6、项目配置文件settings详解

    (1) 注意新创建的app需要在配置文件中注册才能生效

        INSTALLED_APPS = [
            'django.contrib.admin',
            'django.contrib.auth',
            'django.contrib.contenttypes',
            'django.contrib.sessions',
            'django.contrib.messages',
            'django.contrib.staticfiles',
            'app01',  简写
            # 'app01.apps.App01Config'  全称
        ]
    

    (2) 在配置文件中暂时禁用csrf中间件,方便表单提交测试。

    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        # 'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]
    

    (3) 用命令行创建django默认不会自动创建templates文件夹,需要手动自己创建,创建后的路径要添加到设置中。

    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',
                ],
            },
        },
    ]
    

    (4) Django 数据库配置
      Django为什么要配置数据库?
        因为Django默认采用的是sqlite3数据库,而我们用Pycharm编写程序时使用的是Pymysql模块和数据库交互的,为了能够简化编写程序的流程,我们需要修改默认数据库配置。

    原本使用的sqlite3数据库:

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME':os.path.join(BASE_DIR,'db.sqlite3'),
        }
    }
    

    创建一个自己的MySQL数据库:

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'mfd',
            'HOST':'127.0.0.1',
            'POST':3306,
            'USER':'root',
            'PASSWORD':' '
        }
    }
    

    (5) 静态文件配置
      用来存放页面样式的css,js,bootstrap
      查找方式:通过/static/匹配到静态文件的根路由 => 根路由管理着static | static1 | static1 三个存放在项目根目录下的文件夹 => 三个文件夹中任意一个存放着index.css即可

    STATIC_URL = '/static/'  # 接口前缀  默认情况下这个前缀跟静态文件夹名字一样
    # 静态文件配置,规定静态文件可以放入的文件夹
    STATICFILES_DIRS=[
        os.path.join(BASE_DIR,'static'),
        os.path.join(BASE_DIR,'static1'),
        os.path.join(BASE_DIR,'static2')
    ]
    

    7、开启第一个Django项目

    (1)总体设计
      Web页面的组件:
        · 一个模板,用于显示通过Python类字典对象传入的信息。
        · 一个视图函数,用于执行针对请求的核心逻辑。视图会从数据库中获取信息,并格式化显示结果。
        · 一个URL模式,将传入的请求映射到对应的视图中,同时也可以将参数传递给视图。
      Django是自底向上处理请求,它首先查找匹配的URL模式,接着调用对应的视图函数(匹配url是自上而下,匹配成功立即执行,在以后url多的情况下要注意顺序),最后将渲染好的数据通过模板展现给用户。

      构建应用的顺序(可依据自身情况创建):
        (1)因为需要一些可以观察的内容,所以先创建基本的模板;
        (2)设计一个简单的URL模式,让Django可以立即访问应用;
        (3)开发一个视图函数原型,然后在此基础上迭代开发。
        使用这个顺序的主要原因是因为模板和URL模式不会发生较大的改变,而应用的核心是视图,所以先快速构建一个基本视图,在此基础上逐步完善,这非常符合测试驱动模型(TDD)的开发模式。

    测试驱动模型(TDD)
      测试驱动开发是敏捷开发中的一项核心实践和技术,也是一种设计方法论。TDD的原理是在开发功能代码之前,先编写单元测试用例代码,测试代码确定需要编写什么产品代码。TDD虽是敏捷方法的核心实践,但不只适用于XP(Extreme Programming),同样可以适用于其他开发方法和过程。
      TDD的基本思路就是通过测试来推动整个开发的进行,但测试驱动开发并不只是单纯的测试工作,而是把需求分析设计,质量控制量化的过程。
      TDD的重要目的不仅仅是测试软件,测试工作保证代码质量仅仅是其中一部分,而且是在开发过程中帮助客户和程序员去除模棱两可的需求。TDD首先考虑使用需求(对象、功能、过程、接口等),主要是编写测试用例框架对功能的过程和接口进行设计,而测试框架可以持续进行验证。

    (2)创建URL模式【版本不同,配置路由也有区别,不可一概而论】
    ps:这里使用的是django 1.11.17版本
      配置路由的作用是将用户浏览器中URL的路径名映射到应用的不同部分,当用户通过浏览器发出一个请求时,因特网会通过某种方式将主机名与IP地址映射起来,接着客户端在80或其他端口(Django开发服务器默认使用8000端口)与服务器的地址连接起来。

    from app01 import views   # 导入创建的app下的视图文件
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),  # Django自带的登录界面,后面可用来创建超级用户
        url(r'^index/', views.index),  # 配置路由
    ]
    

    (3)创建视图函数
      在具体应用下的视图文件views.py文件中为请求配置响应函数。
      三种响应:HttpResponse  内部传入一个字符串,返回给浏览器
           render       对位填充,返回一个html页面
           redirect     重定向,接受一个URL参数,表示跳转到指定的URL

      🐷ps:重定向引号里面的两个/ / 不能少,不写会报错!看下面例子就知道为什么了:


      传递要重定向的一个硬编码的URL:
      假设有当前路径http://www.baidu.com/path
      /xx/yy 根路径下的xx/yy 即为http://www.baidu.com/xx/yy
      xx/yy 将当前路径添加xx/yy 即为http://www.baidu.com/path/xx/yy
      完整的路径 转到完整的路径下 如:http://www.baidu.com/ 将跳转到首页


    重定向实现原理
      redirect 默认的302(临时重定向),30* 都是重定向,301是永久重定向,对于seo工程师用永久重定向比较多,如果要变为永久重定向,只需要在redirect()里面增加这段代码即可permanent=True

      🐷ps:render 本意就是着色,粉刷的意思,很好理解,使用方式需要记住除request参数外还接受一个待渲染的模板文件和一个保存具体数据的字典参数。
    将数据填充进模板文件,最后把结果返回给浏览器。

    ️  🐷ps:这里的HttpResponse既可以从django.http导入,又可以从django.shortcuts导入,可以看出http中的字符串响应更丰富:


    from django.shortcuts
    from django.http

    代码部分,实现响应字符串,响应HTML页面,重定向:

    from django.shortcuts import render,HttpResponse,redirect
    def view_action1(request):
          return HttpResponse('咸鱼今天努力了没?')   # 响应字符串
    
    def view_action2(request):
          return render(request, 'index.html')   # 响应模板页面
    
    def view_action3(request):
          return redirect('/重定向的路由')
    

    其中render中有两种给前端页面传值的方式:
      第一种是传递一个可迭代对象,这里传递的是一个字典,将值1和值2,通过k1和k2,传递给index.html

            return render(request,'index.html',{'k1': 值1, 'k2': 值2})
    

      第二种是使用locals( ),将视图函数中所有的局部变量都传递给index.html,也可以传递全局变量globals(),当然这可能会传递一些多余的参数,有点浪费内存。

             return render(request, 'index.html', locals())
    

      为了进行快速开发,使用伪视图和半伪造的数据能快速验证应用的基本设置是否正确,这种迭代过程非常快速,表明现在可以安全地开始真正的工作。
    “HELLO WORLD”伪视图:
    views.py中

    from django.shortcuts import render,HttpResponse,redirect,render_to_response
    from app01.models import User  # 导入模型层实例化出来的对象
    
    def index(request):
        test=User(user='wpp',pwd='111')
        return render_to_response('reg.html',{'tests':[test]})
    

    reg.html中

    {% for test in tests %}     <!--注意这里循环的是字典的key-->
    <h2>{{ test.user }}</h2>
    <p>{{ test.pwd }}</p>
    {% endfor %}
    

    启动服务器,网页中显示

    web网页效果图

    在这里简单视图使用的是render(),伪视图使用的是render_to_response(),但实际开发依自己情况看。
      接下来详解一下使用render和render_to_reponse()
    首先使用原生的方式从获取数据到向客户端返回HTTP响应需要遵循以下步骤:
        · 向数据库查询所有用户信息
        · 载入模板文件
        · 为模板创建上下文字典
        · 将上下文传递给模板
        · 将模板渲染到HTML中
        · 通过HTTP响应返回HTML

    ️注意有坑(版本问题)
    def index(request):
        test = User.objects.all()
        t = loader.get_template('reg.html')
        c=Context({'tests':test})
        return HttpResponse(t.render(c))
    

    运行上面展示页面,结果...


    令人崩溃的黄页

    解读一下报错信息:context must be a dict rather than Context.(上下文必须是字典而不是上下文???黑人问号,既拗口又矛盾)对啊,我传的是字典,为什么还会报错呢,那就分析一下源码。
    Context源码:

    def make_context(context, request=None, **kwargs):
        """
        Create a suitable Context from a plain dict and optionally an HttpRequest.
        """
        if context is not None and not isinstance(context, dict):
        ️找到报错点,这里要求传给context的参数必须是字典
            raise TypeError('context must be a dict rather than %s.' % context.__class__.__name__)
        if request is None:
            context = Context(context, **kwargs)
        else:
            # The following pattern is required to ensure values from
            # context override those from template context processors.
            original_context = context
            context = RequestContext(request, **kwargs)
            if original_context:
                context.push(original_context)
    ️返回出去的就直接是context或者是基子类RequestContext实例对象
        return context
    

    那么问题来了,返回给谁呢,而且context的参数是谁传给他的呢??
    经过一番研究,从自己写的代码中抽丝剥茧,发现返回给render,那render又是哪里来的呢?是Template.render(),是Template类中的一个方法,那就看一下Template的源码:

    import django.template.backends.django  # 导入Django,查看源码
    
    class Template(object):
    
        def __init__(self, template, backend):
            self.template = template
            self.backend = backend
    
        @property
        def origin(self):
            return self.template.origin
    ️这里render传入参数给context,再用make_context对传入的字典进行处理,直接返回context,就说明这里context已经封装好了!!!!!我们只要直接传字典进去就好了!!!
        def render(self, context=None, request=None):
            context = make_context(context, request, autoescape=self.backend.engine.autoescape)
            try:
                return self.template.render(context)
            except TemplateDoesNotExist as exc:
                reraise(exc, self.backend)
    

    ️上面这段代码就解释了为什么render要传字典!!
    修改代码:

    def index(request):
        test = User.objects.all()
        t = loader.get_template('reg.html')
        return HttpResponse(t.render({'tests':test}))
    

    终于。。


    来之不易的页面

    总结:版本是个坑,随着版本的更新,很多方法被不断的封装,集成,所以在以后的学习中要注意版本问题,也要多去研究研究源码!

    创建快捷方式 render_to_response()和render()
      从(获取数据,渲染到模板,返回响应)这一系列过程是复杂的而且由于加载模板、填充 context 、将经解析的模板结果返回为 HttpResponse 对象这一系列操作实在太常用了,Django 提供了一条仅用一行代码就完成所有这些工作的捷径。该捷径就是位于 django.shortcuts 模块中名为 render_to_response() 的函数和render()函数。大多数时候,你将使用这两个函数,而不是手动加载模板、创建 Context 和 HttpResponse 对象。
      render_to_response()和render()返回的是HttpResponse对象

      【1】 render( )源码:传三个参数

    def render(request, template_name, context=None, content_type=None, status=None, using=None):
        """
        Returns a HttpResponse whose content is filled with the result of calling
        django.template.loader.render_to_string() with the passed arguments.
        """
        content = loader.render_to_string(template_name, context, request, using=using)
        return HttpResponse(content, content_type, status)
    

      需要的参数有:request,HTML模板页面名,context传参(这里必须传字典[往上看翻车例子,讲了为什么要传字典]或局部变量或全局变量)

      【2】render_to_response( )源码:传一个或两个参数

    def render_to_response(template_name, context=None, content_type=None, status=None, using=None):
        """
        Returns a HttpResponse whose content is filled with the result of calling
        django.template.loader.render_to_string() with the passed arguments.
        """
        content = loader.render_to_string(template_name, context, using=using)
        return HttpResponse(content, content_type, status)
    

      需要的参数有:HTML模板页面名,context参数

      【3】render_to_response( )和render( )的区别:
        区别一:
        自django1.3开始:render()方法是render_to_response的一个崭新的快捷方式,render_to_response会自动使用RequestContext。而render必须coding出来,这是最明显的区别,当然前者更简洁。

    return render_to_response('index.html',{'user': 'wpr', 'pwd': 123})
    
    return render(request, 'index.html', {'user': 'wpr', 'pwd': 123})
    

        区别二:
        如果都不传递data,只返回静态模板的话,render需要传入request,而render_to_response只需传入静态模板就行了:

    def index(request):
        return render(request,'index.html')   
        return render_to_response('index.html')
    

    🦌对于像作者这样的懒人,把极简主义发挥到了极致,而且经常忘记request的人来说,还是render_to_response好用....

    (3)创建模板
      后端传递给前端模板的变量是特殊的python字典,称为上下文(context)。
      模板其实就是HTML前端页面,里面有模板语言,比如变量标签{{ }},里面是用于显示对象的内容,在变量标签中可以使用过滤器(过滤器是函数),它能在标签中立即对变量进行处理,只要在变量的右边插入一个管道符号(“|”)。此外还有块标签{%  %},它用于向html模板中插入如循环或判断这样的逻辑。

    {% for test in tests %}
    <h2>{{ test.user }}</h2>
    <p>{{ test.pwd }}</p>
    {% endfor %}
    

    HTML模板文件是放在templates文件夹下的。


    Myfirstdjango

    # urls.py
    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^index/', views.index),
    ]
    
    
    # views.py
    def index(request):
        test = User.objects.all()
        return render(request, 'index.html', {'tests':test})
    
    # index.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    {% for test in tests %}
        <h2>{{ test.user }}</h2>
        <p>{{ test.pwd }}</p>
    {% endfor %}
    </body>
    </html>
    

    生活要有仪式感

    myfirstdjango

    相关文章

      网友评论

          本文标题:【二】MyFirstDjango

          本文链接:https://www.haomeiwen.com/subject/mofaxctx.html