Django学习笔记(1)_MTV简单介绍及应用

目录

Django介绍

MTV 模型

创建Django项目:

创建应用:

运行项目:

一、模板

1.变量

2.列表

3.字典

4.过滤器

5.if/else标签

6.for标签

7.ifequal/ifnotequal标签

8.注释标签

9.include标签:

10.csrf_token标签

11.HTML转义

12.自定义标签和过滤器

13.装饰器

14.模板继承

二、模型

Django ORM

​2.1mysql数据库配置

2.2定义模型

2.3数据库操作

2.4模型类关系

2.5后台管理

三、视图

3.1视图层

3.2请求对象: HttpRequest 对象(简称 request 对象)包含浏览器的请求信息

3.3 响应对象:HttpResponse 对象

3.4 HTTP请求

四、路由(urls.py )

4.1.正则路径中的分组

4.2路由分发

4.3反向解析

4.4命名空间

实例:

 


Django介绍

Django是一个遵循 MVC 设计模式的框架,MVC是Model、View、Controller三个单词的简写,分别代表模型、视图、控制器。

Django其实也是一个MTV 的设计模式,MTV是Model、Template、View三个单词的简写,分别代表模型、模版、视图   。但是在Django中,控制器接受用户输入的部分由框架自行处理,所以 Django 里更关注的是模型(Model)、模板(Template)和视图(Views),它们各自的职责如下:

MTV 模型

  • M 表示模型(Model):编写程序应有的功能,负责业务对象与数据库的映射(ORM)。

  • T 表示模板 (Template):负责如何把页面(html)展示给用户。

  • V 表示视图(View):负责业务逻辑,并在适当时候调用 Model和 Template(通常是views.py:定义不同的函数,处理不同的请求)。

  • URL 分发器:将一个个 URL 的页面请求分发给不同的 View 处理,View 再调用相应的 Model 和 Template。(urls.py:用户请求的url和视图建立映射关系)

 

创建Django项目:

1.命令行方式:

terminal:切换到想建项目的目录,django-admin startproject  项目名称,会自动生成如下项目目录

terminal:conda activate 激活conda

2.Pycharm方式:

file ---> new project ---- 选择Django ---> 配置路径和项目名称 ---> 配置环境(默认用系统环境) ----> 点击create(完成创建)

项目目录介绍:

 

  • mydjango: 项目的容器。

  • manage.py: 一个实用的命令行工具,可让你以各种方式与该 Django 项目进行交互。

  • mydjango/init.py:一个空文件,告诉 Python 该目录是一个 Python 包。

  • mydjango/asgi.py:一个 ASGI 兼容的 Web 服务器的入口,以便运行你的项目。

  • mydjango/settings.py: 该 Django 项目的设置/配置。

  • mydjango/urls.py: 该 Django 项目的 URL 声明; 一份由 Django 驱动的网站"目录",保存url与视图的对应关系

  • mydjango/wsgi.py: 一个 WSGI 兼容的 Web 服务器的入口,以便运行你的项目。

     

    根目录下新建statics文件夹放置css、js等静态文件

    1.在 settings.py 文件的最下方配置添加以下配置:

    STATIC_URL = '/static/' # 别名 
    STATICFILES_DIRS = [ 
        os.path.join(BASE_DIR, "statics"), #自己建的文件名称statics
    ]

    2.在 statics 目录下创建 css 目录,js 目录,images 目录,plugins 目录, 分别放 css文件,js文件,图片,插件。

    3.在模板文件中:

  • <img src="/static/images/flower.jpg">

  • 动态获取STARIC_URL,拼接静态文件路径:

{% load staticfiles %}  //引入

<img src="{ % static  ' images/flower.jpg'   % }">  // 拼接

应用实例:在mydjango下新建视图views.py处理请求,在urls.py中urlpatterns里建立路径和视图的对应关系,启动项目。

创建应用:

一个项目可能有多个功能模块,一个功能模块对应一个应用APP

