如何在没有任何JavaScript的情况下在Django中构建一个全栈反应式Web应用

298 阅读6分钟

Django中的全栈式反应型网站(无JavaScript)

需要复杂的用户交互的现代网站都是使用专用的前端框架来构建的,比如ReactVue.js以及其他一些框架。然而,一些复杂的问题也随之而来。这些包括时间、主机成本、SEO优化、语法差异,以及在某些情况下有重复的业务逻辑。

你可以用React等技术实现同样的反应式网站,而不用离开你的Django项目或学习其他语言。因此,它的复杂性较低,代码密集度较低,开发时间较快。

目前有几种技术可以实现这些功能,如SockpuppetreactorUnicorn。然而,你可以在本教程中使用Unicorn,在我们的Django应用程序中实现互动性,而不需要任何自定义的JavaScript。

请注意,使用专用的前端可能会有好处;例如,有一个专门的团队负责编码一个软件的前端和后端可能会有帮助。

教程要求

要跟上本教程,读者需要。

  • 对Django网络框架有基本了解。
  • 对Docker有一定的了解。

项目设置和概述

下面是对你将要建立的应用程序的简单介绍。

Home Page

在这个应用中,你可以在不刷新页面的情况下添加和删除一本新书,同样的功能在单页应用(SPA)中也可以实现。

要开始,从django-reactiverepo中克隆下来的基础分支。

$ git clone https://github.com/Samuel-2626/django-reactive --branch base --single-branch
$ cd django-reactive

你将使用Docker来简化Django的设置和运行依赖。在项目根目录下,创建镜像并启动Docker容器。

$ docker-compose up -d --build

接下来,应用迁移,创建一个超级用户并运行开发服务器。

$ docker-compose exec web python manage.py migrate
$ docker-compose exec web python manage.py createsuperuser
$ docker-compose exec web python manage.py run server

请注意book/models.py中的Book 模型。

from django.db import models
class Book(models.Model):
    title = models.CharField(max_length=200)
    def __str__(self):
        return self.title

与Unicorn一起工作

Unicorn是一个组件框架,它逐步增强了标准的Django视图。它在后台通过AJAX调用动态地更新DOM。

把它添加到你安装的应用程序中。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # Third-party
    "django_unicorn", # new
]

像这样更新你的项目urls.py 文件。

from django.urls import path, include
path("unicorn/", include("django_unicorn.urls")), # new

它是如何工作的?

  1. Unicorn是一个开源库,可以逐步增强标准的Django视图;因此,该组件的初始渲染速度很快,对SEO非常有利。
  2. 接下来,Unicorn与规定的元素绑定,并在需要时自动执行AJAX调用。
  3. 最后,DOM由Unicorn动态更新。

项目URL、视图和模板

在这一节中,你将设置你的项目URLs、视图和模板。

像这样更新你的项目urls.py 文件。

path("", views.index), # new

像这样更新你的书籍的应用程序views.py 文件。

def index(request):
    return render(request, "index.html", {})

像这样更新你的书籍的模板index.html 文件。

{% load unicorn %}

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Django Books</title>

    <link
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
      rel="stylesheet"
      integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
      crossorigin="anonymous"
    />
    {% unicorn_scripts %}
  </head>
  <body>
    {% csrf_token %}
    <div class="container">
      <h2>Favourite Django Books</h2>

      {% unicorn 'book' %}
    </div>
  </body>
</html>

解释逻辑

  1. 你为你的项目创建了一个基本的Django模板,同时将视图和URL链接在一起。
  2. 请注意,你必须在Django HTML模板的顶部加载unicorn
  3. 你还将unicorn_scripts 加入到Django HTML模板中,并在模板中也加入了crsf_token

根据Unicorn的说法,该库遵循Django的最佳实践,因此,它要求在任何作为组件的页面上设置一个CRSF token。这就保证了不能做任何邪恶的AJAX帖子。

此外,根据Unicorn的说法,它有一个组件的概念,指的是一套可以放在模板里面的互动功能。因此,例如,在index.html 文件中,你添加了一个book 组件。

