Django_MVT(二)

一、MVT简介

M全拼为Model,与MVC中的M功能相同,负责和数据库交互,进行数据处理。

V全拼为View,与MVC中的C功能相同,接收请求,进行业务处理,返回应答。

T全拼为Template,与MVC中的V功能相同,负责封装构造要返回的html。

Django中的MVT遵守 MVC执行流程。

MVT即模型-模版-视图模式,其标准名称是有争议的。在MVC的解释中,视图描述了展现给用户的数据,是指所看到的数据,而不是如何看见它。在python中视图是指对某一特定URL的回调函数,因为回调函数描述了所要展现的数据。模版用于将内容与展现分离。在django中,视图描述了要展现的数据,而视图一般转交给模版。模版描述了数据如何展现,控制器则是指django框架本身,通过URL配置,系统将一个请求发送到一个合适的视图。

二、M-模型类

我们之前操作数据库是通过写sql语句,那么能不能不写sql语句就可以操作数据库呢? 可以,就是通过接下来要给大家讲的ORM框架。

O是object,也就类对象的意思,R是relation,翻译成中文是关系,也就是关系数据库中数据表的意思,M是mapping,是映射的意思。在ORM框架中,它帮我们把类和数据表进行了一个映射,可以让我们通过类和类对象就能操作它所对应的表格中的数据。ORM框架还有一个功能,它可以根据我们设计的类自动帮我们生成数据库中的表格,省去了我们自己建表的过程。

django中内嵌了ORM框架,不需要直接面向数据库编程,而是定义模型类,通过模型类和对象完成数据表的增删改查操作。

使用django进行数据库开发的步骤如下:

  • 1.在models.py中定义模型类
  • 2.迁移
  • 3.通过实例对象完成数据增删改查操作

下面我们以保存图书信息为例来给大家介绍Django中进行数据库开发的整个流程。

1. 定义模型类

模型类定义在models.py文件中,继承自models.Model类。

说明:不需要定义主键,在生成时会自动添加,并且值为自动增长。

设计书籍类

书籍类:

  • 类名:BookInfo
  • 书籍名称:btitle
  • 发布日期:bpub_date

根据设计,在./booktest/models.py中定义模型类如下:

from django.db import models

class BookInfo(models.Model):
    btitle = models.CharField(max_length=20)
    bpub_date = models.DateField()

2. 迁移

迁移由两步完成:

  1. 生成迁移文件:根据模型类生成创建表的迁移文件。
  2. 执行迁移:根据第一步生成的迁移文件在数据库中创建表。

2.1 生成迁移文件命令如下:

python manage.py makemigrations

 执行生成迁移文件命令后,会在应用booktest目录下的migrations目录中生成迁移文件。

 打开上图中的迁移文件,内容如下:

# Generated by Django 3.1.2 on 2020-10-25 12:27

from django.db import migrations, models


class Migration(migrations.Migration):

    initial = True

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='BookInfo',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('btitle', models.CharField(max_length=20)),
                ('bpub_date', models.DateField()),
            ],
        ),
    ]

Django框架根据我们设计的模型类生成了迁移文件,在迁移文件中我们可以看到fields列表中每一个元素跟BookInfo类属性名以及属性的类型是一致的。同时我们发现多了一个id项,这一项是Django框架帮我们自动生成的,在创建表的时候id就会作为对应表的主键列,并且主键列自动增长。

2.2 执行迁移命令如下:

python manage.py migrate

 当执行迁移命令后,Django框架会读取迁移文件自动帮我们在数据库中生成对应的表格。数据表的默认名称为:<app_name>_<model_name> 例:booktest_bookinfo

3. 数据基础操作

 完成数据表的迁移之后,进入Python交互模式并尝试使用Django提供的免费API。注意,我们不能直接键入"python"进入交互模式,要使用以下命令调用Python Shell

python manage.py shell

因为在manage.py 文件中设置了DJANGO_SETTINGS_MODULE环境变量,它为Django提供python到test1/settings.py文件的导入路径

如果直接键入“python”进入交互模式,在from booktest.models import BookInfo时会报如下错误:

django.core.exceptions.ImproperlyConfigured: Requested setting INSTALLED_APPS, but settings are not configured. 
You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.

需要手动加上DJANGO_SETTINGS_MODULE环境变量

>>> import os,django
>>> os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test1.settings")
'test1.settings'
>>> django.setup()
>>> from booktest.models import BookInfo
>>> BookInfo.objects.all()
<QuerySet []>
>>>

进入Shell后,探索数据库API

>>> from booktest.models import BookInfo
>>> # 查询数据库所有信息
>>> BookInfo.objects.all()        
<QuerySet []>
>>>
>>> #新增数据
>>> book1=BookInfo()  
>>> book1.btitle='射雕英雄传'  
>>> import datetime
>>> book1.bpub_date=datetime.date(1990, 1, 1)   
>>> book1.save()        
>>> BookInfo.objects.all()
<QuerySet [<BookInfo: BookInfo object (1)>]>
>>>
>>>
>>> # 查找指定条件数据
>>> book2=BookInfo.objects.get(id=1)
>>> book2.btitle
'射雕英雄传'
>>> 
>>> # 修改数据
>>> book2.btitle='神雕侠侣'
>>> book2.save()
>>>
>>> # 删除数据
>>> book2.delete()
(1, {'booktest.BookInfo': 1})
>>> BookInfo.objects.all()
<QuerySet []>

更多api方法可查看django源码,路径为:django.db.models.query.QuerySet

QuerySet [<BookInfo: BookInfo object (1)>]>对于了解这个对象不是很直观的,可以给 BookInfo 模型类(位于 test1/models.py 中)增加 __str__() 方法来解决这个问题。

