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

>>> c.name
'古诗'
>>> c.instructions
'古诗,是中国古代诗歌的一种体裁,又称古体诗或古风,指的是产生于唐代以前并和唐代新出现的近体诗(又名今体诗)相对的一种诗歌体裁'
>>> 
  • blog应用的models.py中导入Category类,之后通过实例化一个对象,并调用save()方法保存,这样就已经在数据库中插入了一条数据

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

  • 实例化后 django 返回的是这样不利于观察代码的执行情况,在每一个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()
]>
>>> c = Category.objects.get(name='古诗')
>>> c

>>> 

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

$ python manage.py createsuperuser
Username (leave blank to use 'csx'): fbckf
Email address: [email protected]
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

>>> article.body
'白云在天,丘陵自出。道里悠远,山川间之。将子无死,尚复能来。'
>>> 
  • 调用 django 内置模块timezonenow()方法指定时间

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

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

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

总结

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

你可能感兴趣的:(Django笔记03-数据库与数据模型)