1.命令行模式创建应用:在 Terminal 中输入 python manage.py startapp 应用名

或者django-admin.exe startapp 应用名。

配置settings.py,将应用名字进行注册

2.使用pycharm创建:file--->new project  --> django ---> Location选择此项目,在More Settings 中Application name :app名字。

应用目录说明:

  • myapp1:app名称
  • myapp1/migrations:数据模型迁移记录
  • myapp1/admin.py:自带的admin,后台管理
  • myapp1/apps.py:app相关
  • myapp1/modela.py:数据映射关系,模型类,和数据库相关
  • myapp1/views.py:视图相关,定义不同(视图)函数,接收请求,进行处理,返回应答

运行项目:

1.命令行:和manage.py同级目录下,在终端  python  manage.py  runserver  127.0.0.1:8000

2.pycharm:Edit Configurations配置信息,绿色三角或者直接按 Ctrl+shift+F10

退出项目:Ctrl+C退出

 

一、模板

上例将数据与视图混合在一起,不符合 Django 的 MVC 思想。 Django 模板,用于分离文档的表现形式和内容

1.)根目录下新建templates文件夹放置模板文件(html页面)

2.)配置模板目录

修改mydjango/settings.py,修改 TEMPLATES 中的 DIRS 为 [BASE_DIR /  "templates",]

或者

3)可以在templates为每个app应用建一个文件夹,放置每个应用的模板文件

使用模板文件:

  1. 加载模板文件:去模板目录获取HTML文件
  2. 定义模板上下文:向模板传递数据
  3. 模板渲染:得到一个标准的HTML内容

实例:数据与视图分离

1.变量

模板变量名由数字,字母,下划线和点组成,不能以下划线开头。字典.mydict,列表.mylist,对象.属性名

view:{"HTML变量名" : "views变量名"}
HTML:{{变量名}}

2.列表

view: context['list'] = list(range(1,5))
HTML:{% for i in list %}
          <li>{{ i }}</li>
     {% endfor %}

3.字典

4.过滤器

5.if/else标签

6.for标签

{% for book in books %}
       {{ forloop.counter }}//得到循环次数1,2,3.。。。
      <li>{{ book.title }}</li>
{% empty %}
    内容为空
{% endfor %}

7.ifequal/ifnotequal标签

8.注释标签

{# 这是一个单行注释 #}
{% comment %}
    多行注释
{% endcomment %}

9.include标签:

在模板中包含其他模板的内容  {% include "nav.html" %}

10.csrf_token标签

防止csrf:默认打开CSRF中间件,post提交时加上{% csrf_token %}标签

防御原理:

  1. 渲染模板时生成csrfmiddlewaretoken的隐藏域。
  2. 服务器交给浏览器保存一个名为csrftoken的cookie信息。
  3. 提交表单时,两个值都发给服务器,服务器对比,一样验证通过。

11.HTML转义

HTML默认标记是会被转义的,例如<会变为&lt,带格式显示需要关闭转义,才能解析为HTML格式。

1)safe过滤器关闭转义   2)autoescape关闭转义

12.自定义标签和过滤器

13.装饰器

有许多操作是用户登录之后才能进行的,比如修改密码,首页,都需要先判断用户是否登录,如果没有登录不能显示相应页面。

#登录判断的装饰器
def login_required(view_func):
    def wrapper(request,*view_args,**view_kwargs):
        #判断用户是否登录
        if request.session.has_key('islogin'):
            #用户已经登录
            return view_func(request,*view_args,**view_kwargs)
        else:
            #用户未登录
            return redirect('login')
    return wrapper
    

#装饰器
@login_required
#修改密码
def change_pwd(request):
    ......

14.模板继承

问题:网页中有很多重复出现的内容,比如标题、导航栏等,每个页面都写冗余

解决:模板继承,重复的部分作为父模板,不同的部分在父模板中预留块,子模板继承父模板,重写预留块

