Django笔记03-数据库与数据模型

数据库与数据模型

django框架的设计也采用了MVC模式,但是基于MVC模式却更注重模型(Model)、模板(Template)、视图(View)。通过编写数据模型(Model)来完成对所有数据有关的事物,包括数据库中数据的存取等操作。

数据库

 Mysql、SQLserver 2008、sqlite3 等数据库都可以在 django 中使用,而默认情况下,django 使用的是轻量级的sqlite3,在项目配置文件中可以进行数据库配置

# fbckf/settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
} 

而作为一个小型个人博客,使用 sqlite3 这个数据库就已经绰绰有余了,所以不用去更改配置文件

博客数据

 博客主要是发布文章,文章中包含很多信息,比如标题、作者、类别、评论等,而类别和评论又包括了各自的信息。将数据分为以下两部分,也就是,我们将在数据库中建立两张表,每一部分中的信息就是各自表中的字段。

1.文章

标题 作者 类别 内容 摘要 创建时间 喜欢人数
《绝望》 fbckf 散文 绝望啊... 绝望... 2018-6-2 999+
《白云谣》 先秦诗人 诗词 白云在天... 白云在天... 2018-6-8 9999+

2.类别

名称 简介
散文 散文是一种抒发作者真情实感、写作方式灵活的记叙类文学体裁。
诗词 诗词,是指以古体诗、近体诗和格律词为代表的中国古代传统诗歌。

之所以要将类别和评论从文章中分离出来形成另的表格,是因为这样可以避免数据库中数据的重复存储

数据库模型

 之前所说过,需要在数据库中创建三张表,用来存储博客的各种数据,创建的表就如之前所示的表格一样。一般情况下对数据库的 SQL语句 不熟悉的话,在进行数据库操作时是比较头疼的,幸运的是,django 已经将 SQL语句 转换成相对应的 python 语言,只需要在 blog/models.py 中编写相对应的 python 代码就好了,其中类对应数据库中的表格,类中的属性则对应数据库中的字段
数据

编写数据模型代码

    # blog/models.py
    from django.db import models
    # auth是django内置的一个应用
    from django.contrib.auth.models import User
    
    # 对应数据库中类别的表,类名 Category 就是表的名称
    # 继承了models.Model
    class Category(models.Model):
        # 属性 name 是表中的名称字段, name 是简单的字符串所以使用CharField()类型
        # max_length=20 表示该字段最长为20字符,unique=True 表示该字段具有的唯一性
        name = models.CharField(max_length=20, unique=True)
        # 属性instructions 对应简介字段,因为 instructions 是文本,所以使用TextField()类型
        # default=“” 表示该字段默认内容为空
        instructions = models.TextField(max_length=100, default="")
        
    
    class Article(models.Model):
        title = models.CharField(max_length=50, unique=True)
        # 一个作者有多篇文章,但是一篇文章只有一个作者,这是一对多的关系,所以使用 ForeignKey()类型
        # ForeignKey() 将 注册的用户 User 和文章关联起来
        # on_delete=models.CASCADE 表示当删除该用户时,该用户关联的文章也会一并删除
        # null=True 表示允许为空 比如从别的平台转发文章
        author = models.ForeignKey(User, null=True, on_delete=models.CASCADE)
        category = models.ForeignKey(Category, null=True, on_delete=models.CASCADE)
        body = models.TextField()
        abstract = models.TextField(max_length=50, default="")
        # create_time 是时间,所以使用 DateTimeField()类型
        # auto_now=True 表示自动添加该字段的值
        create_time = models.DateTimeField(auto_now=True)
        # PositiveIntegerField() 只允许正整数和0,因为likes字段不为负数和小数,所以使用该类型
        likes = models.PositiveIntegerField(default=0)
  • django 内置的应用 auth(django.contrib.auth),负责整个网站的用户注册、登陆等功能,而 User 是该应用中用户的模型,就像 Category 类一样,在这里导入后与文章关联。

  • 在编写模型代码时,需要根据字段的类型选择对应的字段类型函数,常用的有字符串类型(CharField)、文本类型(TextField)、日期类型(DateField、DateTimeField)、邮箱(EmailField)、整数类型(IntegerField)等。

  • article 与 category、author是一对多的关联关系所以使用 ForeignKey()关联类型,多对多的关联关系是 MangToManyFiled()。

  • 评论建立另外一个应用来完成。

