Django Model View Template 之间的简单交互 (二)

前言

接续前文,上一篇文章主要涉及了 Django 项目的基础配置等,这篇主要涉及数据库相关的 ORM ,也就是 Django 中的 Model 的使用,MVT 三层之间的交互html

教程基本都是东拼西凑的,防止有些东西表述不许确,由于我以前写 JavaScript 比较多。可是里边注入了本身的理解,尽可能讲清楚。前端

基础环境

  1. Pycharm 2018
  2. Django 2.0.3
  3. Python 3.6.4
  4. mxonline start 分支

Django Model 配置

代替使用原生的 SQL 语句操做数据库。python

原生 SQL 语句操做数据库

# {BASE_DIR}/apps/message/models.py
import MySQLdb
def book_list(request):
    db = MySQLdb.connect(user="me", db="mydb", password="secret", host="localhost")
    cursor = db.cursor()
    cursor.execute('SELECT name FORM books ORDER BY name')
    names = [row[0] for row in cursor.fetchall()]
    db.close()

配置 Django Model

具体的一些细节知识下面会进行叙述。这里只是展现一下如何配置。mysql

# {BASE_DIR}/apps/message/models.py

# 从 Django 中引入 models
from django.db import models


# Create your models here.
class UserMessage(models.Model):
    name = models.CharField(max_length=20, verbose_name=u"用户名")
    email = models.EmailField(verbose_name=u"邮箱")
    address = models.CharField(max_length=100, verbose_name=u"联系地址")
    message = models.CharField(max_length=500, verbose_name=u"留言信息")

    class Meta:
        verbose_name = u"用户留言信息"
        verbose_name_plural = verbose_name

model 建立完成,接下来是生成数据表。git

生成数据表

$ python manage.py makemigrations message
$ python manage.py migrate message

而后查看数据库是否是生成了表。github

以前有十个表,分别是:ajax

+----------------------------+
| Tables_in_test_django      |
+----------------------------+
| auth_group                 |
| auth_group_permissions     |
| auth_permission            |
| auth_user                  |
| auth_user_groups           |
| auth_user_user_permissions |
| django_admin_log           |
| django_content_type        |
| django_migrations          |
| django_session             |
+----------------------------+
10 rows in set (0.00 sec)

如今:sql

+----------------------------+
| Tables_in_test_django      |
+----------------------------+
| auth_group                 |
| auth_group_permissions     |
| auth_permission            |
| auth_user                  |
| auth_user_groups           |
| auth_user_user_permissions |
| django_admin_log           |
| django_content_type        |
| django_migrations          |
| django_session             |
| message_usermessage        |
+----------------------------+
11 rows in set (0.00 sec)
mysql> desc message_usermessage;
+---------+--------------+------+-----+---------+----------------+
| Field   | Type         | Null | Key | Default | Extra          |
+---------+--------------+------+-----+---------+----------------+
| id      | int(11)      | NO   | PRI | NULL    | auto_increment |
| name    | varchar(20)  | NO   |     | NULL    |                |
| email   | varchar(254) | NO   |     | NULL    |                |
| address | varchar(100) | NO   |     | NULL    |                |
| message | varchar(500) | NO   |     | NULL    |                |
+---------+--------------+------+-----+---------+----------------+
5 rows in set (0.04 sec)

对应上面 Model 中的字段,完美~shell

注意事项

  1. ChartField 必须指定 max_length。

ORM 功能介绍

稍候会有完整的 Model 例子。数据库

字段 Field

每个模型均可以包含有任意数量的字段,每一个字段都会对应数据表中的一个字段,咱们须要指定字段的属性。

name = models.CharField(max_length=20, verbose_name=u"用户名")

上述字段的名称是 name,类型是 models.CharField。对应到 MySQL 数据中是 varchar 类型。varchar 类型的字段都是须要去指定一个长度值,对应到 Django 的 ORM 模型上就是 max_length 属性。

字段参数

下面列举一下目前笔者在开发中用到的一些字段:

  1. max_length:指定字段的长度值,接受一个数字,CharField 必须指定最大长度, TextField 不须要。
  2. verbose_name:字段标签的可读名称,接受一个字符串。若是不指定,Django 会从字段名称去推断默认的详细名称,建议每个字段都进行指定。
  3. default:字段默认值。
  4. null:是否能够为 null,接受 True 或者 False
  5. blank: 是否能够为空,一样接受 True 或者 False
  6. primary_key:若是设置为 Ture,则该字段置为模型主键,若是模型中没有指定主键,则 Django 会自动为模型添加一个主键,默认为 id
  7. help_text:为 HTML 表单文本提供单文本标签。
  8. choices:一组字段选项,提供这一项的时候,默认对应的表单不见是选择字段的盒子,而不是标准文本字段。