【base.html】

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>父模板</title>
</head>
<body>
<div style="background-color: chocolate ;width: 900px;height: 100px">
    <h2>导航栏</h2>
</div>

<div style="width: 900px;height: 300px">
 {% block main %}
    {% block main_left %}
    <div style="float: left;width: 300px;height: 300px;background-color: limegreen"> <h5>父模块中左==左==左</h5></div>
    {% endblock main_left %}

     {% block main_right %}
    <div style="float: right;width: 300px;height: 300px;background-color: red"> <h5>父模块中预留块右==右==右</h5></div>
    {% endblock main_right %}

{% endblock main %}
</div>

<div style="height: 100px;width: 900px;background-color: darkorchid">
    <h4>版权</h4>
</div>

</body>
</html>

【child.html】

{# 模板继承 #}
{% extends 'base.html' %}
{% block main_left %}
    {#  显示父模板中内容  #}
    {#    {{ block.super }}#}
    <div style="float: left;width: 200px;height: 200px;background-color: blue">
    <h5>child模块中新加的内容</h5>
    </div>

{% endblock main_left %}

二、模型

Django 对各种数据库提供了很好的支持,包括:PostgreSQL、MySQL、SQLite、Oracle。Django 为这些数据库提供了统一的调用API。,我们可以根据自己业务需求选择不同的数据库。

Django ORM

对象关系映射(Object Relational Mapping,简称 ORM )用于实现面向对象编程语言里不同类型系统的数据之间的转换。

ORM 在业务逻辑层和数据库层之间充当了桥梁的作用。

ORM 是通过使用描述对象和数据库之间的映射的元数据,将程序中的对象自动持久化到数据库中。通过类和对象就可以对数据表进行操作。

2.1mysql数据库配置

1.首先手动创建数据库(mysql数据库,可以利用数据库图形化软件创建)

2.settings.py 文件中找到 DATABASES 配置项,将其信息修改为:

DATABASES = {    
'default':    
    {    
      'ENGINE': 'django.db.backends.mysql',  # 数据库引擎      
      'NAME': 'django_db', # 数据库名称      
      'HOST': '127.0.0.1', # 数据库地址,本机 ip 地址 127.0.0.1  
      'PORT': 3306, # 端口         
      'USER': 'root',  # 数据库用户名        
      'PASSWORD': '11111111', # 数据库密码      
      }  
}

3.安装pymysql:pip install pymysql

4.告诉 Django 使用 pymysql 模块连接 mysql 数据库:

#在与 settings.py 同级目录下的 __init__.py 中引入模块和进行配置

import pymysql 
pymysql.install_as_MySQLdb()

2.2定义模型

1.定义模型类 myapp1/models.py 文件(模型类==数据库表)

from django.db import models
# Create your models here.

#设计图书模型类,类名代表数据库表名,必须继承Model
class BookInfo(models.Model):
    #类里的字段代表数据库表中的字段,
    #图书名称,CharField字符串,长度20
    title=models.CharField(max_length=20)
    #出版日期,DataField日期类型
    pub_data=models.DateField()


"""
属性命名限制:
1)不能是python保留关键字
2)不允许使用连续的下划线
3)定义属性时需要指定字段类型,属性名=models.字段类型()
"""

2.模型类生成数据表

terminal命令行中:

> python  manage.py migrate   # 创建表结构
1)生成迁移文件
> python  manage.py makemigrations   
2)执行迁移生成表
> python  manage.py migrate    # 创建表结构

执行后会在应用的migrations中生成迁移文件,数据库生成数据表。数据库表名组成结构为:应用(app)名_模型类名(如:myapp1_bookInfo)

 

2.3数据库操作

  • 添加数据

先创建对象,再执行save()函数

\# 数据库操作 
def testdb(request):   
    test1 = Test(name='runoob')    
    test1.save()    
    return HttpResponse("<p>数据添加成功!</p>")
  • 获取数据

objects.all()  #返回所有 ,返回值是模型类对象

objects.filter(查询条件)  # 返回满足条件的数据   返回值是查询集 【模糊查询,范围查询,比较查询,日期查询】

object.exclude(查询条件)  #返回不满足条件的数据  返回值是查询集

objects.get(查询条件)#返回一条数据,没有或者多条会抛异常  返回值是查询集

objects.order_by() #排序  返回值是查询集 

 

 

【Q对象】:用于查询条件之间的逻辑关系,可以对Q对象进行&且,| ~
 

##导入Q对象
from django.db.models import Q

#查询id大于3  且  阅读量大于30的图书信息
Book.objects.filter(id__gt=3,read__gt=30)

Book.objects.filter(Q(id__gt=3)&Q(read__gt=30))

#查询id大于3  或  阅读量大于30的图书信息
Book.objects.filter(Q(id__gt=3)|Q(read__gt=30))

#查询id 不等于 5的图书
Book.objects.filter(~Q(id__gt=3))

【F对象】:用于类属性之间的比较

##导入F对象
from django.db.models import F

#查询图书阅读量大于评论量的图书信息
Book.objects.filter(read__gt=F('comment'))

【聚合】sum   count   avg  max  min

#导入聚合类
from django.db.models import Sum,Count,Max,Min,Avg
#要调用aggregate()函数来使用聚合,返回值是字典{{'类属性_聚合种类':结果}}

#查询所有图书的数目
Book.objects.aggregate(Count(id))#返回值{{'id_count':5}}

【查询集】

1>惰性查询:只在实际使用时查询

2>缓存:第一次查询结果缓存起来,第二次使用缓存中的数据

3>切片会产生一个查询集

Book.objects.order_by('name')[0:2] # 限制返回的数据 相当于 SQL 中的 OFFSET 0 LIMIT 2;

  • 更新数据

save()

update()

  • 删除数据

delete()

2.4模型类关系

【一对一关系】关系属性 models.OneToOneField 定义在哪个类中都可以

【一对多关系】关系属性 models.ForeignKey ( ) 定义在多的类
models.py

from django.db import models

# Create your models here.

#设计图书 模型类
class BookInfo(models.Model):
    #图书名称,CharField字符串,长度20
    title=models.CharField(max_length=20)
    #出版日期,DataField日期类型
    pub_data=models.DateField()

   

"""
图书和英雄是一对多的关系,在多的一方建立外键,
"""

#英雄人物 模型类
class HeroInfo(models.Model):
    #名称
    hname=models.CharField(max_length=10)
    #性别,布尔类,default指定默认值
    hgender=models.BooleanField(default=False)
    #备注
    hcomment=models.CharField(max_length=128)
    #关系属性 hbook建立图书和英雄人物类之间一对多关系
    #数据库表中关系属性的字段名:关系属性名_id,例如:hbook_id
    hbook=models.ForeignKey('BookInfo',on_delete=models.DO_NOTHING)
    """on_delete=None, # 删除关联表中的数据时,当前表与其关联的field的行为
        on_delete=models.CASCADE, # 删除关联数据,与之关联也删除
        on_delete=models.DO_NOTHING, # 删除关联数据,什么也不做
    django 升级到2.0之后,表与表之间关联的时候,必须要写on_delete参数,否则会报异常,
    由于多对多(ManyToManyField)没有 on_delete 参数,
    所以以上只针对外键(ForeignKey)和一对一(OneToOneField)"""

    

关联查询


#查询id为1的图书关联的英雄信息

b=BookInfo.objects.get(id=1)

heros=b.heroinfo_set.all()
#通过模型类查询
heros=HeroInfo.objects.filter(hbook__id=1)

#查询id为1的英雄关联的图书信息

h=HeroInfo.objects.get(id=1)

books=h.hbook
#通过模型类查询
books=BookInfo.object.filter(heroinfo__id=1)

"""
通过多类条件查询一类数据:

一类名.objects.filter(多类名小写__多类属性名_条件名)

通过一类条件查询多类类数据:

多类名.objects.filter(关联属性名__一类属性名_条件名)
"""


 

【多对多关系】关系属性 models.ManyToManyField ( ) 定义在哪个类都行

【自关联】特殊的一对多

 

2.5后台管理

在创建的应用中admin.py是后台管理文件

1)本地化

       语言和时区的本地化,修改settings.py

 

