如何创建 Django 模型

简介

在上一篇教程“如何创建 Django 应用程序并将其连接到数据库”中,我们介绍了如何创建一个 MySQL 数据库,如何创建和启动一个 Django 应用程序,以及如何将其连接到一个 MySQL 数据库。

在本教程中,我们将创建 Django 模型,定义我们将要存储的博客应用程序数据的字段和行为。这些模型将 Django 应用程序的数据映射到数据库。这是 Django 用来通过对象关系映射(ORM)API生成数据库表的方式,被称为“模型”。

先决条件

本教程是 Django 开发系列的一部分,是该系列的延续。

如果您没有跟随这个系列,我们做出以下假设:

  • 您已安装 Django 版本为 4 或更高版本。
  • 您已将 Django 应用程序连接到数据库。我们正在使用 MySQL,您可以通过跟随 Django 系列的第二部分“如何创建 Django 应用程序并将其连接到数据库”来实现这种连接。
  • 您正在使用基于 Unix 的操作系统,最好是 Ubuntu 22.04 云服务器,因为这是我们测试的系统。如果您想在类似的环境中设置 Django,请参考我们的教程“如何在 Ubuntu 22.04 上安装 Django 并设置开发环境”。

由于本教程主要涉及 Django 模型,即使您的设置有些不同,您也可以跟着做。

步骤 1 — 创建 Django 应用程序

为了与 Django 的模块化哲学保持一致,我们将在我们的项目中创建一个 Django 应用程序,其中包含创建博客网站所需的所有文件。

每当我们开始在 Python 和 Django 中工作时,我们应该激活我们的 Python 虚拟环境并进入我们的应用程序的根目录。如果您跟着这个系列,您可以通过输入以下内容来实现这一点。

cd ~/my_blog_app
. env/bin/activate
cd blog

然后,让我们运行以下命令:

python manage.py startapp blogsite

这将创建我们的应用程序以及一个 blogsite 目录。

在本教程系列的这一点上,您的项目将具有以下目录结构:

my_blog_app/
└── blog├── blog│   ├── __init__.py│   ├── __pycache__│   │   ├── __init__.cpython-38.pyc│   │   ├── settings.cpython-38.pyc│   │   ├── urls.cpython-38.pyc│   │   └── wsgi.cpython-38.pyc│   ├── asgi.py│   ├── settings.py│   ├── urls.py│   └── wsgi.py├── blogsite│   ├── __init__.py│   ├── admin.py│   ├── apps.py│   ├── migrations│   │   └── __init__.py│   ├── models.py│   ├── tests.py│   └── views.py└── manage.py

在本教程中,我们将专注于 models.py 文件,该文件位于 blogsite 目录中。

步骤 2 — 添加文章模型

首先,我们需要打开并编辑 models.py 文件,以便其中包含生成 Post 模型的代码。Post 模型包含以下数据库字段:

  • title — 博客文章的标题。
  • slug — 存储和生成网页的有效 URL。
  • content — 博客文章的文本内容。
  • created_on — 文章创建的日期。
  • author — 撰写文章的人。

现在,进入包含 models.py 文件的目录。

cd ~/my_blog_app/blog/blogsite

使用 cat 命令在终端中显示文件的内容。

cat models.py

文件应该包含以下代码,其中导入了模型,并包含了一个描述应该放入这个 models.py 文件的注释。

from django.db import models# Create your models here.

使用您喜欢的文本编辑器,将以下代码添加到 models.py 文件中。我们将使用 nano 作为我们的文本编辑器,但您可以使用您喜欢的任何编辑器。

nano models.py

在这个文件中,已经添加了导入模型 API 的代码,我们可以继续删除后面的注释。然后,我们将导入 slugify 以从字符串生成 slug,Django 的 User 用于身份验证,以及从 django.urls 导入 reverse 以便更灵活地创建 URL。

from django.db import models
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
from django.urls import reverse

然后,在我们将要称为 Post 的模型类上添加类方法,其中包含以下数据库字段:titleslugcontentcreated_onauthor。将这些添加到您的导入语句下面。

...
class Post(models.Model):title = models.CharField(max_length=255)slug = models.SlugField(unique=True, max_length=255)content = models.TextField()created_on = models.DateTimeField(auto_now_add=True)author = models.TextField()

接下来,我们将为生成 URL 添加功能,并为保存文章添加功能。这是至关重要的,因为这将创建一个唯一的链接来匹配我们的唯一文章。

