Django中的全栈式反应型网站(无JavaScript)
需要复杂的用户交互的现代网站都是使用专用的前端框架来构建的,比如React、Vue.js以及其他一些框架。然而,一些复杂的问题也随之而来。这些包括时间、主机成本、SEO优化、语法差异,以及在某些情况下有重复的业务逻辑。
你可以用React等技术实现同样的反应式网站,而不用离开你的Django项目或学习其他语言。因此,它的复杂性较低,代码密集度较低,开发时间较快。
目前有几种技术可以实现这些功能,如Sockpuppet、reactor和Unicorn。然而,你可以在本教程中使用Unicorn,在我们的Django应用程序中实现互动性,而不需要任何自定义的JavaScript。
请注意,使用专用的前端可能会有好处;例如,有一个专门的团队负责编码一个软件的前端和后端可能会有帮助。
教程要求
要跟上本教程,读者需要。
- 对Django网络框架有基本了解。
- 对Docker有一定的了解。
项目设置和概述
下面是对你将要建立的应用程序的简单介绍。

在这个应用中,你可以在不刷新页面的情况下添加和删除一本新书,同样的功能在单页应用(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
它是如何工作的?
- Unicorn是一个开源库,可以逐步增强标准的Django视图;因此,该组件的初始渲染速度很快,对SEO非常有利。
- 接下来,Unicorn与规定的元素绑定,并在需要时自动执行AJAX调用。
- 最后,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>
解释逻辑
- 你为你的项目创建了一个基本的Django模板,同时将视图和URL链接在一起。
- 请注意,你必须在Django HTML模板的顶部加载
unicorn。 - 你还将
unicorn_scripts加入到Django HTML模板中,并在模板中也加入了crsf_token。
根据Unicorn的说法,该库遵循Django的最佳实践,因此,它要求在任何作为组件的页面上设置一个
CRSFtoken。这就保证了不能做任何邪恶的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>
这里发生了什么?
- 在该组件内,你可以使用正常的Django语法。
- 注意输入元素;除了
Unicorn: model属性外,这一点很熟悉。这将指定你的后端组件中的哪个字段将被绑定到这个输入。在这种情况下,字段名应该是title。
unicorn: model是将输入与后端组件联系起来的魔法。
- 注意
Add Books按钮有一个属性unicorn: click,它告诉unicorn将add_book后台方法绑定到点击浏览器事件上。 - 同样地,
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
解释代码逻辑
- 你正在导入
UnicornView,它是TemplateView的一个子类,在罩子下面。因此,从一个标准的基于类的视图切换的过程应该是很直接的。 - 当组件被实例化时,
hydrate方法被调用,以便从数据库中抓取最新的书籍,从而使信息是最新的。 add_book方法将从标题中创建一个新的图书模型,将其保存在数据库中,然后清除标题。delete_book方法将删除一个符合id的书。
完成后,导航到http://127.0.0.1:8080/,以确保该应用程序按预期工作。你应该看到下面的情况。

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