2)创建管理员

命令行:python manage.py createsuperuser ,然后输入用户名,邮箱,密码

启动项目,地址栏http://127.0.0.1:8000/admin  登录

3)注册模型类

在应用下的admin.py中注册模型类,告诉Django框架根据注册的模型生成对应的表管理界面。<1>导入<2>注册

再登录管理界面就能看到BookInfo

4)自定义管理页面

想显示数据表更多的信息,需要自定义管理页面

list_display=[' id '  ]: 页面显示的列内容

list_per_page=10: 每页显示10条数据

list_filter=[ ' ' ]:列表右侧过滤栏

search_fields = [ ' ' ]:列表上方搜索框

三、视图

3.1视图层

一个视图函数,简称视图,是一个简单的 Python 函数,它接受 Web 请求并且返回 Web 响应。响应可以是一个 HTML 页面、一个 404 错误页面、重定向页面、XML 文档、或者一张图片...

无论视图本身包含什么逻辑,都要返回响应。代码写在哪里都可以,只要在 Python 目录下面,一般放在项目的 views.py 文件中。每个视图函数都负责返回一个 HttpResponse 对象,对象中包含生成的响应。

视图层中有两个重要的对象:请求对象(HttpRequest)与响应对象(HttpResponse)。

3.2请求对象: HttpRequest 对象(简称 request 对象)包含浏览器的请求信息