...def get_absolute_url(self):return reverse('blog_post_detail', args=[self.slug])def save(self, *args, **kwargs):if not self.slug:self.slug = slugify(self.title)super(Post, self).save(*args, **kwargs)

现在,我们需要告诉模型帖子应该如何排序,并在网页上显示。这个逻辑将被添加到一个嵌套的内部 Meta 类中。Meta 类通常包含与数据库字段定义无关的其他重要模型逻辑。

...class Meta:ordering = ['created_on']def __unicode__(self):return self.title

最后,我们将在这个文件中添加 Comment 模型。这涉及添加另一个名为 Comment 的类,其签名中包含 models.Models,并定义以下数据库字段:

  • name — 发表评论的人的姓名。
  • email — 发表评论的人的电子邮件地址。
  • text — 评论本身的文本。
  • post — 发表评论的文章。
  • created_on — 评论创建的时间。
...
class Comment(models.Model):name = models.CharField(max_length=42)email = models.EmailField(max_length=75)website = models.URLField(max_length=200, null=True, blank=True)content = models.TextField()post = models.ForeignKey(Post, on_delete=models.CASCADE)created_on = models.DateTimeField(auto_now_add=True)

到目前为止,models.py 将会完成。确保您的 models.py 文件与以下内容匹配:

from django.db import models
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
from django.urls import reverseclass Post(models.Model):title = models.CharField(max_length=255)slug = models.SlugField(unique=True, max_length=255)content = models.TextField()created_on = models.DateTimeField(auto_now_add=True)author = models.TextField()def get_absolute_url(self):return reverse('blog_post_detail', args=[self.slug])def save(self, *args, **kwargs):if not self.slug:self.slug = slugify(self.title)super(Post, self).save(*args, **kwargs)class Meta:ordering = ['created_on']def __unicode__(self):return self.titleclass Comment(models.Model):name = models.CharField(max_length=42)email = models.EmailField(max_length=75)website = models.URLField(max_length=200, null=True, blank=True)content = models.TextField()post = models.ForeignKey(Post, on_delete=models.CASCADE)created_on = models.DateTimeField(auto_now_add=True)

确保保存并关闭文件。如果您使用的是 nano,您可以通过输入 CTRLX,然后 Y,然后 ENTER 来完成。

有了设置好的 models.py 文件,我们可以继续更新我们的 settings.py 文件。

步骤 3 — 更新设置

现在我们已经向我们的应用程序添加了模型,我们必须告知我们的项目刚刚添加的 blogsite 应用程序的存在。我们通过将其添加到 settings.py 中的 INSTALLED_APPS 部分来实现这一点。

导航到包含您的 settings.py 的目录。

cd ~/my_blog_app/blog/blog

然后,使用 nano 或其他编辑器打开您的 settings.py 文件。

 nano settings.py

打开文件后,按照下面的指示将您的 blogsite 应用程序添加到文件的 INSTALLED_APPS 部分。

# Application definition
INSTALLED_APPS = ['blogsite','django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles',
]

添加了 blogsite 应用程序后,您可以保存并退出文件。

此时,我们已经准备好继续应用这些更改。

步骤 4 — 进行迁移

添加了我们的 PostComment 模型后,下一步是应用这些更改,以便我们的 MySQL 数据库模式识别它们并创建必要的表。

首先,我们必须使用 makemigrations 命令将我们的模型更改打包成单独的迁移文件。这些文件类似于版本控制系统(如 Git)中的提交。

现在,如果您导航到 ~/my_blog_app/blog/blogsite/migrations 并运行 ls 命令,您会注意到只有一个 __init__.py 文件。一旦我们添加了迁移,这将会改变。

使用 cd 切换到博客目录,如下所示:

cd ~/my_blog_app/blog

然后在 manage.py 上运行 makemigrations 命令。

python manage.py makemigrations

然后您将在终端窗口中收到以下输出:

Migrations for 'blogsite':blogsite/migrations/0001_initial.py- Create model Post- Create model Comment

记住,当我们导航到 /~/my_blog_app/blog/blogsite/migrations 时,它只有 __init__.py 文件?如果我们现在切换回该目录,我们会注意到已经添加了两个项目:__pycache__0001_initial.py。当您运行 makemigrations 时,0001_initial.py 文件会自动生成。每次运行 makemigrations 时都会生成类似的文件。

如果您想阅读文件的内容,请从所在目录运行 less 0001_initial.py

现在导航到 ~/my_blog_app/blog

cd ~/my_blog_app/blog