数据库迁移

完成模型代码编写事情后还没有结束,那只是单纯的写好 python 代码,就像只是写策划书,还没有真正去执行,所以还需要告诉 django,根据编写在models.py中的代码,去执行相应的 SQL语句。

    $ python manage.py makemigrations
    Migrations for 'blog':
      blog/migrations/0001_initial.py
        - Create model Article
        - Create model Category
        - Add field category to article
    
    $ python manage.py migrate
    Operations to perform:
      Apply all migrations: admin, auth, blog, contenttypes, sessions
    Running migrations:
      Applying contenttypes.0001_initial... OK
      Applying auth.0001_initial... OK
      Applying admin.0001_initial... OK
      Applying admin.0002_logentry_remove_auto_add... OK
      Applying contenttypes.0002_remove_content_type_name... OK
      Applying auth.0002_alter_permission_name_max_length... OK
      Applying auth.0003_alter_user_email_max_length... OK
      Applying auth.0004_alter_user_username_opts... OK
      Applying auth.0005_alter_user_last_login_null... OK
      Applying auth.0006_require_contenttypes_0002... OK
      Applying auth.0007_alter_validators_add_error_messages... OK
      Applying auth.0008_alter_user_username_max_length... OK
      Applying auth.0009_alter_user_last_name_max_length... OK
      Applying blog.0001_initial... OK
      Applying sessions.0001_initial... OK

执行以上命令之后,在查看一下项目的变化

    $ tree fbckf
    fbckf
    ├── blog
    │     ├── admin.py
    │     ├── apps.py
    │     ├── __init__.py
    │     ├── migrations
    │     │     ├── 0001_initial.py
    │     │     ├── __init__.py
    │     │     └── __pycache__
    │     │             ├── 0001_initial.cpython-35.pyc
    │     │             └── __init__.cpython-35.pyc
    │     ├── models.py
    │     ├── __pycache__
    │     │       ├── admin.cpython-35.pyc
    │     │       ├── __init__.cpython-35.pyc
    │     │       └── models.cpython-35.pyc
    │     ├── tests.py
    │     └── views.py
    ├── db.sqlite3
    ├── fbckf
    │     ├── __init__.py
    │     ├── __pycache__
    │     │       ├── __init__.cpython-35.pyc
    │     │       ├── settings.cpython-35.pyc
    │     │       └── urls.cpython-35.pyc
    │     ├── settings.py
    │     ├── urls.py
    │     └── wsgi.py
    └── manage.py

  • 在项目主目录中生成了一个新的文件db.sqlite3这就是 django 根据模型创建的数据库文件,博客的数据也将存储在里面

  • blog/migrations中的生成了0001_initial.py文件,其中存放着 django 对数据库的操作记录,可以使用命令python manage.py sqlmigrate <应用名称> 0001查看。

    $ python manage.py sqlmigrate blog 0001
    BEGIN;
    --
    -- Create model Article
    --
    CREATE TABLE "blog_article" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "title" varchar(50) NOT NULL UNIQUE, "body" text NOT NULL, "abstract" text NOT NULL, "create_time" datetime NOT NULL, "likes" integer unsigned NOT NULL, "author_id" integer NOT NULL REFERENCES "auth_user" ("id") DEFERRABLE INITIALLY DEFERRED);
    --
    -- Create model Category
    --
    CREATE TABLE "blog_category" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(20) NOT NULL UNIQUE, "instructions" text NOT NULL);
    --
    -- Add field category to article
    --
    ALTER TABLE "blog_article" RENAME TO "blog_article__old";
    CREATE TABLE "blog_article" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "title" varchar(50) NOT NULL UNIQUE, "body" text NOT NULL, "abstract" text NOT NULL, "create_time" datetime NOT NULL, "likes" integer unsigned NOT NULL, "author_id" integer NOT NULL REFERENCES "auth_user" ("id") DEFERRABLE INITIALLY DEFERRED, "category_id" integer NOT NULL REFERENCES "blog_category" ("id") DEFERRABLE INITIALLY DEFERRED);
    INSERT INTO "blog_article" ("author_id", "body", "id", "create_time", "likes", "abstract", "category_id", "title") SELECT "author_id", "body", "id", "create_time", "likes", "abstract", NULL, "title" FROM "blog_article__old";
    DROP TABLE "blog_article__old";
    CREATE INDEX "blog_article_author_id_905add38" ON "blog_article" ("author_id");
    CREATE INDEX "blog_article_category_id_7e38f15e" ON "blog_article" ("category_id");
    COMMIT;