class BookInfo(models.Model):
    ...

    def __str__(self):
        return F"btitle:{self.btitle},bpub_date:{self.btitle}"

重进Shell后

>>> from booktest.models import BookInfo
>>> BookInfo.objects.all()
<QuerySet [<BookInfo: btitle:射雕英雄传,bpub_date:1980-05-01>, <BookInfo: btitle:天龙八部,bpub_date:1986-07-24>, <BookInfo: btitle:雪山飞狐,bpub_date:1987-11-11>]>
>>>

三、V-视图

对于django设计的MVT框架,用户在URL中请求的是视图,视图接收请求后进行处理,并将处理的结果返回给请求者。

使用视图时需要进行两步操作:

  1. 定义视图函数
  2. 配置URLconf

1.定义视图

视图就是一个Python函数,被定义在views.py中。

视图的必须有一个参数,一般定义为request,视图必须返回HttpResponse对象,HttpResponse中的参数内容会显示在浏览器的页面上。

打开booktest/views.py文件,定义视图index如下

from django.http import HttpResponse

def index(request):
    return HttpResponse("hello python!")

2.配置URLconf

视图的查找过程是请求者在浏览器地址栏中输入url,请求到网站后,获取url信息,然后与编写好的URLconf逐条匹配,如果匹配成功则调用对应的视图函数,如果所有的URLconf都没有匹配成功,则返回404错误。

一条URLconf包括url规则、视图两部分:

  • url规则使用正则表达式定义。
  • 视图就是在views.py中定义的视图函数。

需要两步完成URLconf配置:

  • 1.在应用中定义URLconf
  • 2.包含到项目的URLconf中

在booktest/应用下新建urls.py文件,定义代码如下:

from django.conf.urls import url
from booktest import views
urlpatterns = [
    url('index', views.index),
]

将booktest/urls包含到项目中:打开test1/urls.py文件,为urlpatterns列表增加项如下:

path('booktest/', include('booktest.urls')),

test1/urls.py文件完整代码如下:

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('booktest/', include('booktest.urls')),    # booktest/ 可以为空白
]

访问服务器

视图和URLconf都定义好了,接下来在浏览器地址栏中输入网址:

 

四、T-模板

如何向请求者返回一个漂亮的页面呢?

肯定需要用到html、css,如果想要更炫的效果还要加入js,问题来了,这么一堆字段串全都写到视图中,作为HttpResponse()的参数吗?这样定义就太麻烦了吧,因为定义字符串是不会出任何效果和错误的,如果有一个专门定义前端页面的地方就好了。

解决问题的技术来了:模板

在Django中,将前端的内容定义在模板中,然后再把模板交给视图调用,各种漂亮、炫酷的效果就出现了。

创建模板文件

在项目test1中新增templates目录,现在我们可以直接将模板放入 test1/templates,但实际上并不建议这样做。Django会选择找到的第一个名称匹配的模板,如果在其他应用有一个具有相同名称的模板,Django则无法区分它们。我们需要Django能够指向正确的位置,而确保这一点的最佳方法是将这些模板放在应用程序本身命名的另一个目录中。目录结构如下图:

 

设置模板的查找路径:打开test1/settings.py文件,设置TEMPLATES的DIRS值

'DIRS': [os.path.join(BASE_DIR, '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',
            ],
        },
    },
]

定义模板

在模板中输出变量语法如下,变量可能是从视图中传递过来的,也可能是在模板中定义的。

{{变量名}}

在模板中编写代码段语法如下:

{%代码段%}

打开templtes/booktest/index.html文件,定义模板如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>图书列表</title>
    <style>
        td {text-align: center;}
    </style>
</head>
<body>
<h1>{{title}}</h1>
<table width="500px">
    <tr>
        <th>书籍名称</th>
        <th>发布日期</th>
    </tr>
{%for book in books%}
    <tr>
        <td>{{book.btitle}}</td>
        <td>{{book.bpub_date}}</td>
    </tr>
{%endfor%}
</table> </body> </html>

视图调用模板

调用模板分为三步骤:

  • 1.找到模板
  • 2.定义上下文
  • 3.渲染模板

打开booktst/views.py文件,调用上面定义的模板文件

from django.shortcuts import render
from booktest.models import BookInfo
from django.http import HttpResponse
from django.template import loader, RequestContext

# Create your views here.


def index(request):
    # 1.获取模板
    template=loader.get_template('booktest/index.html')
    # 2.定义上下文
    books = BookInfo.objects.all()
    # context=RequestContext(request,{'title':'图书列表','books':books})    # 老版本
    context = {'title': '图书列表', 'books': books}
    # 3.渲染模板
    # return HttpResponse(template.render(context))     # 老版本
    return HttpResponse(template.render(context, request))

打开浏览器刷新页面,显示效果如下图:

视图调用模板简写

视图调用模板都要执行以上三部分,于是Django提供了一个函数render封装了以上代码。 方法render包含3个参数:

  • 第一个参数为request对象
  • 第二个参数为模板文件路径
  • 第三个参数为字典,表示向模板中传递的上下文数据

打开booktst/views.py文件,调用render的代码如下:

from django.shortcuts import render
from booktest.models import BookInfo

# Create your views here.


def index(request):
    books = BookInfo.objects.all()
    context = {'title': '图书列表', 'books': books}
    return render(request, 'booktest/index.html', context)

 综合案例: https://www.cnblogs.com/testlearn/p/13897597.html

 

posted @ 2020-10-25 20:43  码上测  阅读(188)  评论(0编辑  收藏  举报