跳到主要内容
博客数据库Django如何为SQL做重活

Django如何为SQL做重活

Django是如何完成重任的 - 博客头条

PythonDjango,尤其是Django,是建立更有效的应用程序的必要条件,用更少的代码,并连接到一个高度可扩展的数据库。我在这里要和大家讨论的是,如何使用SQL和Python ,减少构建和支持现代应用程序时的日常摩擦,以抽象出复杂性,使我们的工作和生活更轻松一些。

在不深入了解的情况下,我们可以假设:

  • SQL是为SQL数据库优化的
  • Python 没有针对SQL数据库进行优化

这个练习直接支持《理解数据库》电子书和我新的Linode LIVE!教育系列,使用Python 和Pythonic工具来执行原始SQL的命令,而不需要实际编写SQL。我使用的是Django的数据建模,但其语法与Python 中的SQLAlchemy包非常相似。

让我们开始吧!
这里有一个Django数据模型的例子:

class BlogArticle(models.Model):
    user = models.ForeignKey(User, default=1, on_delete=models.SET_DEFAULT)
    title = models.CharField(max_length=120)
    slug = models.SlugField(blank=True, null=True)
    content = models.TextField(blank=True, null=True)
    publish_timestamp = models.DateTimeField(
        auto_now_add=False,
        auto_now=False,
        blank=True,
        null=True,
    )

让我们假设这个模型生活在一个名为 Articles (Django应用程序本质上是构成Django项目整体的组件)。

所以现在我们有两个名字可以使用:

  • Articles (应用名称)
  • BlogArticle (模型名称)

结合起来,这些就转化为SQL表的名称:

articles_blog_article

Django为我们施展了这个魔法。

如果我们使用的是MySQL外壳,我们会看到:

mysql> SHOW TABLES;
+------------------------------+
| Tables_in_cfe_django_blog_db |
+------------------------------+
| articles_blog_article        |
| auth_group                   |
| auth_group_permissions       |
| auth_permission              |
| auth_user                    |
| auth_user_groups             |
| auth_user_user_permissions   |
| django_admin_log             |
| django_content_type          |
| django_migrations            |
| django_session               |
+------------------------------+
11 rows in set (0.01 sec)

现在让我们看看我们的Django模型中的列:

mysql> DESCRIBE articles_blog_article;
+------------------------+--------------+------+-----+---------+----------------+
| Field                  | Type         | Null | Key | Default | Extra          |
+------------------------+--------------+------+-----+---------+----------------+
| id                     | bigint       | NO   | PRI | NULL    | auto_increment |
| title                  | varchar(120) | NO   |     | NULL    |                |
| slug                   | varchar(50)  | YES  | MUL | NULL    |                |
| content                | longtext     | YES  |     | NULL    |                |
| publish_timestamp      | datetime(6)  | YES  |     | NULL    |                |
| user_id                | int          | NO   | MUL | NULL    |                |
+------------------------+--------------+------+-----+---------+----------------+
12 rows in set (0.00 sec)

除了写一个基本的配置之外,Django在这个MySQL数据库中为我们做了所有的SQL工作。在这一点上,Django并没有做任何非常令人印象深刻的事情。事实上,这个练习的大部分内容并不是为了突出Django或Python 作为SQL的替代品,而是为了提醒你抽象工作的事实

Python 的崛起和摩擦的代价

让我们来谈谈阻力最小的路径,以及为什么我认为Python 是利用SQL的最佳方式之一。

编写、阅读、运行和运送Python ,都非常容易。将 "Python" 改为几乎任何其他的编程范式,几乎不可能做出同样的声明。JavaScript也是一个竞争者,但它也一直被混淆为Java。我知道这些都是概括性的,并不总是真实的,但这是开发你的应用程序时常见的问题。

我相信这些概括往往是真实的,因为Python's English-like syntax for doing things.

让我们比较一下SQL语句和Python 、Django语句:

  • SQL: SELECT * from articles_blog_article;
  • Python 和Django: items = BlogArticle.objects.all()

两条语句产生的数据完全相同。然而,Python 语句返回一个Python 对象的列表(items),几乎任何有经验的Python 开发人员都可以使用。原始的SQL结果在被用于Python 应用程序之前需要进行转换。

字段描述
如果我们仔细看一下这个SQL字段描述:

+------------------------+--------------+------+-----+---------+----------------+
| Field                  | Type         | Null | Key | Default | Extra          |
+------------------------+--------------+------+-----+---------+----------------+
| title                  | varchar(120) | NO   |     | NULL    |                |
+------------------------+--------------+------+-----+---------+----------------+

与这个Django字段描述相比:

title = models.CharField(max_length=120)

  • 哪一个的摩擦力更大?
  • 哪一个更容易理解发生了什么事?

其中提供的信息刚好够用

如果你不是一个编码员,看到 varchar(120)你会怎么想?我敢肯定,你至少可以猜到什么 max_length=120 means.最酷的是,它们的意思完全一样:把这个字段限制在120个字符以内。

