Django开发--step2 数据库操作

本文详细介绍了如何在Django中使用ORM进行数据库操作,包括模型设计、数据增删改查,以及数据库迁移的全过程。了解如何从Python代码转换为数据库语言,掌握Django的模型与数据库之间的映射机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、博客系统数据库设计
博客文章表
1. ID  | 标题   | 正文  |  发表时间   | 分类  |  标签
2. ID  | 分类名
3. ID  | 标签名
表中最起码有这些内容

二、编写博客模型代码
例如我们的分类数据库表,Django 只要求我们这样写:

blogapp/models.py

from django.db import models

class Category(models.Model):
    name = models.CharField(max_length=100)


Category 就是一个标准的 Python 类,它继承了 models.Model 类,类名为 Category 。Category 类有一个属性 name,它是 models.CharField 的一个实例。

这样,Django 就可以把这个类翻译成数据库的操作语言,在数据库里创建一个名为 category 的表格,这个表格的一个列名为 name。还有一个列 id,Django 则会自动创建。可以看出从 Python 代码翻译成数据库语言时其规则就是一个 Python 类对应一个数据库表格,类名即表名,类的属性对应着表格的列,属性名即列名。

上述操作数据库的方法叫做ORM,是django设计的一套python对象与数据库的映射系统,使得开发者可以不用SQL语句就能实现及其复杂的数据库操作,ORM框架为每个表对应的类都生成了objects对象(如果你没有显式指定表的Manager的话),而这个objects对象拥有操作表的所有方法,诸如批量查询filter、单次查询get、更新update等。所以当我们执行SQL操作时,比如查询整表,可以如下:

articles = Article.objects.all()

上述代码返回了表中的所有行,注意在代码中:

  • ForeignKey: 一对多, 将该属性定义到多的那一端
  • OneToOneField: 一对一, 将该属性定义到任一端
  • ManyToManyField: 多对多, (将该属性定义到两端),多对多关系会自动生成一张表

 

三、Django完成翻译-迁移数据库

以上我们编写的知识python代码,django还没有把它翻译为数据库语言,因此数据库表还没有在真正的数据库中创建

什么是数据库迁移?
当我们在看关于web开发的教程时,教程在设计数据表时,不是一下子就设计好的,而是先设计一个能用的数据表,然后再慢慢的往里面增加东西。当我们往表里面增加东西时,比如说增加一个字段,那么之前的数据怎么办?
这时候就要用到数据库迁移了,在数据表进行更新时,可以利用数据库迁移脚本在当前数据表进行更新,而不是重新创建一个数据表。

在django中的数据库迁移需要前后执行两个命令:

python manage.py makemigrations

   和  

 python manage.py migrate

执行第一个命令---》生成迁移文件

执行第二个命令---》生成数据库表

当我们执行了 python manage.py makemigrations 后,Django 在 blog 应用的 migrations\ 目录下生成了一个 0001_initial.py 文件,这个文件是 Django 用来记录我们对模型做了哪些修改的文件。目前来说,我们在 models.py 文件里创建了 3 个模型类,Django 把这些变化记录在了 0001_initial.py 里。

不过此时还只是告诉了 Django 我们做了哪些改变,为了让 Django 真正地为我们创建数据库表,接下来又执行了 python manage.py migrate 命令。Django 通过检测应用中 migrations\ 目录下的文件,得知我们对数据库做了哪些操作,然后它把这些操作翻译成数据库操作语言,从而把这些操作作用于真正的数据库。

你可以看到命令的输出除了 Applying blog.0001_initial... OK 外,Django 还对其它文件做了操作。这是因为除了我们自己建立的 blog 应用外,Django 自身还内置了很多应用,这些应用本身也是需要存储数据的。可以在 settings.py 的 INSTALLED_APP 设置里看到这些应用,当然我们目前不必关心这些。

只要模型类涉及到结构改变都要重新执行两个迁移命令

当我们执行 :::

python manage.py sqlmigrate blogapp 0001

可以看到django究竟为我们做了什么

BEGIN;
--
-- Create model Category
--
CREATE TABLE "blogapp_category" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(100) NOT NULL);
--
-- Create model Post
--
CREATE TABLE "blogapp_post" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "title" varchar(70) NOT NULL, "body" text NOT NULL, "created_time" datetime NOT NULL,
 "modified_time" datetime NOT NULL, "excerpt" varchar(200) NOT NULL, "author_id" integer NOT NULL REFERENCES "auth_user" ("id"), "category_id" integer NOT NULL REF
