全栈“食”代:用 Django + Nuxt 实现美食分享网站(上)
Django 作为 Python 社区最受欢迎的 Web 框架之一,凭借其高度抽象的组件和强大方便的脚手架,将快速且流畅的开发体验演绎到了极致。而 Nuxt 作为从 Vue.js 进化而来的前端框架,能够轻松胜任复杂的 SPA(单页应用)开发。两者相遇,能够擦出怎样的火花?这篇教程将用 Django + Nuxt 实现带有完整的增删改查(CRUD)功能的全栈应用。最后郑重警告:不要在深夜阅读此教程!!!
本文所涉及的源代码都放在了 Github 上,如果您觉得我们写得还不错,希望您能给❤️这篇文章点赞+Github仓库加星❤️哦~ 本文代码改编自 Scotch。
项目初始化
在这一系列教程中,我们将会实现一个全栈美食分享网站,后端用 Django 实现,前端则是 Nuxt 框架,下面是最终完成后的项目效果:
预备知识
本教程假定你已经知道了
- 基本的 Python 3 语言知识,包括使用 pip 安装包
- Django 框架的基础概念(MTV 架构),可参考这篇教程进行学习
- Vue 的基础概念,以及用 npm 工具链的使用,可参考这篇教程
- 前后端分离的基本概念,包括前端如何通过发起 HTTP(S) 请求从后端获取数据
学习目标
学完这篇教程后,你将:
- 了解用 pipenv 工具管理 Python 依赖
- 学会用 Django REST Framework 快速开发 REST API
- 学会用 Nuxt 框架快速开发 SPA(单页应用),能够从后端获取数据并渲染
用 pipenv 初始化 Python 环境
首先创建项目目录,并进入:
$ mkdir recipes_app && cd recipes_app
在这个项目中,我们用 pipenv 来管理 Python 项目的环境依赖。Pipenv 是 Python 社区偶像级大师 Kenneth Reitz 牵头开发的开发流程优化工具,立志集所有项目管理工具(Node 的 npm、Ruby 的 bundler、PHP 的 composer 等等)的优势为一体。我们通过下面的命令安装 pipenv,并创建项目的依赖环境:
$ pip install pipenv
$ pipenv shell
如果看到命令提示符前面出现 (recipes_app-nV3wuGJ1)
的提示(后面那串随机字符串可能不一样),就表明我们已经成功地创建了项目独有的虚拟环境!我们接着安装 Django “三件套”:
- Django: Django 框架本身,提供了丰富且强大的服务器开发组件;
- DRF (Django Rest Framework):Django 框架的超级搭档,大大方便了 REST API 的开发;
- Django CORS Headers:用于实现跨域资源请求(CORS)的 Django 中间件(如果你不了解 CORS,可以参考阮一峰的日志)。
安装命令如下:
(recipes_app-nV3wuGJ1) $ pipenv install django django-rest-framework django-cors-headers
这时 pipenv 便产生了 Pipfile 文件,它的作用就类似 Node 项目中的 package.json 文件:
[[source]]
url = "https://mirrors.aliyun.com/pypi/simple/"
verify_ssl = true
name = "pypi"[packages]
django = "*"
django-rest-framework = "*"
django-cors-headers = "*"[dev-packages][requires]
python_version = "3.6"
然后用 Django 脚手架创建服务器项目 api
的基本结构,并进入到 api
创建一个子应用 core
:
(recipes_app-nV3wuGJ1) $ django-admin startproject api
(recipes_app-nV3wuGJ1) $ cd api
(recipes_app-nV3wuGJ1) $ python manage.py startapp core
接着进行数据库迁移,并创建用于登录后台管理的超级用户:
(recipes_app-nV3wuGJ1) $ python manage.py migrate
(recipes_app-nV3wuGJ1) $ python manage.py createsuperuser
按照问题输入信息即可。要记住用户名和密码哦!然后运行开发服务器:
(recipes_app-nV3wuGJ1) $ python manage.py runserver
访问 http://localhost:8000/admin,可以看到后台管理的登录页面。输入刚才创建的超级用户的用户名和密码,就进入了后台管理系统,如下所示:
熟悉的界面,但是——没什么东西,而且全是英文!别担心,后面我们会一个个搞定。
用 Django 实现 REST API
接下来我们将实现本项目所需要用的所有 API。对,你没有听错,我们会在这一步实现所有后端接口,大概只 10 分钟左右可以敲完!这就是 Django 的宣言:
The web framework for perfectionists with deadlines.
“为赶时间的完美主义者而生!”
全局配置
首先,在全局配置文件 settings.py 中做如下改动:
- 在
INSTALLED_APPS
中添加rest_framework
、corsheaders
和core
,前两个分别是 Django Rest Framework 和 Django CORS Headers 的应用,最后一个是我们网站的应用; - 在
MIDDLEWARE
中添加corsheaders.middleware.CorsMiddleware
,注册跨域请求中间件(注意一定要放在最前面!); - 设置
CORS_ORIGIN_WHITELIST
,添加跨域请求白名单,这里我们先写上http://localhost:3000
,后面开发前端时将用到; - 设置
LANGUAGE_CODE
为zh-hans
,可以将后台管理设置为中文,非常方便; - 设置
MEDIA_URL
和MEDIA_ROOT
,用于在开发中提供图片资源文件的访问。
具体代码如下:
# ...INSTALLED_APPS = [# 默认的 App ...'rest_framework','corsheaders','core',
]MIDDLEWARE = ['corsheaders.middleware.CorsMiddleware',# 默认的中间件 ...
]CORS_ORIGIN_WHITELIST = ('http://localhost:3000',
)# ...LANGUAGE_CODE = 'zh-hans'MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
实现 core 应用
接下来就是实现 core
这个 Django 应用。实现一个 Django 应用大致都是按照这样的流程:
- 定义数据模型(models.py),用于实现和数据库之间的绑定;
- 定义后台管理配置(admin.py),用于在后台管理系统中进行操作;
- 定义序列化器(serializers.py),仅当实现 REST API 时需要,用于提供数据模型的 JSON 序列化(或其他数据交换格式);
- 定义视图(views.py),用于实现具体的业务逻辑;
- 定义路由(urls.py),用于定义路由规则,将其映射到相应的视图;
- 将应用路由接入全局路由文件(api/urls.py)中。
我们从第一步开始,完成菜谱 Recipe
数据模型如下:
from django.db import modelsclass Recipe(models.Model):DIFFICULTY_LEVELS = (('Easy', '容易'),('Medium', '中等'),('Hard', '困难'),)name = models.CharField(max_length=120, verbose_name='名称')ingredients = models.CharField(max_length=400, verbose_name='食材')picture = models.FileField(verbose_name='图片')difficulty = models.CharField(choices=DIFFICULTY_LEVELS, max_length=10,verbose_name='制作难度')prep_time = models.PositiveIntegerField(verbose_name='准备时间')prep_guide = models.TextField(verbose_name='制作指南')class Meta:verbose_name = '食谱'verbose_name_plural = '食谱'def __str__(self):return '{} 的食谱'.format(self.name)
其中,class Meta
定义了 Recipe
的元数据;__str__
方法定义了一个菜谱对象转换为字符串时应该怎样显示。这些设置的作用在打开后台管理系统之后就会很清晰了。想要了解更多关于 Django 数据模型的知识,请参考相关中文文档。
第二步,为 core
子应用配置相应的后台管理功能。非常简单,只需注册定义好的 Recipe
模型:
from django.contrib import admin
from .models import Recipe# Register your models here.
admin.site.register(Recipe)
第三步,定义序列化器 serializers.py(脚手架并不会自动创建,需要手动创建)。序列化器是 Django Rest Framework 提供的功能,能够非常方便地将 Django 数据模型序列化成相应的 JSON 数据格式。在这里,我们定义一个 RecipeSerializer
,并在 class Meta
中指定对应的数据模型为刚才创建的 Recipe
,并选择相应的字段展示:
from rest_framework import serializers
from .models import Recipeclass RecipeSerializer(serializers.ModelSerializer):class Meta:model = Recipefields = ('id', 'name', 'ingredients', 'picture','difficulty', 'prep_time', 'prep_guide')
第四步,实现视图。这里我们采用开挂模式,直接调用 Django Rest Framework 提供的模型视图集(ModelViewset
)直接搞定数据模型的增删改查逻辑:
from rest_framework import viewsets
from .serializers import RecipeSerializer
from .models import Recipeclass RecipeViewSet(viewsets.ModelViewSet):serializer_class = RecipeSerializerqueryset = Recipe.objects.all()
只需指定 serializer_class
(序列器类)和 queryset
(模型查询集),就自动定义好了模型的添加、删除、查询和修改!虽然视图集非常强大,但是如果要实现更加灵活的业务逻辑,那么还是要为每个接口定义单独的视图类才行。
第五步,实现路由。由于我们上一步使用了视图集,因此只需先调用 DefaultRouter
自动生成相关的路由,然后加入记录路由映射的列表 urlpatterns
中:
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import RecipeViewSetrouter = DefaultRouter()
router.register(r'recipes', RecipeViewSet)urlpatterns = [path('', include(router.urls)),
]
router
为我们自动生成以下路由:
/recipes/
:创建食谱(POST 方法)或读取食谱列表(GET方法);/recipes/{id}
:获取单个食谱(GET)、更新单个食谱(PUT)或删除食谱(DELETE)。
注意
在 Django 路由定义中不包括 HTTP 方法,具体的 HTTP 方法可以在视图中读取并判断。
最后一步,我们将 core
子应用中的路由接入全局路由:
from django.contrib import admin
from django.urls import path, includeurlpatterns = [path('admin/', admin.site.urls),path('api/', include('core.urls')),
]
没错,关于食谱的增删改查的 API 我们全都实现了!不信?先运行开发服务器:
(recipes_app-nV3wuGJ1) $ python manage.py runserver
由于 Django REST Framework 为我们提供了测试 API 的 Web 界面,因此这里就不用 Postman 等工具进行测试了。用浏览器访问 localhost:8000/api/recipes,就进入了如下所示的 API 测试页面:
这个页面的下方还有添加数据(发起 POST 请求)的表单,我们填一些数据,然后点击 POST 按钮:
然后再次访问食谱列表页面,就有我们刚刚添加的食谱了!此外,你还可以尝试访问单个食谱的详情页面(例如 localhost:8000/api/recipes/1),并且可以通过 Web 页面直接修改或删除哦!
用 Nuxt.js 实现网站首页
Django 的 MTV 架构固然优秀,但是随着现在的业务逻辑越来越多地向前端倾斜(也就是现在流行的富前端应用),其中的 T(Template)需要更强大的武器来解决,这里就是我们的第二位主角 Nuxt。
用脚手架初始化 Nuxt 项目
我们将把所有的前端代码放到 client 目录中,不过无需自己创建,我们调用 nuxt 的脚手架来创建前端应用:
$ npx create-nuxt-app client
之后脚手架应用会询问一系列问题,按下面的截图进行选择(当然作者名填自己):
我们对 Nuxt 脚手架生成的目录结构稍作讲解。可以看到 client 目录下有以下子目录:
- assets:存放图片、CSS、JS 等原始资源文件
- components:存放 Vue 组件
- layouts:存放应用布局文件,布局可在多个页面中使用
- middleware:存放应用的中间件。Nuxt 中的中间件指页面渲染前执行的自定义函数(本教程中不需要)
- pages:应用的视图和路由。Nuxt 会根据此目录中的
.vue
文件自动创建应用的路由 - plugins: 存放 JavaScript 插件,用于在应用启动前加载(本教程中不需要)
- static:存放通常不会改变的静态文件,并且将直接映射到路由(即可通过
/static/picture.png
访问) - store:存放 Vuex Store 文件(本教程中不需要)
本项目所用到的图片资源请访问我们的 GitHub 仓库,并下载到对应的目录中。
编写前端首页
我们在 client/pages 中创建 index.vue 文件,并在其中实现我们的前端首页:
<template><header><div class="text-box"><h1>吃货天堂
全栈“食”代:用 Django + Nuxt 实现美食分享网站(上)相关推荐
- 全栈“食”代:用 Django + Nuxt 实现美食分享网站(一)
Django 作为 Python 社区最受欢迎的 Web 框架之一,凭借其高度抽象的组件和强大方便的脚手架,将快速且流畅的开发体验演绎到了极致.而 Nuxt 作为从 Vue.js 进化而来的前端框架, ...
- 塔望3W消费战略全案|小靳师傅:地方美食如何乘上新速食时代快车
小靳师傅品牌全案服务 公司:上海中达食品有限公司 品牌:小靳师傅 行业:即食.自热.食品行业 服务:品牌全案服务 [项目背景] 中华的美食有着悠久的历史,与中国的文化息息相关.在历史的发展长河与生产生 ...
- python 全栈开发,Day84(django请求生命周期,FBV和CBV,ORM拾遗,Git)
一.django 请求生命周期 流程图: 1. 当用户在浏览器中输入url时,浏览器会生成请求头和请求体发给服务端 请求头和请求体中会包含浏览器的动作(action),这个动作通常为get或者post ...
- python 全栈开发,Day79(Django的用户认证组件,分页器)
一.Django的用户认证组件 用户认证 auth模块 在进行用户登陆验证的时候,如果是自己写代码,就必须要先查询数据库,看用户输入的用户名是否存在于数据库中: 如果用户存在于数据库中,然后再验证用户 ...
- Python全栈(十)Django框架之6.ORM模型基本使用
文章目录 一.ORM创建模型和映射数据库 1.创建模型 2.数据库映射 二.ORM模型数据操作 1.添加数据 2.查询数据 3.删除数据 4.更新数据 三.ORM实现图书管理系统 一.ORM创建模型和 ...
- Python全栈工程师学习笔记 | Django的模型层
Model模型 模型是你的数据的唯一的.权威的信息源.它包含你所储存数据的必要字段和行为. 通常,每个模型对应数据库中唯一的一张表. 每个模型都是django.db.models.Model的一个Py ...
- python datetime需要安装_Python全栈工程师学习笔记 | Django的模型层
Model模型 模型是你的数据的唯一的.权威的信息源.它包含你所储存数据的必要字段和行为. 通常,每个模型对应数据库中唯一的一张表. 每个模型都是django.db.models.Model的一个Py ...
- Python全栈(十)Django框架之9.聚合函数和表达式
文章目录 一.聚合函数 1.Avg函数 2.聚合函数实现链式调用 3.aggregate和annotate的区别 4.Count函数 5.Max和Min函数 6.Sum函数 二.F表达式和Q表达式 1 ...
- Python全栈(十)Django框架之10.ORM模型对象和QuerySet方法
文章目录 一.objects对象源码解读 二.QuerySet方法 1.exclude方法 2.order_by方法 3.values方法 4.values_list方法 5.create方法 6.g ...
最新文章
- Form表单提交前进行JS验证的3种方式
- C 函数 toascii
- Singing Everywhere
- php生成 sku_高并发下,php与redis实现的抢购、秒杀功能
- 跨平台加密版 SQLite 3 - wxSQLite3
- android 系统(162)---O版本的Camera Startup time比N版本时间长
- camera(22)---camera 客观测试 Imatest教程--色彩还原度测试
- 产品研发过程管理专题——软件测试过程管理实践
- SpringBoot--自动装配之Import注解以及源码分析
- Cobalt Strike神器使用教程
- 360安全卫士 免杀
- 使用python处理wps表格_Python处理Word文件的实用姿势
- wireshark密码嗅探侵入后台管理系统
- “函数...已有主体”问题解决
- 用计算机完成下表的视距测量计算公式,中南大学工程测量计算题库及参考答案...
- 手绘风格的白板Excalidraw
- 618年中大促 ,全场6折起!限量周边8件套!
- 国产ETL etl-engine 星光不问赶路人 时我不待
- 网站统计IP PV UV实现原理
- windows 命令行切换目录
热门文章