向数据库添加数据

有了Django:

BlogArticle.objects.create(
    title="Hello World",
    content="Coming Soon",
    slug="hello-world",
    publish_timestamp=None,
)

有了SQL:

INSERT INTO `articles_blog_article` (`user_id`, `title`, `slug`, `content`, `publish_timestamp`) 
VALUES (1, 'Hello World', 'hello-world', 'Coming Soon', NULL);

说到简单和清晰,我认为上面的赢家肯定是Django和Python 。 title = "Hello World" 是比在SQL中弄清楚同等的列(字段)值是怎么回事更容易。不要搞错了,当你知道自己在做什么的时候,在SQL中的这种写法是非常有效的。

用Django添加多行

items = [
    BlogArticle(title='Hello Again 0', slug='hello-again-0', content="Coming Soon"),
    BlogArticle(title='Hello Again 1', slug='hello-again-1', content="Coming Soon"),
    BlogArticle(title='Hello Again 2', slug='hello-again-2', content="Coming Soon"),
    BlogArticle(title='Hello Again 3', slug='hello-again-3', content="Coming Soon"),
    BlogArticle(title='Hello Again 4', slug='hello-again-4', content="Coming Soon"),
]
BlogArticle.objects.bulk_create(items)

有了SQL:

INSERT INTO `articles_blog_article` (`user_id`, `title`, `slug`, `content`, `publish_timestamp`) 
VALUES (1, 'Hello Again 0', 'hello-again-0', 'Coming Soon', NULL),
    (1, 'Hello Again 1', 'hello-again-1', 'Coming Soon', NULL),
    (1, 'Hello Again 2', 'hello-again-2', 'Coming Soon', NULL),
    (1, 'Hello Again 3', 'hello-again-3', 'Coming Soon', NULL),
    (1, 'Hello Again 4', 'hello-again-4', 'Coming Soon', NULL);

同样,Python 的代码更具有可读性,而SQL代码则能更深入地了解实际数据。而且,Python ,又一次用上面的Django代码为我们写了这段SQL代码。很整洁,是吧?

我之所以潜心研究这个侧面比较,不是为了挑选,哪个是利用SQL数据库的最佳方式,而是为了突出Python,帮助减少直接学习编写原始SQL的开销。

有几个Python 包,它们基本上是为你写原始SQL,下面是其中的几个:

  • Django
  • 熊猫
  • SQLAlchemy
  • 极点
  • 邓小平
  • Vaex
  • Python的内置CSV模块
  • 龟兔赛跑 ORM
  • Pony ORM
  • 淘宝客

Django做重活
对象关系映射包(通常被称为ORM)是Python ,它是如何利用SQL数据库的秘方。我认为ORM是一个中间人,它可以帮助在任何特定的编程语言的本地语法中移动数据。

在本练习的早些时候,我们开始看到这一点是如何转化为Django的,但现在让我们扩展一下。

假设我们的数据库里有数据,我们可以写一个这样的命令:

my_post = BlogArticle.objects.first()
这个语句将查询我们的数据库,提取数据,将其加载到一个Python Class,然后将其分配给变量 my_post.

从这里,我们现在可以做这样的事情:

# using a django-managed python shell
# via python manage.py shell
>>> print(my_post.title)
Hello World

在这种情况下,我们使用点符号来访问 title 中声明的字段。 BlogPost 上一节中的Django模型。这个字段对应于我们SQL数据库表中的一个列 articles_blog_article.

多亏了ORM,我们可以做到这一点:

>>> my_post.title = "some other title"

在这个Python shell会话的例子中, my_post.title 现在将 始终"some other title".然而,底层的SQL数据库仍然将这些完全相同的数据识别为 Hello World.数据库将保留原始数据,直到Python 最终提交(又称 .save())这个数据变化到数据库中。如果Python ,它将永远不会在数据库中被更新。这就是ORM的神奇之处。我们可以 使用变化 而不影响实际存储的数据。当我们想改变数据库中实际发生的情况时,我们运行:

>>> my_post.title = "some other title again"
>>> my_post.save()

运行后 .save() 我们的数据库,对于这个特定的行,将更新列的标题,以完全匹配上面写成的Python 字符串。请不要忘记,在 .save() 方法是专门用于在Django模型中向数据库进行提交的。 .save() 对一个人来说,实际上并不意味着什么Python Class 而不首先继承一个形式的Django模型类。

用Django、MySQL和Linode进行建设

这是Django如何为你做繁重工作的众多例子之一。如果你对在Linode上部署Django应用程序的现代方法以及管理的MySQL数据库、用于CI/CD的GitHub Actions、Terraform ,以及Ansible ,请查看以下内容,现在Linode上可以看到:

为了帮助你开始,Coding for Entrepreneurs GitHub有一个代码库,与该系列的每个步骤相配套。祝你好运,一定要通过Twitter@JustinMitchel让我知道事情进展如何。


注释

留下回复

您的电子邮件地址将不会被公布。 必须填写的字段被标记为*