ERENCES "blogapp_category" ("id"));
--
-- Create model Tag
--
CREATE TABLE "blogapp_tag" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(100) NOT NULL);
--
-- Add field tags to post
--
CREATE TABLE "blogapp_post_tags" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "post_id" integer NOT NULL REFERENCES "blogapp_post" ("id"), "tag_id" integer NO
T NULL REFERENCES "blogapp_tag" ("id"));
CREATE INDEX "blogapp_post_4f331e2f" ON "blogapp_post" ("author_id");
CREATE INDEX "blogapp_post_b583a629" ON "blogapp_post" ("category_id");
CREATE UNIQUE INDEX "blogapp_post_tags_post_id_3c6dd183_uniq" ON "blogapp_post_tags" ("post_id", "tag_id");
CREATE INDEX "blogapp_post_tags_f3aa1999" ON "blogapp_post_tags" ("post_id");
CREATE INDEX "blogapp_post_tags_76f094bc" ON "blogapp_post_tags" ("tag_id");
COMMIT;

sqlite和mysql数据库的区别  本项目使用的是sqlite3 ,在项目的根目录下显示有数据库 db.sqlite3

 

四、用django的方式操作数据库

对数据库的操作无非是增删改查

(blog_venv) D:\python_study2019\blog>python manage.py shell
Python 3.6.5 (v3.6.5:f59c0932b4, Mar 28 2018, 17:00:18) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
# 增加数据
>>> from blogapp.models import Category, Tag, Post
>>> c=Category(name='category test')
>>> c.save()
>>> t=Tag(name='tag test')
>>> t.save()
>>> quit()

# 创建用户
(blog_venv) D:\python_study2019\blog>python manage.py createsuperuser
Username (leave blank to use 'dell'): slyslyme
Email address: slyslyme@163.com
Password:
Password (again):
Superuser created successfully.

(blog_venv) D:\python_study2019\blog>python manage.py shell
Python 3.6.5 (v3.6.5:f59c0932b4, Mar 28 2018, 17:00:18) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from blog.models import Category, Tag, Post
Traceback (most recent call last):
  File "<console>", line 1, in <module>
ModuleNotFoundError: No module named 'blog.models'
>>> from blogapp.models import Category, Tag, Post
>>> from django.utils import timezone
>>> from django.contrib.auth.models import User
>>> user=User.objects.get(username='slyslyme')
>>> c=Category.objects.get(name='category test')
>>> p=Post(title='title test',body='body test', created_time=timezone.now(), modified_time=timezone.now(), category=c, author=user)
>>> p.save()
>>> Category.objects.all()
<QuerySet [<Category: Category object>]>

然后在三个模型代码中各添加了
    def __str__(self):
        return self.name


now exiting InteractiveConsole...

(blog_venv) D:\python_study2019\blog>python manage.py shell
Python 3.6.5 (v3.6.5:f59c0932b4, Mar 28 2018, 17:00:18) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)

# 查询全部
>>> from blogapp.models import Category, Tag, Post
>>> Category.objects.all()
<QuerySet [<Category: category test>]>
>>> Tag.objects.all()
<QuerySet [<Tag: tag test>]>

# 修改数据
>>> c=Category.objects.get(name='category test')
>>> c.name='category test new'
>>> c.save()
>>> Category.objects.all()
<QuerySet [<Category: category test new>]>
>>> c=Category(name='category test')
>>> c.save()
>>> Category.objects.all()
<QuerySet [<Category: category test new>, <Category: category test>]>

# 删除数据
>>> c=Category.objects.get(name='category test new')
>>> c
<Category: category test new>
>>> c.delete()
(2, {'blogapp.Post_tags': 0, 'blogapp.Post': 1, 'blogapp.Category': 1})
>>> Category.objects.all()
<QuerySet [<Category: category test>]>

 

若在运行时报错

    category = models.ForeignKey(Category)
TypeError: __init__() missing 1 required positional argument: 'on_delete'


则将外键修改为

category = models.ForeignKey(Category,on_delete=models.CASCADE)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值