常用的request方法

1.request.GET  保存get方法提交的内容,类型是QueryDict

request.GET.get():返回字符串,如果该键对应有多个值,取出该键的最后一个值

def login_check(request):
    #取得请求中的用户名
    username=request.GET.get(" username'')

2.request.POST  保存post方法提交的内容,类型是QueryDict

get():返回字符串,如果该键对应有多个值,取出该键的最后一个值

def login_check(request):
    #取得请求中的用户名
    username=request.POST.get(" username'')

3.request.body

4.request.path   获取 URL 中的路径部分,不包括域名和参数,数据类型是字符串

5.request.method  返回request的请求类型,POST还是GET

3.3 响应对象:HttpResponse 对象

HttpResponse(): 返回文本,参数为字符串,字符串中写文本内容。如果参数为字符串里含有 html 标签,也可以渲染。

def runoob(request):
    return HttpResponse("菜鸟教程")
    return HttpResponse("<a href='http://https://www.runoob.com/>菜鸟教程</a>")

render(): 返回文本,第一个参数为 request,第二个参数为字符串(页面名称),第三个参数为字典(可选参数,向页面传递的参数:键为页面参数名,值为views参数名)

def runoob(request):
   name ="菜鸟教程"
   return render(request,"runoob.html",{"name":name})

redirect()重定向,浏览器再发起到另一个页面的请求。参数为字符串,字符串中填写页面路径。一般用于 form 表单提交后,跳转到新页面。

from django.http import  HttpResponseRedirect
from django.shortcuts import render, redirect

#到login_check的请求重定向到index
def login_check(request):
    #密码正确,重定向到首页index
    #return HttpResponseRedirect('/index')
    return redirect('/index')#简写形式
   

3.4 HTTP请求

【GET方法】:提交的参数在url中,可以看到请求内容

获取请求内容:request.GET[' input的name ']

  <!--get请求,调用/search方法-->
 <form action="/search" method="get">
    <input type="text" name="q">
    <input type="submit" value="搜索">
</form>

【POST方法】:提交的参数在请求头中

获取请求内容:request.POST[' input标签的name ']

<html> 
    <head>
        <meta charset="utf-8"> 
        <title>学习post方法</title>
    </head> 
    <body>  
        <!--    post请求,调用search-post方法-->
        <form action="/search-post" method="post">       
            {% csrf_token %}       
            <input type="text" name="q">        
            <input type="submit" value="Submit">    
        </form>     
        <p>{{ rlt }}</p> 
    </body> 
</html>

表格后面有一个{% csrf_token %}的标签,csrf 全称是 Cross Site Request Forgery,这是Django提供的防止伪装提交请求的功能,POST 方法提交的表格,必须有此标签。 rlt 记号,为表格处理结果预留位置。

 

四、路由(urls.py )

路由简单的来说就是根据用户请求的 URL 链接来判断对应的处理程序,并返回处理结果,也就是 URLDjango 的视图函数建立映射关系。

Django 路由在 urls.py 配置,urls.py 中的每一条配置对应相应的处理方法。

Django 不同版本 urls.py 配置有点不一样:

Django1.1.x 版本

url() 方法:普通路径和正则路径均可使用,需要自己手动添加正则首位限制符号。

from django.conf.urls import url # 用 url 需要引入 
 
 urlpatterns = [ 
   url(r'^admin/$', admin.site.urls), 
   url(r'^index/$', views.index), # 普通路径 
   url(r'^articles/([0-9]{4})/$', views.articles), # 正则路径 
 ]

Django 2.2.x 之后的版本

  • path:用于普通路径,不需要自己手动添加正则首位限制符号,底层已经添加。

  • re_path:用于正则路径,需要自己手动添加正则首位限制符号。

from django.urls import re_path # 用re_path 需要引入 
 urlpatterns = [ 
   path('admin/', admin.site.urls), 
   path('index/', views.index), # 普通路径 
   re_path(r'^articles/([0-9]{4})/$', views.articles), # 正则路径 
 ]

4.1.正则路径中的分组

正则路径中的无名分组:无名分组按位置传参,一一对应。

正则路径中的有名分组:有名分组按关键字传参,与位置顺序无关。

4.2路由分发

存在问题:Django 项目里多个app目录共用一个 urls 容易造成混淆,后期维护也不方便。

解决:使用路由分发(include),让每个app目录都单独拥有自己的 urls。每当Django遇到时include(),它都会截断直到该处匹配的URL的任何部分,并将剩余的字符串发送到包含的URLconf中以进行进一步处理。

步骤:

  • 1、在每个 app 目录里都创建一个 urls.py 文件。

  • 2、在项目名称目录下的 urls 文件里,统一将路径分发给各个 app 目录。

    **from** django.contrib **import** admin 
     **from** django.urls **import** path,include # 从 django.urls 引入 include 
     urlpatterns = [ 
       path('admin/', admin.site.urls), 
       path("app01/", include("app01.urls")), 
       path("app02/", include("app02.urls")), 
     ]

    或者使用path()实例列表包括其他URL模块

    myapp1 = [
        path('reports/', myapp1_views.report),
        path('charge/', myapp1_views.charge),
    ]
    
    urlpatterns = [
        path('', main_views.homepage),
        path('myapp1/', include(myapp1)),
    ]
    
    #这样也可以达到共用前缀myapp1,可以避免单个前缀冗余

     

  • 3、在各自 app 目录下,写自己的 urls.py 文件,进行路径跳转。

app01 目录:

from django.urls import path,re_path 
from app01 import views # 从自己的 app 目录引入 views 
urlpatterns = [ 
    re_path(r'^login/(?P<m>[0-9]{2})/$', views.index, ),
] 

app02 目录:

from django.urls import path,re_path
from app02 import views # 从自己的 app 目录引入views 
urlpatterns = [ 
    re_path("^xxx/(?P[0-9]{4})/$", views.xxx), 
]
  • 4、在各自 app 目录下的 views.py 文件中写各自的视图函数。

4.3反向解析

随着功能的增加,路由层的 url 发生变化,就需要去更改对应的视图层和模板层的 url,非常麻烦,不便维护。这时我们可以利用反向解析,当路由层 url 发生改变,在视图层和模板层动态反向解析出更改后的 url,免去修改的操作。反向解析一般用在模板中的超链接及视图中的重定向。

普通路径

  • 在 urls.py 中给路由起别名,name="路由别名"

path("login1/", views.login, name="login")
  • 在 views.py 中,从 django.urls 中引入 reverse,利用 reverse("路由别名") 反向解析:

return redirect(reverse("login"))
  • 在模板 templates 中的 HTML 文件中,利用 {% url "路由别名" %} 反向解析。

<form action="{% url 'login' %}" method="post"> 

正则路径(无名分组)

  • 在 urls.py 中给路由起别名,name="路由别名"

re_path(r"^login/([0-9]{2})/$", views.login, name="login")
  • 在 views.py 中,从 django.urls 中引入 reverse,利用 reverse("路由别名",args=(符合正则匹配的参数,)) 反向解析。

return redirect(reverse("login",args=(10,)))
  • 在模板 templates 中的 HTML 文件中利用 {% url "路由别名" 符合正则匹配的参数 %} 反向解析。

<form action="{% url 'login' 10 %}" method="post"> 

正则路径(有名分组)

  • 在 urls.py 中给路由起别名,name="路由别名"

re_path(r"^login/(?P<year>[0-9]{4})/$", views.login, name="login")
  • 在 views.py 中,从 django.urls 中引入 reverse,利用 reverse("路由别名",kwargs={"分组名":符合正则匹配的参数}) 反向解析。

return redirect(reverse("login",kwargs={"year":3333}))
  • 在模板 templates 中的 HTML 文件中,利用 {% url "路由别名" 分组名=符合正则匹配的参数 %} 反向解析。

<form action="{% url 'login' year=3333 %}" method="post">

4.4命名空间

命名空间(英语:Namespace)是表示标识符的可见范围。一个标识符可在多个命名空间中定义,它在不同命名空间中的含义是互不相干的。一个新的命名空间中可定义任何标识符,它们不会与任何重复的标识符发生冲突,因为重复的定义都处于其它命名空间中。

存在问题:路由别名 name 没有作用域,Django 在反向解析 URL 时,会在项目全局顺序搜索,当查找到第一个路由别名 name 指定 URL 时,立即返回。当在不同的 app 目录下的urls 中定义相同的路由别名 name 时,可能会导致 URL 反向解析错误。

解决:使用命名空间。

普通路径

  • 定义命名空间(include 里面是一个元组)格式如下:

include(("app名称:urls","app名称"))

实例:项目名称目录下的 urls 文件里,统一将路径分发给各个 app 目录

path("app01/", include(("app01.urls","app01"))) 
path("app01/", include(("app02.urls","app02")))
  • 在 app01/urls.py 中起相同的路由别名。

path("login/", views.login, name="login")
  • 在 views.py 中使用名称空间,语法格式如下:

reverse("app名称:路由别名")

实例:

return redirect(reverse("app01:login")
  • 在 templates 模板的 HTML 文件中使用名称空间,语法格式如下:

{% url "app名称:路由别名" %}

实例:

<form action="{% url 'app01:login' %}" method="post">

更多url知识:

https://blog.csdn.net/weixin_44870139/article/details/105565242

实例:

实现效果如下图,显示所有图书信息,点击图书展示图书中的英雄人物介绍。

实现步骤分析:

  1. 新建一个叫做booktest的应用,在settings.py中注册应用。
  2. 在templates模板文件夹中为booktest建一个文件夹放html,写页面。
  3. 在models.py中设计图书模型类和英雄模型类,一本书对应多个英雄,迁移生成数据库表,添加信息。
  4. views.py中定义视图函数,实现功能。
  5. 在urls.py中配置路由

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值