由于我们已经创建了迁移文件,我们必须使用 migrate 命令将这些文件描述的更改应用到数据库。但首先,让我们使用 showmigrations 命令检查当前存在哪些迁移。

python manage.py showmigrations
admin[X] 0001_initial[X] 0002_logentry_remove_auto_add[X] 0003_logentry_add_action_flag_choices
auth[X] 0001_initial[X] 0002_alter_permission_name_max_length[X] 0003_alter_user_email_max_length[X] 0004_alter_user_username_opts[X] 0005_alter_user_last_login_null[X] 0006_require_contenttypes_0002[X] 0007_alter_validators_add_error_messages[X] 0008_alter_user_username_max_length[X] 0009_alter_user_last_name_max_length[X] 0010_alter_group_name_max_length[X] 0011_update_proxy_permissions
blogsite[ ] 0001_initial
contenttypes[X] 0001_initial[X] 0002_remove_content_type_name
sessions[X] 0001_initial

您会注意到除了我们刚刚创建的 0001_initial 之外,所有迁移都已经被检查。

现在让我们使用以下命令检查一旦我们进行迁移将执行哪些 SQL 语句,它接受迁移和迁移的标题作为参数:

python manage.py sqlmigrate blogsite 0001_initial

下面显示了幕后实际执行的 SQL 查询。

--
-- Create model Post
--
CREATE TABLE `blogsite_post` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `title` varchar(255) NOT NULL, `slug` varchar(255) NOT NULL UNIQUE, `content` longtext NOT NULL, `created_on` datetime(6) NOT NULL, `author` longtext NOT NULL);
--
-- Create model Comment
--
CREATE TABLE `blogsite_comment` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `name` varchar(42) NOT NULL, `email` varchar(75) NOT NULL, `website` varchar(200) NULL, `content` longtext NOT NULL, `created_on` datetime(6) NOT NULL, `post_id` integer NOT NULL);
ALTER TABLE `blogsite_comment` ADD CONSTRAINT `blogsite_comment_post_id_de248bfe_fk_blogsite_post_id` FOREIGN KEY (`post_id`) REFERENCES `blogsite_post` (`id`);

现在让我们执行迁移,以便将它们应用到我们的 MySQL 数据库。

python manage.py migrate

您将收到以下输出:

Operations to perform:Apply all migrations: admin, auth, blogsite, contenttypes, sessions
Running migrations:Applying blogsite.0001_initial... OK

您已成功应用了迁移。

请记住,根据 Django 文档,使用 MySQL 作为后端的 Django 迁移有三个注意事项。

  • 不支持围绕模式更改操作的事务。换句话说,如果迁移未成功应用,您将不得不手动取消您所做的更改,以尝试另一个迁移。无法回滚到在失败迁移之前的任何更改。
  • 对于大多数模式更改操作,MySQL 将完全重写表。在最坏的情况下,时间复杂度将与表中的行数成正比。根据 Django 文档,这可能慢到每百万行一分钟。
  • 在 MySQL 中,列、表和索引的名称长度有限制。所有列和索引覆盖的组合大小也有限制。虽然其他一些后端可以支持 Django 中创建的更高限制,但在使用 MySQL 后端时,相同的索引将无法创建。

对于您考虑用于 Django 的每个数据库,务必权衡各自的优缺点。

步骤 5 —— 验证数据库模式

迁移完成后,我们应该验证通过 Django 模型创建的 MySQL 表的成功生成。

为此,请在终端中运行以下命令以登录到 MySQL。我们将使用之前教程中创建的 djangouser

mysql blog_data -u djangouser

现在,选择我们的数据库 blog_data。如果你不知道正在使用的数据库,可以在 SQL 中使用SHOW DATABASES;来显示所有数据库。

USE blog_data;

然后输入以下命令以查看表。

SHOW TABLES;

这个 SQL 查询应该会显示以下内容:

+----------------------------+
| Tables_in_blog_data        |
+----------------------------+
| auth_group                 |
| auth_group_permissions     |
| auth_permission            |
| auth_user                  |
| auth_user_groups           |
| auth_user_user_permissions |
| blogsite_comment           |
| blogsite_post              |
| django_admin_log           |
| django_content_type        |
| django_migrations          |
| django_session             |
+----------------------------+
12 rows in set (0.01 sec)

在这些表中包括 blogsite_commentblogsite_post。这些是我们刚刚创建的模型。让我们验证它们是否包含我们定义的字段。