可以在输出中看到详细的 SQL语句

数据库操作

django提供了一个 shell,可以通过它来进行数据库的简单操作

$ python manage.py shell
Python 3.5.2 (default, Sep 14 2017, 22:51:06) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from blog.models import Category, Article
>>> c = Category(name="古诗", instructions="古诗,是中国古代诗歌的一种体裁,又称古体诗或古风,指的是产生于唐代以前并和唐代新出现的近体诗(又名今体诗)相对的一种诗歌体裁")
>>> c.save()
>>> c
<Category: Category object (1)>
>>> c.name
'古诗'
>>> c.instructions
'古诗,是中国古代诗歌的一种体裁,又称古体诗或古风,指的是产生于唐代以前并和唐代新出现的近体诗(又名今体诗)相对的一种诗歌体裁'
>>> 
  • blog应用的models.py中导入Category类,之后通过实例化一个对象,并调用save()方法保存,这样就已经在数据库中插入了一条数据

  • save()方法继承自models.Model

  • 实例化后 django 返回的是<Category: Category object (1)>这样不利于观察代码的执行情况,在每一个models.py的类中写一个__str__用以返回对象的name属性

class Category(models.Model):
    ...
    def __str__(self):
        return self.name
$ python manage.py shell
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from blog.models import Category
>>> Category.objects.all()
<QuerySet [<Category: 古诗>]>
>>> c = Category.objects.get(name='古诗')
>>> c
<Category: 古诗>
>>> 

因为文章类需要关联一个User对象,所以这里直接使用命令创建一个超级用户,也方便接下来的管理

$ python manage.py createsuperuser
Username (leave blank to use 'csx'): fbckf
Email address: m15220982078@163.com
Password: 
Password (again): 
Superuser created successfully.
  • leave blank to use 'csx'是 django 检测到当前操作系统用户名称为 'csx' ,提示默认使用 'csx' 作为超级用户名称

  • 之后邮箱和密码,密码的强度比较严格,所以要好好记住自己设置的密码

$ python manage.py shell
>>> from django.utils import timezone
>>> from django.contrib.auth.models import User
>>> from blog.models import Category, Article
>>> auth = User.objects.get(username='fbckf')
>>> c = Category.objects.get(name='古诗')
>>> article = Article(title='白云谣', author=auth, category=c, body='白云在天,丘陵自出。道里悠远, 山川间之。将子无死,尚复能来。', abstract='白云在天,丘陵自出。', create_time=timezone.now(), likes=0)
>>> article.save()
>>> article.title
'白云谣'
>>> article.author
<User: fbckf>
>>> article.body
'白云在天,丘陵自出。道里悠远,山川间之。将子无死,尚复能来。'
>>> 
  • 调用 django 内置模块timezonenow()方法指定时间

  • 使用get()方法,指定取出用户 'fbckf' 和类别 '古诗'

  • 实例化一个 article 对象并保存

  • delete()方法用于删除数据

总结

  简单来说,整一个博客应用的编写就是围绕着对数据的操作进行的,数据的重要性不言而喻。也因此,数据库的操作也显的尤为重要,而 django 将SQL语句都封装起来,就使得可以通过编写 python 代码来进行数据库操作,这就意味着即使不懂 SQL语句 也可以使用数据库,极大的降低了 django 的使用门槛(当然 SQL语句 也是很重的)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,204评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,091评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,548评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,657评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,689评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,554评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,302评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,216评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,661评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,851评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,977评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,697评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,306评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,898评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,019评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,138评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,927评论 2 355

推荐阅读更多精彩内容