君不见长松卧壑困风霜,时来屹立扶明堂。这篇文章主要讲述#yyds干货盘点#菜谱系统小成阶段,Python Web 领域终于攻占一个小山头相关的知识,希望能为你提供帮助。
十、菜谱的添加与展示本篇博客将进行菜谱系统的核心模块开发,菜谱的添加与展示。
10.1 添加菜谱在 Django 中对于一个功能的实现,添加一定是必备的,没有数据就没有办法进行后续操作了。
实现该功能的第一步依旧是在模板文件夹中添加 html 页面。本页面对于口味,工艺需要调用 API 数据进行渲染,本阶段不做调整。
% extends "menuapp/frame.html" % % block title % 菜谱系统 ---- 添加菜谱 %
endblock % % block content %
<
div class="container">
<
h2 class="form-signup-heading">
添加菜谱<
/h2>
<
div class="well">
<
/div>
<
form class="form-horizontal" role="form" method="post">
% csrf_token %
<
div class="form-group">
<
label for="name" class="col-sm-2 control-label">
名称:<
/label>
<
div class="col-sm-6">
<
input
type="text"
class="form-control"
id="name"
name="name"
placeholder="请输入菜谱名称"
/>
<
/div>
<
/div>
<
div class="form-group">
<
label for="technology_sel" class="col-sm-2 control-label">
工艺:<
/label>
<
div class="col-sm-6">
<
select name="technology" class="form-control" id="technology_sel">
<
option>
炒<
/option>
<
option>
煮<
/option>
<
option>
烤<
/option>
<
option>
蒸<
/option>
<
/select>
<
/div>
<
/div>
<
div class="form-group">
<
label for="flavor_sel" class="col-sm-2 control-label">
口味:<
/label>
<
div class="col-sm-6">
<
select name="flavor" class="form-control" id="flavor_sel">
<
option>
家常<
/option>
<
option>
香辣<
/option>
<
option>
怪味<
/option>
<
option>
黑椒<
/option>
<
/select>
<
/div>
<
/div>
<
div class="form-group">
<
label for="difficulty" class="col-sm-2 control-label">
难度:<
/label>
<
div class="col-sm-6">
<
select name="difficulty" class="form-control" id="difficulty">
<
option value="https://www.songbingjia.com/android/1">
初级<
/option>
<
option value="https://www.songbingjia.com/android/2">
中级<
/option>
<
option value="https://www.songbingjia.com/android/3">
高级<
/option>
<
/select>
<
/div>
<
/div>
<
div class="form-group">
<
label for="production_time_sel" class="col-sm-2 control-label"
>
时间:<
/label
>
<
div class="col-sm-6">
<
select
name="production_time"
class="form-control"
id="production_time_sel"
>
<
option value="https://www.songbingjia.com/android/5">
5分钟<
/option>
<
option value="https://www.songbingjia.com/android/10">
10分钟<
/option>
<
option value="https://www.songbingjia.com/android/15">
15分钟<
/option>
<
option value="https://www.songbingjia.com/android/30">
30分钟<
/option>
<
/select>
<
/div>
<
/div>
<
div class="form-group">
<
div class="col-sm-offset-2 col-sm-6">
<
button type="submit" class="btn btn-lg btn-primary btn-block">
确定添加
<
/button>
<
/div>
<
/div>
<
/form>
<
/div>
% endblock %
add.html 添加完毕,接下来在对
views.py
文件进行补充,完善该页面的调用。# 菜谱添加
@user_passes_test(lambda u: u.is_staff)
def add_menu(request):
user = request.user
state = None
# 当用户点击确认添加按钮时候的操作
if request.method == "POST":
n_menu = Menu(
name=request.POST.get("name", ""),
technology=request.POST.get("technology", ""),
flavor=request.POST.get("flavor", ""),
difficulty=request.POST.get("difficulty", ""),
production_time=request.POST.get("production_time", "")
)
n_menu.save()
state = "success"context =
"active_menu": add_menu,
"user": user,
"state": statereturn render(request, "menuapp/add_menu.html", context)
注意该函数上部存在一个装饰器,主要用于判断当前登录的用户是否是超级管理员,否则没有权限操作。使用该装饰器,需要在头部导入相关函数。
from .models import Menu
from django.contrib.auth.decorators import user_passes_test
此时,访问
http://127.0.0.1:8000/add
页面,URL 会自动跳转到 http://127.0.0.1:8000/login/?next=/add/
页面,注意这里遇到了之前埋下的雷,也就是旧 BUG,我们在编制路由的之后,没有考虑带参数的场景,所以接下来修改 urls.py
代码如下,修改的内容差异你可以自行比对。from django.urls import path
from . import viewsurlpatterns = [
path("", views.index, name="default"),
path("register/", views.register, name="register"),
path("login/", views.login, name="login"),
path("logout/", views.logout, name="logout"),
path("add/", views.add_menu, name="add_menu")
]
此时编译代码,得到如下界面,表示本步骤已经操作完成。
文章图片
写到这里需要对
login
函数进行一下完善,因为该视图可能处理两种情况,第一种登录之后跳转首页,第二种是登录之后跳转到登录前的页面。修改代码部分如下:if user is not None:
auth.login(request, user)
# 获取 next 指向的地址,如果存在就跳转到 next 指向的地址
target_url = request.GET.get("next", reverse("default"))return HttpResponseRedirect(target_url)
接下来实现注册用户的同时,添加管理员权限,该权限字段由
is_staff
来控制。修改 register.html
页面,修改的代码部分如下所示:<
div class="form-group">
<
label for="master" class="col-sm-2 control-label">
权限:<
/label>
<
div class="col-sm-6">
<
div class="checkbox">
<
label>
<
input type="checkbox" name="is_staff" id="master" />
管理员
<
/label>
<
/div>
<
/div>
<
/div>
继续修改
views.py
文件,重点在函数头部编写了一个复选框数据转换字典,然后通过前台传递到视图的数据进行转换:def register(request):
CHECKBOX_MAPPING = on: True, off: False,
if request.user.is_authenticated:
return HttpResponseRedirect(reverse("default"))# 用户注册状态信息
state = None
# 当用户提交注册信息
if request.method == "POST":
username = request.POST.get("username", "")
password = request.POST.get("password", "")
email = request.POST.get("email", "")
is_staff = CHECKBOX_MAPPING[request.POST.get("is_staff", "off")]# 判断用户名是否存在
if User.objects.filter(username=username):
state = "user_exist"else:
n_user = User.objects.create_user(username=username, password=password, email=email, is_staff=is_staff)
# 保存注册信息到数据库
n_user.save()
state = "success"# 表示注册成功context =
"active_menu": default,
"user": None,
"state": statereturn render(request, "menuapp/register.html", context)
当上述代码运行成功之后,再通过
register.html
页面注册的同时,可以勾选管理员身份,注册到数据库中的数据如下。文章图片
截止到现在,如果你整体步骤都梳理清楚之后,就已经实现登录之后才可以访问添加菜谱页面的 Web 应用了。
备注,如果非管理员访问
add/
会自动跳转回首页。10.2 菜谱列表优先实现一个最简单的列表页面,在读取菜谱数据的时候,为防止出现一次性读取大量数据,所以需要使用投影方法,读取部分数据字段。
views.py
新增 menu_list
函数,该函数要求用户登录状态下才可以访问,在文件开头注意导入对应的函数。from django.contrib.auth.decorators import user_passes_test, login_required
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage# 分页组件@login_required
def menu_list(request):
user = request.usermenus = Menu.objects.all()# 数据分页
paginator = Paginator(menus, 10)
page = request.GET.get("page")
# 分页异常处理
try:
menus = paginator.page(page)
except PageNotAnInteger:
menus = paginator.page(1)
except EmptyPage:
menus = paginator.page(paginator.num_pages)context =
"user": user,
"active_menu": "view_menu",
"menu_list": menusreturn render(request, "menuapp/list.html", context)
本函数实现了基本的分页功能,但是对菜谱的分类功能,还未实现,后文继续对其进行补充说明。实现了
menu_list
函数之后,立刻对 urls.py
文件进行修改。urlpatterns = [
path("", views.index, name="default"),
path("register/", views.register, name="register"),
path("login/", views.login, name="login"),
path("logout/", views.logout, name="logout"),
path("add/", views.add_menu, name="add_menu"),
path("list/", views.menu_list, name="menu_list")
]
准备工作已经完成,在
templates/menuapp
中新增文件 list.html
,添加如下代码,该代码中使用了部分模板语言。% extends "menuapp/frame.html" % % block title % 菜谱系统 ---- 列表页面 %
endblock % % block content %
<
div class="container">
<
div class="row">
<
div class="col-md-10 col-md-offset-1">
<
div class="col-md-2">
<
div class="list-group">
<
a rel="nofollow" href="https://www.songbingjia.com/android/% url menu_list%">
全部菜谱<
/a>
<
!--后期处理成菜谱分类-->
<
/div>
<
/div>
<
div class="col-md-9 col-md-offset-1">
<
table class="table table-hover">
<
thead>
<
tr>
<
th>
#<
/th>
<
th>
菜谱名称<
/th>
<
th>
工艺<
/th>
<
th>
口味<
/th>
<
th>
难度<
/th>
<
th>
时间<
/th>
<
/tr>
<
/thead>
<
tbody>
% for menu in menu_list %
<
tr>
<
td>
forloop.counter<
/td>
<
td>
menu.name <
/td>
<
td>
menu.technology <
/td>
<
td>
menu.flavor <
/td>
<
td>
menu.difficulty <
/td>
<
td>
menu.production_time <
/td>
<
/tr>
% endfor %
<
/tbody>
<
/table>
<
nav>
<
ul class="pager">
% if menu_list.has_previous %
<
li class="previous">
<
a
href="https://www.songbingjia.com/android/% url menu_list %?page= menu_list.previous_page_number"
>
上一页<
/a
>
<
/li>
% else %
<
li class="previous disabled">
<
a rel="nofollow" href="https://www.songbingjia.com/android/#">
上一页<
/a>
<
/li>
% endif % 第menu_list.number/
menu_list.paginator.num_pages页 % if menu_list.has_next %
<
li class="next">
<
a
href="https://www.songbingjia.com/android/% url menu_list %?page= menu_list.next_page_number"
>
下一页<
/a
>
<
/li>
% else %
<
li class="next disabled">
<
a rel="nofollow" href="https://www.songbingjia.com/android/#">
下一页<
/a>
<
/li>
% endif %
<
/ul>
<
/nav>
<
/div>
<
/div>
<
/div>
<
/div>
% endblock %
最终实现初稿效果如下,一个包含分页的菜谱系统列表页面已经完成。
文章图片
10.3 本篇博客小节【#yyds干货盘点#菜谱系统小成阶段,Python Web 领域终于攻占一个小山头】本篇博客对菜谱系统的菜谱添加、列表以及分页功能,一个微型的菜谱管理系统已经初具模型,后续都是对其进行完善与修改,希望你能在本篇博客学到知识,感谢。
推荐阅读
- 手把手教你使用Python打造一款摸鱼倒计界面
- Python如何判断和寻找完美数
- nginx四层代理
- 单链表(java)——简单实现
- 拿什么守护你-PHP程序级守护进程的实现与优化
- web服务之源码编译安装LNMP
- Modbus协议详解#yyds干货盘点#
- SpringBoot配置文件——加载顺序
- #yyds干货盘点# 盘点两种使用Python读取.nc文件的方法