DESCRIBE blogsite_comment;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | int          | NO   | PRI | NULL    | auto_increment |
| name       | varchar(42)  | NO   |     | NULL    |                |
| email      | varchar(75)  | NO   |     | NULL    |                |
| website    | varchar(200) | YES  |     | NULL    |                |
| content    | longtext     | NO   |     | NULL    |                |
| created_on | datetime(6)  | NO   |     | NULL    |                |
| post_id    | int          | NO   | MUL | NULL    |                |
+------------+--------------+------+-----+---------+----------------+
7 rows in set (0.00 sec)
DESCRIBE blogsite_post;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | int          | NO   | PRI | NULL    | auto_increment |
| title      | varchar(255) | NO   |     | NULL    |                |
| slug       | varchar(255) | NO   | UNI | NULL    |                |
| content    | longtext     | NO   |     | NULL    |                |
| created_on | datetime(6)  | NO   |     | NULL    |                |
| author     | longtext     | NO   |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)

我们已经验证了数据库表是否成功从我们的 Django 模型迁移中生成。

你可以使用 CTRL + D 退出 MySQL,当你准备离开 Python 环境时,可以运行 deactivate 命令:

deactivate

退出编程环境将使你回到终端命令提示符。

结论

在本教程中,我们成功为博客 Web 应用程序的基本功能添加了模型。你已经学会了如何编写 modelsmigrations 的工作原理以及将 Django models 转换为实际的 MySQL 数据库表的过程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/11741.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

孩子如何备考编程竞赛

为了帮助孩子更好地备考编程竞赛,家长和老师还可以采取以下一些措施: 制定合理的学习计划:家长和孩子可以一起制定一个合理的学习计划,包括每天的学习时间安排、学习内容和目标等。通过制定学习计划,可以帮助孩子更有条…

An 2024下载

An2024下载: 百度网盘下载https://pan.baidu.com/s/1cQQCFL16OUY1G6uQWgDbSg?pwdSIMS Adobe Animate 2024,作为Flash技术的进化顶点,是Adobe匠心打造的动画与交互内容创作的旗舰软件。这款工具赋予设计师与开发者前所未有的创意自由&#x…

HIVE卡口流量需求分析

