写点什么

让我们一起开发【菜谱系统】吧,滚雪球学 Python 第三轮项目计划

发布于: 2 小时前

橡皮擦,一个逗趣的互联网高级网虫。新的系列,让我们一起进入 Django 世界。


六、Python Django 菜谱系统

从本篇博客开始,我们将正式进入 Django 项目化的课程中,从一个菜谱系统开始,逐步掌握 Django 开发网站的各种技术点。


第一个项目属于管理类内部系统,假设,用户量少,使用频率不高,功能不多,实现对菜谱的增删改查即可。


基本功能清单如下:


  1. 用户登录与注册

  2. 用户权限管理

  3. 菜谱的添加

  4. 菜谱的删除

  5. 菜谱的修改

  6. 分类展示菜谱

  7. 查询菜谱

6.1 菜谱系统相关设计

菜谱系统最核心的就是菜谱了,菜谱包含如下信息:名称、工艺、口味、烹饪时间、难度、主料、辅料,还有诱人图片。


用户权限设计两个身份即可,普通用户无需登录就可以查询数据,管理员可以进入菜谱有关管理页面对数据进行维护。


相关页面可以简单进行拆解:


  1. 用户的欢迎页面,网站首页

  2. 菜谱的列表页面

  3. 菜谱详情页面

  4. 用户登录与注册页面

  5. 菜谱添加与修改页面


有了上述数据,基本可以确定该系统包括两张核心表,一张为用户表,一张为菜谱表,所有的操作都将围绕以上两个表或者模型来实现。

6.2 Django 中的数据模型

在正式开始设计菜谱系统的表结构之前,需要先掌握 Django 的模型(Model)相关知识,作为 Web 框架而言,Django 也提供了完整的 ORM 框架,ORM 在之前的博客也简单说明过,叫做对象-关系映射框架。该框架可以将数据库中的关系映射到 Python 的类与对象中,一般情况下,每一个模型都映射着一张数据表,模型中的每一个属性都对应数据表中的一个字段,这个概念需要先理解清楚。

6.2.1 模型的数据字段(Field types)

截止到 橡皮擦 编写本文的时候,Django 中的基本数据字段类型 30 个左右,该数量不固定,具体你可以依据 Django 版本自行查询。https://docs.djangoproject.com/en/3.1/ref/models/fields/#field-types


为了便于学习,你可以对这些基本数据字段类型进行简单的分类。


数字类字段


  • AutoField:如果没有给模型指定一个主键,Django 会自动给模型添加一个 AutoField 类型的字段,该字段是一个自增的整数;

  • BitAutoField:与 AutoField 含义一致,就是数据范围更大一些,如果该表数据量大,使用它即可;

  • SmallAutoField:Django 3.0 新增,看名字就知道范围比 AutoField 小;

  • IntegerField:32 位整数,取值范围 -2147483648 to 2147483647

  • BigIntegerField:从 IntegerField 派生出来,64 位整数,取值范围 -9223372036854775808 to 9223372036854775807

  • SmallIntegerField:取值范围 -32768 to 32767

  • PositiveIntegerField:非负整数类型的字段,取值范围 0 to 2147483647

  • PositiveSmallIntegerField:非负,取值范围 0 to 32767

  • PositiveBigIntegerField:取值范围 0 to 9223372036854775807,这个要注意 Django 3.1 版本才有;

  • FloatField:浮点数类型字段;

  • DecimalField:十进制数类型字段,表示一个固定精度的十进制数,这个在用到的时候,详细说明。


字符类字段


  • CharField:字符串类型,需要携带一个必备属性 max_length,表示字符串长度;

  • EmailField:基于 CharField 但是多了邮箱格式验证;

  • URLField:同上,多了 URL 特殊处理;

  • SlugField:只包含字母、数字、下划线或连字符,通常用于 URL;

  • TextField:可存储大量文本的字段;

  • UUIDField:UUID 字段,对应的是 Python 中的 UUID 对象,有时候主键会使用 UUID 替代 AutoField

  • FilePathField:文件路径字段。


文件类字段


  • FileField:处理文件上传的字段,不能作为文件主键;

  • ImageField:图片字段,继承自 FileField


布尔类字段


  • BooleanField:只有 True 和 False 两个值的字段;

  • NullBooleanField:可空布尔字段。


日期时间字段


  • DateField:对应 Python 中的 datetime.date 实例;

  • DateTimeField:对应 Python 中的 datetime.datetime 实例;

  • TimeField:对应 Python 中的 datetime.time 实例;

  • DurationField:对应 Python 中的 timedelta 实例。


二进制字段


  • BinaryField:二进制字段,不建议使用。


其它的不常使用,先不涉及,具体有应用场景在进行说明。

6.2.2 模型关系

模型与模型之间存在三种关系,分别是 一对一一对多多对多


接下来先介绍基本使用方式,后文案例中进行深度学习。


多对一关系例如一个食谱包含多个食材,代码如下:


# 食材类class Ingredients(models.Model):    menu = models.ForeignKey("Menu", on_delete=models.CASCADE)
# 菜谱类class Menu(models.Model): pass
复制代码


需要注意的是多对一关系中,在多对象的那个类中增加外键关系,使用的方法是 models.ForeignKey(),该方法有两个参数,第一个是与之关联的模型名称,第二个是 on_delete 字段,关联的对象被删除时该对象的行为,例如 models.CASCADE 就表示级联删除,彻底掌握还是需要看实际应用场景。


