美文网首页
Django_01开发环境搭建

Django_01开发环境搭建

作者: tzktzk1 | 来源:发表于2023-11-27 17:25 被阅读0次

    开发环境搭建

    1.虚拟环境+库 安装django

      python -m venv myvenv
      myvenv Scripts activate.bat
      pip install Django
    

    2.start project 项目创建

      python -m django startproject djangosite
    

    3.start app 应用程序创建

      cd djangosite  (外面的djangosite)
      python manage.py startapp demo
    

    4注册app
    目的是被Diango发现,以便可以扫描到数据模型和模板

    image.png

    Djanog基本架构

    传统MVC

    image.png

    django改进的MVC---MTV

    image.png

    Modle:和数据库交互,通过Model可以不用直接操作数据库,提高了代码编写效率
    View: 处理用户的请求,和返回数据响应,可以直达用户
    Template: django独特的网页渲染方式,将内容配合模板渲染成网页展现给用户,需要配合前端基本知识使用(html css js)如果前后端分离则用不到此模块

    Django视图

    视图定义:处理http请求的部分,返回http响应

    Django如何定义视图

      # demo/views.py
      #定义视图--用户能看到的内容
      def index(request):
          return HttpResponse('lalala')
    

    如何访问该视图?

    通过路由系统

    Django的路由系统

    什么是路由 ?

    请求的向导,如用户访问 http://host/path/foo/bar 被系统转到foo视图函数,处理后返回结果

    路由原理

    通过解析传递过来的url,来分配具体执行的视图函数。可以理解为视图的调度器。


    image.png

    Django的路由定义

      # djangosite/urls.py
      from login import views
      urlpatterns = [
          path('admin/', admin.site.urls),
          path('index/',views.index),
      ]
    

    Django路由转发

    当系统比较复杂时,一层路由会显得很臃肿,且后期不好维护,所以我们可以把路由层层分解,这个叫做路由的转发。


    image.png

    蓝色的是总路由,统一处理用户的请求,后面五颜六色的是分路由,分别处理总路由发过来的请求。这个就好比之前的小店老板1个人处理业务就够了,但是现在公司做大了,老板接到活以后要分配给下面的员工来处理。

    路由的注意点

      末尾/的问题
      一般我们在定义路由的时候习惯末尾加/(斜杠)
    

    如果定义了斜杠

    那么浏览器访问的时候可以不带(会自动为你补全)
      但是请求工具,比如代码request必须带(不会自动补全)
    

    如果末尾没有定义/(斜杠)

      那么浏览器访问的时候不带/(不会自动帮你删/)
      同样请求工具,比如代码request也不能带/(不会自动补全也不会自动帮你删/)
    

    路由的分发

    对比下我们目前的路由文件 urls.py

            """
                路由文件
            """
            
            from django.contrib import admin
            from django.urls import path
            
            urlpatterns = [
                path('admin/', admin.site.urls),
            ]
            
            from testapp import views
            
            urlpatterns += [
                path("index/",views.index),    # 为你的项目添加一个可以访问的地址:http://127.0.0.1:8000/index/ 并返回某个视图的内容
                path("hello/",views.hello_world),
                path("world/",views.world),
                path('events/',views.events),  # 发布会管理页面
                path('events/detail',views.event_detail),   # 发布会详情页
            ]
    

    不同的app路由都统一集中到了一块,如果项目简单还好,项目复杂,url文件就会变得特别臃肿。
    所以为了后期好维护,我们可以将路由逐层分解。

    我们可以用django的include函数完成这个操作

      from django.urls import path,include
      path('1级路由/',include(视图模块))
    

    在app目录下新建分路由文件urls.py(这个文件名可以自定义,一般叫这个名字)

    demo/urls.py

      from django.urls import path,include
      from .  import views
      urlpatterns = [
          path('index/',views.index),
      ]
    

    sgin/urls.py

      from django.urls import path,include
      from .  import views
      urlpatterns = [
          path('events/',views.events),
          path('event_detail/',views.event_detail),
      ]
    

    修改主路由,开头导入include

      from django.contrib import admin
      from django.urls import path,include #导入include
      #第一步导入路由
      from demo import urls as demo_view
      from sgin import urls as sgin_view
      urlpatterns = [
          path('admin/', admin.site.urls),
          #路由分发
          path('demo/',include(demo_view)),  
          # 签到系统路由
          path('sgin/',include(sgin_view)),
      ]
    

    路由与视图组合练习

    创建应用程序 ---sgin

    python -m django startapp sgin # 或者django-admin startapp demo

    定义URL

      #djangosite/urls,py
      from sgin import views
      urlpatterns = [
          path('admin/', admin.site.urls),
          path('events/',views.events)   #列出发布会
      ]
    

    页面视图

      #sgin/views.py
      from django.http import HttpResponse
      def events(request):
          return HttpResponse('发布会')
    

    启动python开发服务器

    python manage.py runserver 9090 #最后一个表示端口号,随意,只要不和当前系统程序冲突即可

    升级视图-增加发布会数量

      def events(request):
          event_list=['测开发布会',
                      '自动化发布会',
                      '性能发布会',
                      '安全发布会',
                      '全栈发布会',
                      'ISTQB',
                      'TM项目管理',
                      'PMP考证']
          return HttpResponse('|'.join(event_list))
    

    视图再升级-加入html标签

      def events(request):
          event_list=['测开发布会',
                      '自动化发布会',
                      '性能发布会',
                      '安全发布会',
                      '全栈发布会',
                      'ISTQB',
                      'TM项目管理',
                      'PMP考证']
          #套入标签<li></li>中
          res=''.join([f'<li>{event}</li>' for event in event_list])
          return HttpResponse(res)
    

    这时候发现在代码里面修改html很麻烦,且不好维护,这个时候我们需要将html的内容外包给模板系统来处理,他负责对外展示的样式。

    Django模板--初识

    模板的作用

    用HMTL文件来保存待显示的内容,然后我们代码直接返回HTML文件即可
    我们只需利用Django的模板机制就可以实现

    用法--template

    首先在应用程序Login的目录下新建一个templates的目录 目录名必须相同
    然后新建HTML文件,里面塞入如下内容

      <!DOCTYPE html>
      <html lang="en">
          <head>   
              <meta charset="UTF-8">   
              <title>发布会</title>
          </head>
          <body>
              <h1>测试开发发布会</h1>
          </body>
      </html>
    

    模板实践---修改发布会视图返回,改为返回html文件

    return render(request,'events.html')

    刷新页面,展示的内容

    image.png
    第一个模板技术-变量

    作用:

    将视图函数的变量返回到模板中,django将其渲染

    用法:

    视图返回变量:{'模板中用到的变量名':变量}

      return render(request,'events.html',{'events':res})
    

    模板使用变量:{{变量名}}

      <body>
        {{ events }}   #标签中加入
      </body>
    

    刷新页面

    image.png

    发现变量自带的标签没有被渲染,对的,默认情况下django返回的变量中若带html标签是不会被渲染的,当然如果你本就不想渲染html标签,或者变量内容没有Html标签那么可以忽略,但是如果想的话,请看下面:

    第二个模板技术-for循环控制器

    作用:

    将列表类型的变量挨个展现出来

    用法:
    视图返回变量列表:
    修改下原视图函数的返回,之前是字符串,现在改为列表并且去掉标签

      #套入标签<li></li>中
          res=[event for event in event_list]
    
          return render(request,'events.html',{'events':res},)
    

    模板使用for:

      <ul>
      {% for event in events %}
          <li>{{ event }}</li>
      {% endfor %}
      </ul>
    

    发现没有?语法和 python几乎一样!不要忘记For循环结束要加{% endfor %},因为Html里是不认你的缩进的。。。
    刷新页面 正常了

    第三个模板技术-if控制器

    作用:

    条件控制,可以根据条件选择渲染哪些元素

    用法:

    视图返回变量同上

    模板使用变量:

      {% if 'ISTQB' in events %}
         <h3>8个发布会</h3>
      {% endif %}
    

    注意:在标签内使用变量不用再加{{}}了,否则会报错

    再换一个条件

      {% if events.length == 9 %}
         <h3>9个发布会</h3>
      {% endif %}
    

    发现没有生效,原因是在模板中.length这种列表自带的属性失效了,需要使用模板自带的过滤器来实现

    第四个模板技术-过滤器的用法

    作用:

    转换变量和标签参数的值

    写法:

    {{变量|过滤器}}

    上面的案例可以改成

      {% if events|length == 9 %}
         <h3>9个发布会</h3>
      {% endif %}
    

    刷新页面发现可以了

    内置的模拟器参考:https://docs.djangoproject.com/zh-hans/3.1/ref/templates/builtins/#ref-templates-builtins-tags
    Tips:当哪天你发现内置的模拟器也不能满足需求了,你可以自定义过滤器,不过如果你不专注前端开发可能很少用到了,参考:https://docs.djangoproject.com/zh-hans/3.1/howto/custom-template-tags/#writing-custom-template-filters

    页面的美化-更新模板加入静态文件

    加入静态文件
    image.png

    将提供的静态文件按照如上目录结构存放。
    由于我们要使用django的模板系统来渲染页面,所以引入静态文件需要遵循django的规则

      {% load static %}
         #开头加上该标签<!DOCTYPE html>
      <html lang="cn">
    

    同时修改外部文件的引入格式
    原来的引入方式

      <link href="assets/css/bootstrap.css " rel="stylesheet" />   #css
      <script src="assets/js/jquery-1.10.2.js"></script> #js
    

    修改后

      <link href="{% static 'assets/css/bootstrap.css' %} " rel="stylesheet" /> #css
      <script src="{% static 'assets/js/jquery-1.10.2.js' %}"></script>   #js
    
    填充模板页面

    将发布会信息显示到页面上

      {% for event in events %}
         <li>{{ event }}</li>
      {% endfor %}
    

    发现不好看,再选择性的加入一些样式

      <ul class="list-group">
         {% for event in events %}
         <li class="list-group-item text-center">{{ event }}</li>
         {% endfor %}
      </ul>
    

    Tips: class="list-group" class="list-group-item text-center" 表示使用该css文件时,class对应的样式,bootstrap为我们定义了现成的样式,只需要引入类即可,不用从头写cs

    完美呈现

    继续页面的开发

    展示发布会具体信息:名称,时间,地点 等
    从发布会管理页面链接到详情页
    增加返回

    此时发现一个问题,两个页面的基本样式都差不多---测边栏和页首菜单,只是中间区域不同
    如果只有两个页面还好,多个页面就会出现难以维护的情况,因为可能你改动一个样式就要改N个文
    件,非常不方便!
    所以我们丰富的编程思路该如何解决问题?
    对了,定义一个相对不变的公共模板,其他页面继承这个模板就可以了,模板留出接口,继承的页面只
    需要改动这个接口就可以。

    模板的继承

      {% block title%}{% endblock %}
    

    类似这种{% block 标签%}{% endblock %}格式的标签
    这个就是模板提供的接口,预留了空间让继承的子页面用于改动的
    我们要做的就是继承这个模板页面,改动需要改动的即可
    定义基础模板base.html表示根模板的意思

      <!-- base.html-->
      {% load static %}
      <!DOCTYPE html>
      <html lang="cn">
      
      <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta content="haiwen" name="author" />
        <!-- Bootstrap Styles-->
        <link href="{% static 'assets/css/bootstrap.css' %} " rel="stylesheet" />
        <!-- FontAwesome Styles-->
        <link href="{% static 'assets/css/font-awesome.css'%}" rel="stylesheet" />
        <!-- Custom Styles-->
        <link href="{% static 'assets/css/custom-styles.css' %}" rel="stylesheet" />
        <title>{% block title%}{% endblock %}</title>
      </head>
      
      <body>
      <div id="wrapper">
        <nav class="navbar navbar-default top-navbar" role="navigation">
          <div class="navbar-header">
            <a class="navbar-brand"><i class="icon fa fa-plane"></i> 发布会签到系统</a>
      
            <div id="sideNav" >
              <i class="fa fa-bars icon"></i>
            </div>
          </div>
      
          <ul class="nav navbar-top-links navbar-right">
            <li class="dropdown">
              <a class="dropdown-toggle" data-toggle="dropdown" href="#" aria-expanded="false">
                <i class="fa fa-user fa-fw"></i> <i class="fa fa-caret-down"></i>
              </a>
              <ul class="dropdown-menu dropdown-user">
                <li><a href="#"><i class="fa fa-user fa-fw"></i> User Profile</a>
                </li>
                <li><a href="#"><i class="fa fa-gear fa-fw"></i> Settings</a>
                </li>
                <li class="divider"></li>
                <li><a href="#"><i class="fa fa-sign-out fa-fw"></i> Logout</a>
                </li>
              </ul>
              <!-- /.dropdown-user -->
            </li>
          </ul>
        </nav>
        <!--/. NAV TOP  -->
        <nav class="navbar-default navbar-side" role="navigation">
          <div class="sidebar-collapse">
            <ul class="nav" id="main-menu">
              <li>
                <a class="active-menu" href="/sgin/events"><i class="fa fa-dashboard"></i> 发布会</a>
              </li>
              <li>
                <a href="/sgin/guests"><i class="fa fa-desktop"></i> 嘉宾</a>
              </li>
      
            </ul>
      
          </div>
      
        </nav>
        <!-- /. NAV SIDE  -->
      
        <div id="page-wrapper">
          <div class="header">
            <div class="page-header">
              {% block maintitle %}{% endblock %}
            </div>
      
          </div>
          <div id="page-inner" class="panel-body">
            {% block content%}
      
            {% endblock %}
            <footer><p>Author:haiwen.  <a href="https://ke.qq.com/course/3135766" target="_blank">松勤测试开发课程</a></p>
            </footer>
          </div>
          <!-- /. PAGE INNER  -->
      
        </div>
        <!-- /. PAGE WRAPPER  -->
      </div>
      
      
      <!-- jQuery Js -->
      <script src="{% static 'assets/js/jquery-1.10.2.js' %}"></script>
      <!-- Bootstrap Js -->
      <script src="{% static 'assets/js/bootstrap.min.js' %}"></script>
      
      <!-- Custom Js -->
      <script src="{% static 'assets/js/custom-scripts.js' %}"></script>
      <script>
        $(document).ready(
          $('#main-menu>li>a').each(function (){
            $(this).attr('class',''); //先取消选中
            let current_href = window.location.pathname
            if(current_href === $(this).attr('href')){
              $(this).attr('class','active-menu');
            }
          }),
        )
      </script>
      
      </body>
      
      </html>
    

    子页面events.html改写

      {% extends "base.html" %}
      {% block title%}发布会管理{% endblock %}
      {% block content%}
        <ul class="list-group">
          {% for event in event_list %}
            <li class="list-group-item text-center">
            <a href="/events/detail">{{ event }}</a>
            </li>
          {% endfor %}
        </ul>
      {% endblock %}
    

    开头的 {% extends "base.html" %} 表示继承base.html 页面
    {% block content %}{% endblock %} 这之间的内容就填写子页面特有的个性内容。
    刷新页面,依旧美丽,但是我们的Html文件简洁了很多,有木有!
    依次类推,我们可以在模板想要改动的地方留出接口,子页面继承的时候可以改动这些接口,这里并不
    是所有的接口都要子页面填充,你可以只填充你想填充的地方。
    原则就是,模板提供的接口,子页面可以填充,没有提供的接口,自然就填充不了哦
    依次类推,直接继承父模板,定义子页面

    event_detail.html

      {% extends 'base.html' %}
      {% block title%}发布会详情页{% endblock %}
      {% block content%}
      <h1>发布会详情页</h1>
        <p><a href="/events/" class="btn btn-info">返回发布会列表</a></p>
      {% endblock %}
    

    定义路由 urls.py

            """
                路由文件
            """
            
            from django.contrib import admin
            from django.urls import path
            
            urlpatterns = [
                path('admin/', admin.site.urls),
            ]
            
            from testapp import views
            
            urlpatterns += [
                path("index/",views.index),    # 为你的项目添加一个可以访问的地址:http://127.0.0.1:8000/index/ 并返回某个视图的内容
                path("hello/",views.hello_world),
                path("world/",views.world),
                path('events/',views.events),  # 发布会管理页面
                path('events/detail',views.event_detail),   # 发布会详情页
            ]
    

    定义视图 views.py

            from django.shortcuts import render
            from django.http import HttpResponse    # 管理项目请求和响应的一个包
            # Create your views here.
            """
                视图管理
            """
            
            # Create your views here.
            
            def events(request):
                event_list = [
                    '自动化发布会',
                    '测试开发布会',
                    '性能发布会',
                    '安全发布会',
                     '全栈发布会',
                    'ISTQB',
                    'TM项目管理',
                    'PMP考证'
                ]
                # 简单的返回字符串
                # return HttpResponse([f'<li>{event}</li>' for event in event_list])
                # 返回一个模板内容
                return render(request,'events.html',{'event_list':event_list})
            
            #发布会详情页
            def event_detail(request):
                return render(request,'event_detail.html')
            
            def index(request):
                # return HttpResponse("你好")
                return render(request,"index.html")
            
            def hello_world(request):
                return HttpResponse("hello_world是根据字符串作为返回值的")
            
            def world(request):
                # return HttpResponse("你好")
                return render(request,"world.html")
    

    访问 发布会详情页(http://127.0.0.1:9090/events/detail)

    附录--知识点官方文档

    路由:https://docs.djangoproject.com/zh-hans/3.1/topics/http/urls/
    视图:https://docs.djangoproject.com/zh-hans/3.1/topics/http/views/
    模板:https://docs.djangoproject.com/zh-hans/3.1/topics/templates/
    内置模板标签和过滤器:https://docs.djangoproject.com/zh-hans/3.1/ref/templates/builtins/#ref-templates-builtins-tags
    django通用术语:https://docs.djangoproject.com/zh-hans/3.1/glossary/

    相关文章

      网友评论

          本文标题:Django_01开发环境搭建

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