HIVE卡口流量需求分析 目录 HIVE卡口流量需求分析 1.创建表格 插入数据 2.需求 3.总结: 1.创建表格 插入数据 CREATE TABLE learn3.veh_pass( id STRING COMMENT "卡口编号", pass_time STRING COMMENT "进过时间", pass_num int COMMENT …

huggingface 笔记:AutoClass (quick tour 部分)

AutoClass 是一个快捷方式,它可以自动从模型的名称或路径检索预训练模型的架构。只需要为任务选择适当的 AutoClass 及其关联的预处理类。 1 AutoTokenizer 分词器负责将文本预处理成模型输入的数字数组。控制分词过程的规则有多种,包括如何分割单词以…

【iOS】架构模式

文章目录 前言一、MVC二、MVP三、MVVM 前言 之前写项目一直用的是MVC架构,现在来学一下MVP与MVVM两种架构,当然还有VIPER架构,如果有时间后面会单独学习 一、MVC MVC架构先前已经详细讲述,这里不再赘述,我们主要讲一…

Golang | Leetcode Golang题解之第87题扰乱字符串

题目: 题解: func isScramble(s1, s2 string) bool {n : len(s1)dp : make([][][]int8, n)for i : range dp {dp[i] make([][]int8, n)for j : range dp[i] {dp[i][j] make([]int8, n1)for k : range dp[i][j] {dp[i][j][k] -1}}}// 第一个字符串从 …

【SAP ABAP学习资料】通过RFC接口上传图片至SAP 图片格式转换 图片大小调整

SAP图片相关: 链接: 【SAP ABAP学习资料】图片上传SAP 链接: 【SAP ABAP学习资料】屏幕图片预览 链接: 【SAP ABAP学习资料】smartforms打印图片,动态打印图片 需求: SAP上传图片只能本地电脑选择图片通过SE78或PERFORM IMPORT_BITMAP_BDS上…

linux程序分析命令(三)

linux程序分析命令(三) **ldd:**用于打印共享库依赖。这个命令会显示出一个可执行文件所依赖的所有共享库(动态链接库),这对于解决运行时库依赖问题非常有用。**nm:**用于列出对象文件的符号表。这个命令可以显示出定…

Milvus入门初探

引言 Milvus 是一款开源的向量数据库,专为处理向量搜索任务而设计。它支持多种类型的向量,如浮点向量、二进制向量等,并且可以处理大规模的向量数据。Milvus 在 AI 应用中非常流行,尤其是在需要执行相似性搜索或最近邻搜索的场景…

【超详细】跑通YOLOv8之深度学习环境配置3-YOLOv8安装

环境配置3下载安装内容如下: 1、配置清华等镜像源 2、创建环境 3、下载安装Pytorch 4、下载安装YOLOv8运行环境 版本:Python3.8(要求>3.8),torch1.12.0cu113(要求>1.8) 1、配置清华等镜…

算法-卡尔曼滤波之为什么要使用卡尔曼滤波器

假设使用雷达来预测飞行器的位置; 预先的假设条件条件: 1.激光雷达的激光束每5s发射一次; 2.通过接受的激光束,雷达估计目标当前时刻的位置和速度; 3.同时雷达要预测下一时刻的位置和速度 根据速度,加速度和位移的…

ESP32重要库示例详解(三):按键之avdweb_Switch库

在Arduino开发中,我们经常需要处理按钮和开关的输入。avdweb_Switch库就是为了简化这一任务,提供了一个优雅且高效的事件处理方式。本文将通过一个实际示例,介绍该库的主要特性和用法。 导入库 在Arduino IDE导入avdweb_Switch库的步骤如下…

Python---NumPy万字总结【此篇文章内容难度较大,线性代数模块】(3)

NumPy的应用(3) 向量 向量(vector)也叫矢量,是一个同时具有大小和方向,且满足平行四边形法则的几何对象。与向量相对的概念叫标量或数量,标量只有大小,绝大多数情况下没有方向。我们…

家居分类的添加、修改、逻辑删除和批量删除

文章目录 1.逻辑删除家居分类1.将之前的docker数据库换成云数据库2.树形控件增加添加和删除按钮1.找到控件2.粘贴四个属性到<el-tree 属性>3.粘贴两个span到<el-tree>标签里4.代码5.效果6.方法区新增两个方法处理添加和删除分类7.输出查看一下信息8.要求节点等级小…

李开复引领的零一万物开源了Yi-1.5模型,推出了6B、9B、34B三个不同规模的版本

零一万物&#xff0c;由李开复博士引领的AI 2.0公司&#xff0c;近期开源了其备受瞩目的Yi-1.5模型&#xff0c;这一举措再次彰显了公司在人工智能领域的创新实力与开放精神。Yi-1.5模型作为零一万物的重要技术成果&#xff0c;不仅代表了公司在大模型技术研发上的新高度&#…

冥想的时候怎么专注自己

冥想的时候怎么专注自己&#xff1f;我国传统的打坐养生功法&#xff0c;实际最早可追溯到五千年前的黄帝时代。   每天投资两个半小时的打坐&#xff0c;有上千年之久的功效。因为当你们打坐进入永恒时&#xff0c;时间停止了。这不只是两个半小时&#xff0c;而是百千万亿年…

为什么3d重制变换模型会变形?---模大狮模型网

3D建模和渲染过程中&#xff0c;设计师经常会遇到一个让人头疼的问题&#xff0c;那就是模型在进行重制变换后出现的意外变形。这种变形不仅影响了模型的外观和质量&#xff0c;也给设计工作带来了额外的麻烦。本文将深入探讨3D模型进行重制变换后出现变形的原因&#xff0c;帮…

小王的踩坑日记 之mysql

按天按月按年统计 mysql中dateTime字段提供了 date_format 函数进行格式化该字段显示成期望形式 DATE_FORMAT(date,format) 函数用于以不同的格式显示日期/时间数据。 格式描述%a缩写星期名%b缩写月名%c月&#xff0c;数值%D带有英文前缀的月中的天%d月的天&#xff0c;数值&…

回炉重造java----JVM

为什么要使用JVM ①一次编写&#xff0c;到处运行&#xff0c;jvm屏蔽字节码与底层的操作差异 ②自动内存管理&#xff0c;垃圾回收功能 ③数组下边越界检查 ④多态 JDK&#xff0c;JRE&#xff0c;JVM的关系 JVM组成部分 JVM的内存结构 《一》程序计数器(PC Register) 作用…

傻瓜化备份/恢复K8S集群Etcd数据

前言&#xff1a; 备份重要数据&#xff0c;简化重复操作&#xff0c;让一指禅、点点点也能完成运维任务。 脚本呈现界面如下&#xff1a; 1、查看Etcd版本 rootmaster:~# cat /etc/kubernetes/manifests/etcd.yaml | grep image: | awk {print $2} registry.aliyuncs.com/goo…