多对多关系多对多关系属于比较复杂的模型关系了,在部分情况下,还需要 through_field 来定义中间模型。


# 菜谱类class Menu(models.Model):    name = models.CharField(max_length=20)
# 口味class Flavor(models.Model): name = models.CharField(max_length=10) contain = models.ManyToManyField( Menu, through='MenuContainFlavor', # 该参数为通过哪一个模型进行关联 through_fields=('flavor', 'menu'), # 关联字段名称,元组的第一个参数是当前模型名称 )
# 关联关系模型class MenuContainFlavor(models.Model): flavor = models.ForeignKey(Flavor, on_delete=models.CASCADE) menu = models.ForeignKey(Menu, on_delete=models.CASCADE)
复制代码


上面的案例中,MenuContainFlavor 就是中间模型,主要为了关联菜谱与口味。


一对一关系一对一关系基表简单,与外键字段类似,一对一返回的是一个对象。因为基本语法非常简单,可以简单理解是对一张数据表的数据扩充就可以了。

6.2.3 字段参数

了解了模型中的字段类型之后,要知道这些字段都是基于类的形式存在的,既然是类就会出现一些可选参数,具体内容如下:


  • null:数据库层面是否可以为空;

  • blank:业务层面是否可以为空,设置为 True,数据的输入框可为空;

  • choices:元组或列表格式,表示内容可选项;

  • db_column:指定该字段在数据表中的名称;

  • db_index:数据库索引配置,设置为 True 将会在这个字段上设置索引;

  • default:默认值;

  • editable:是否可编辑;

  • primary_key:该字段是否设置为主键;

  • unique:唯一索引;

  • verbose_name:可读性名称,或者叫做展示文字也可以;

  • validators:自定义逻辑验证。

6.3 菜谱系统模型设计

学习了基本知识点之后,就可以针对菜谱系统的模型进行相关设计了。


菜谱系统涉及的模型包括:菜谱主料辅料用户,先暂定这几个模型,后续如果有需要,再进行扩展。


每个模型涉及的字段分别如下:


菜谱


  • 名称

  • 工艺

  • 口味

  • 时间

  • 难度


主料


  • 名称

  • 数量


辅料


  • 名称

  • 数量


用户


  • 用户名

  • 邮箱

  • 密码

  • 是否管理员


数据字段暂定为上述内容,后续随着项目研发进行补充。

6.3.1 pycharm 创建 Django 项目

如果你使用的是专业版的 pycharm 是可以直接一键创建的,由于橡皮擦使用的版本是免费的社区办,故需要自己手动进行创建。操作步骤十分简单,只需要用 pycharm 打开一个文件夹,然后输入如下命令即可:


> django-admin startproject MenuSystem> cd MenuSystem> python manage.py startapp menuapp
复制代码


生成的目录结构如下图所示:


6.3.2 models.py 编写模型

下面的工作就是在 models.py 中对模型进行编写了,具体代码如下:


# 菜谱模型类class Menu(models.Model):    pass
# 主料类class Ingredients(models.Model): pass
# 辅料class SubMaterial(models.Model): pass
复制代码


三个模型类先占好位置,然后在进行拆解。详细内容编写如下:


from django.db import models
# Create your models here.# 菜谱模型类class Menu(models.Model): name = models.CharField(max_length=50, verbose_name="菜谱名称") technology = models.CharField(max_length=10, verbose_name="工艺") flavor = models.CharField(max_length=50, verbose_name="口味") production_time = models.IntegerField(default=0, verbose_name="制作时间") difficulty = models.SmallIntegerField(default=0, verbose_name="难度")
create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
# 定义类的 __str__ 方法,便于将模型对象当做参数输出时显示菜谱名称 def __str__(self): return self.name
# 主料类class Ingredients(models.Model): name = models.CharField(max_length=50, verbose_name="主料名称") quantity = models.IntegerField(default=0, verbose_name="数量") # 一个主料属于一个菜谱,一个菜谱包含多个主料 menu = models.ForeignKey(Menu, on_delete=models.CASCADE, verbose_name="所属菜谱")
def __str__(self): return self.name
# 辅料class SubMaterial(models.Model): name = models.CharField(max_length=50, verbose_name="辅料名称") quantity = models.IntegerField(default=0, verbose_name="数量") # 一个辅料属于一个菜谱,一个菜谱包含多个辅料 menu = models.ForeignKey(Menu, on_delete=models.CASCADE, verbose_name="所属菜谱")
def __str__(self): return self.name
复制代码


models.py 中没有实现用户模型,本项目使用 Django 自带的用户系统,后续为你说明。

6.4 本篇博客小节

本篇博客主要介绍的是 Django 中的数据模型,任何系统的设计都是从表结构开始的,牢牢掌握本篇博客的内容吧,一个很小的承上启下环节。


发布于: 2 小时前阅读数: 2
用户头像

爬虫 100 例作者,蓝桥签约作者,博客专家 2021.02.06 加入

6 年产品经理+教学经验,3 年互联网项目管理经验; 互联网资深爱好者; 沉迷各种技术无法自拔,导致年龄被困在 25 岁; CSDN 爬虫 100 例作者。 个人公众号“梦想橡皮擦”。

评论

发布
暂无评论
让我们一起开发【菜谱系统】吧,滚雪球学 Python 第三轮项目计划