此外,一个组件由以下内容组成。Django HTML模板,包括特定的标签。Python视图类,它给出了模板的后端逻辑。

添加和删除书籍

在本节中,你将使用Unicorn ,在不刷新浏览器的情况下实现添加和删除书籍的功能。

第1步

从你的项目根目录中,创建一个新的文件夹,称为unicorn ,创建一个新的文件夹,称为components ,最后,创建一个新的文件,称为book.py

第2步

从你先前创建的unicorn 文件夹中,创建另一个名为templates 的文件夹,在这个文件夹中创建一个名为unicorn 的新文件夹,最后,在这个文件夹中,创建一个名为book.html 的新文件。

第3步

book.html ,添加以下代码。

<div class="row">
  <div class="col-md-6">
    <section>
      <ul class="list-group">
        {% for book in books %}
        <li class="list-group-item">
          {{ book.title }}
          <button
            class="btn btn-outline-danger"
            style="float: right;"
            unicorn:click="delete_book('{{ book.id }}')"
          >
            Delete Book
          </button>
        </li>
        {% empty %}
        <p>Database Empty | Add your favourite Django book</p>
        {% endfor %}
      </ul>
    </section>
  </div>
  <div class="col-md-6">
    <form>
      <input
        type="text"
        class="form-control"
        placeholder="Enter title of the book..."
        unicorn:model.defer="title"
      />
      <br />
      <button
        class="btn btn-secondary"
        style="min-width: 100%;"
        unicorn:click.prevent="add_book"
      >
        Add Books
      </button>
    </form>
  </div>
</div>

这里发生了什么?

  1. 在该组件内,你可以使用正常的Django语法。
  2. 注意输入元素;除了Unicorn: model 属性外,这一点很熟悉。这将指定你的后端组件中的哪个字段将被绑定到这个输入。在这种情况下,字段名应该是title

unicorn: model 是将输入与后端组件联系起来的魔法。

  1. 注意Add Books 按钮有一个属性unicorn: click ,它告诉unicornadd_book 后台方法绑定到点击浏览器事件上。
  2. 同样地,Delete Book 按钮告诉unicorn 绑定delete_book 后台方法。你还把书id 传给了delete_book 函数,以唯一地识别每本书。

为了防止每次输入都发生更新,你可以在unicorn: model 的末尾添加一个lazy或defer修改器。

组件模板中使用的属性习惯上以unicorn: 开始,但也支持快捷键u: 。注意,组件的属性可以有很多类型,包括str,int,list,dictionary,decimal, 和Django Model

最后,Unicorn 需要一个根元素,它包涵了组件模板。

第4步

book.py 内,添加以下代码。

from django_unicorn.components import UnicornView
from books.models import Book
class BookView(UnicornView):
    title: str = ""
    books = Book.objects.none()
    def hydrate(self):
        self.books = Book.objects.all()
    def add_book(self):
        if self.title != "":
            book = Book(title=self.title)
            book.save()
        self.title = ""
    def delete_book(self, id):
        try:
            book = Book.objects.get(id=id)
            book.delete()
        except:
            pass

解释代码逻辑

  1. 你正在导入UnicornView ,它是TemplateView 的一个子类,在罩子下面。因此,从一个标准的基于类的视图切换的过程应该是很直接的。
  2. 当组件被实例化时,hydrate 方法被调用,以便从数据库中抓取最新的书籍,从而使信息是最新的。
  3. add_book 方法将从标题中创建一个新的图书模型,将其保存在数据库中,然后清除标题。
  4. delete_book 方法将删除一个符合id的书。

完成后,导航到http://127.0.0.1:8080/,以确保该应用程序按预期工作。你应该看到下面的情况。

Home Page 2

尝试添加和删除一些你喜欢的Django书籍。

总结

本教程向你介绍了如何在没有任何JavaScript的情况下在Django中构建一个全栈反应式Web应用。你用unicorn 构建了一个简单的应用程序,可以在不刷新页面的情况下添加和删除一本书,因此是反应式