字段类型

  1. CharField:用来定义短到中等长度的字段字符串,必须指定 max_length 属性
  2. TextField:用于大型的任意长度字符串,不强制要求指定 max_length 属性,指定的 max_length 仅仅当该字段以表单显示才会使用,不会再数据库级别进行强制执行。
  3. IntegerField:用于存储整形数据,在用于表单中验证输入的值须要时整数。
  4. FloatField:用于存储浮点型数据
  5. DateField 和 DateTimeField:用于存储/表示日期和日期/时间信息(分别是Python.datetime.date和datetime.datetime对象。这些字段能够另外代表(互斥)参数auto_now=Ture (在每次保存模型时将该字段设置为当前日期),auto_now_add(仅设置模型首次建立时的日期)和default(设置默认日期,能够被用户覆盖)。通常笔者选择的默认日期是 datetime.now
  6. EmailField:用来存储和验证电子邮件地址。
  7. FileField:用于上传文件,须要提供 upload_to 指定上传到的地方。
  8. ImageField:和上传文件表现基本类似,会额外进行是否为图像的验证。
  9. AutoField:是一种 IntegerField 自增的特殊类型,若是模型没有指定主键的话,此类型的主键将自动添加到模型中。
  10. ForeignKey:外键,用于指定与另外一个数据库模型的一对多关系。关系 “一” 侧是包含密钥的模型。和 flask 指定外键的方式不一样。
  11. ManyToManyField:用于指定多对多关系,例如,一本书能够有几种类型,每种类型能够包含几本书)。在咱们的图书馆应用程序中,咱们将很是相似地使用它们ForeignKeys,可是能够用更复杂的方式来描述组之间的关系。这些具备参数on_delete来定义关联记录被删除时会发生什么(例如,值models.SET_NULL将简单地设置为值NULL)。笔者用的不是不少。

元数据

经过声明 class Meta 来声明模型级别的元数据

class UserMessage(models.Model):
    # Config Field
        
    class Meta:
        ordering = ["id"]
       verbose_name = u"用户留言信息"
       verbose_name_plural = verbose_name

这里最有用的功能是能够指定模型返回数据时候的默认的顺序,更多的文档能够查看这里

方法

一个模型也能够有方法,最基本的使用就是定义一个标准的 Python 类方法: __str__

class UserMessage(models.Model):
    # Config Field
    
    # Config Meta
    
    def __str__(self):
       return self.message

这样为每一个对象返回一我的类可读的字符串。固然还有其余高级的使用,往后再说

完整的 model

# {BASE_DIR/apps/message/models.py}

from django.db import models


# Create your models here.
class UserMessage(models.Model):
    name = models.CharField(max_length=20, verbose_name=u"用户名")
    email = models.EmailField(verbose_name=u"邮箱")
    address = models.CharField(max_length=100, verbose_name=u"联系地址")
    message = models.CharField(max_length=500, verbose_name=u"留言信息")

    class Meta:
        ordering = ["id"]
        verbose_name = u"用户留言信息"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.message

使用 Django ORM

以前已经定义好了数据模型的字段(Field)、元数据(Meta)、方法(Method)等。如今要作的是把页面上提交过来的数据经过 ORM 来存放到数据库中,经过 ORM 来进行数据的 CURD 操做。

建立数据

templates 中已经建立了 message_form.html 模板文件,如今进行修改,修改 formaction 目标地址:

<form action="/" method="post" class="smart-green">

这里根据本身配置的 Url 来自行决定,因为笔者配置的是 /,因此这里就配置成这个样子。

这里指定的是使用 form 的原生事件 post 事件进行提交,可是在实际的开发中,为了实现更精确的控制,咱们经常不会使用原生事件,而更倾向于使用 ajax 进行提交,固然这里的重点不是前端的逻辑,重点在于 Django 后端逻辑的处理,顾不赘述。

接下来的任务就是:拿到 POST 发来的数据,而后存入数据库中。

存储数据

以前使用 Django 的 ORM 进行了数据库中数据表的配置,如今使用 Django 的 ORM 将数据保存到数据库中。

在 Django 中,咱们使用不是传统的 MVC 架构,咱们使用的是一种叫 MVT 的方式。不一样的 Template(模板) 呈现不一样的 View。咱们将在 View(请求视层)中获取用户提交的数据,以及将从 Model(数据层) 中得到的数据传递给 Template(模板层)

MVT 的概念自己就来自于 Django 框架,下面进行代码的展现:

# {BASE_DIR/apps/message/views.py}
from django.shortcuts import render  # 引入 render 方法
from .models import UserMessage      # 引入以前配置好的 Model


# Create your views here.

def get_form(request):
    if request.method == 'POST':
        name = request.POST.get('name', '')
        message = request.POST.get('name', '')
        address = request.POST.get('address', '')
        email = request.POST.get('email', '')
        user_message = UserMessage()
        user_message.name = name
        user_message.message = message
        user_message.address = address
        user_message.email = email
        user_message.save()
    return render(request, 'message_form.html')

经过 POST 方法提交的数据会存储到 request 对象的 POST 属性下边,经过 Django 提供的 get 方法就能够取到对应的字段。其中 get 接收两个参数,分别是字段的名称默认值

在取到 Template 提交过来的每个字段以后,就可使用 ORM 提供的方法将其存入数据库中。

实例化引入的 Model,而后将以前定义的字段进行赋值,而后就能够调用实例的 save() 方法将数据存入数据库。

而后就能够经过 Navicat 或者终端等方式查看数据是否保存到了数据库中。

读取数据

以前已经实现了数据的存储,这部分将实现数据的读取功能。

# {BASE_DIR/apps/message/views.py}
from django.shortcuts import render
from .models import UserMessage


# Create your views here.

def get_form(request):
    message = None
    all_message = UserMessage.objects.filter(name='test')
    if all_message:
        message = all_message[0]
    return render(request, 'message_form.html', {'my_message': message})

这里会涉及到 Django 的 QuerySets(查询集)相关知识,这里捡着用的着的部分看一下。

首先先声明 message,值为 None,用于存储取到的数据。

从本质上讲,QuerySets 是给定对象模型(这里是 UserModel)的对象列表(list),容许咱们从数据库中读取数据,选择以及排序。经过这种方式操做的话,就能够避免直接操做数据库。从而抹平不一样数据库操做的差别,这部分由 Django 帮咱们来完成。

上面的代码中有这样的一句:

UserMessage.objects.filter(name='test')

做用是从数据库中查找 name 值为 test 的全部条目,返回的是一个 <QuerySet> 列表,并赋值给 all_message。同时咱们也能够发现,QuerySet 能够链式调用。相似于 JavaScript 中的 Promise

而后若是 all_message 不为空的话,取出列表第一项,而后传递给 my_message 模板。

关于 QuerySet 的详细知识,能够查看 Django 的官方文档的这一部分

渲染到模板

在上面步骤中,咱们将符合预设条件的数据从数据库中取出来,传递到模板中,这里的目标是将数据正确的显示与渲染。部分语法相似于 ejs 模板的语法,但同时 Django 又在模板中内置了不少经常使用的函数。可是 Django 不像 Java 那样,容许在模板中写一些 Java 代码,Django 的 Template 中不容许将 Python 代码混进来。

因为模板代码过长,这里只放一些关键部分的代码,完整的代码能够查看文章对应的代码仓库。

<form action="{% url 'go_form' %}" method="post" class="smart-green">
    <label>
        <span>姓名 :</span>
        <input id="name" type="text" name="name" value="{% if my_message.name == 'test' %}test{% endif %}" class="error"
               placeholder="请输入您的姓名"/>
    </label>
    <label>
        <span>留言 :</span>
        <textarea id="message" name="message" placeholder="请输入你的建议">{{ my_message.message }}</textarea>
    </label>
    {% csrf_token %}
</form>

在上一篇文章中,提到过,path 接收 name 参数。在 template 中能够经过 name 来取到对应的 url,方法以下:

action="{% url 'go_form' %}"

这样作提供了另外一种获取 url 的方式,当咱们由于某种缘由去修改了 url 地址以后,经过 name 还能找到它。

textarea 中,有这样一段代码:

{{ my_message.message }}

做用是取到传入的 my_message 对象的 message 属性取出来并显示,因为 html 基本属于前端部分了,因此用前端的方式进行描述。

双花括号(八字胡)语法: {{...}} 在任何模板语言中都很常见,做用是将数据渲染到双括号内部。

上面还有一部分代码是这样子的:

{% if my_message.name == 'test' %}test{% endif %}"

意思很好懂的,是吧。

具体的 Django 中模板的语法能够查看官方文档。

后记

这里只是简单的介绍了一下 Django 中 Model 层、View 层、以及 Template 层之间交互的部分知识,很简略,不详细。在每部分的后边都附加了详细的官方文档地址。若是之后有时间了能够对每部分进行详细的阐述。

参考资料

  1. Python升级3.6 强力Django+杀手级Xadmin打造在线教育平台
  2. MDN 的 Django教程 ———— 设计LocalLibrary模型
  3. Django 官方文档 Model 部分
  4. Django Girls 教程
相关文章
相关标签/搜索