django3基础入门-p02-模型层Model

  1. 模型 Model
  2. 设计数据库Model
    1. 字段类型与属性选项说明
    2. 多对一关联设计
    3. 多对多关联设计
    4. 一对一关联设计
  3. 使用模型
  4. 数据库Model API
    1. 创建对象
    2. 为模型提供初始化数据
    3. 查询对象
      1. 获取所有对象(记录)
      2. 通过过滤器检索指定对象
        1. 字符串类型字段:__startswith,__endswith,__contains
        2. 时间类型字段:__year
        3. F()为模型指定字段
        4. 查询 JSONField
        5. 通过 Q 对象完成复杂查询
    4. 跨关联查询:多对一关联模型
      1. 通过1模型的条件过滤获得关联的M模型实例列表
      2. 通过M模型实例获取其关联的1模型对象
      3. 通过M模型的条件过滤获得关联的1模型实例列表
      4. 通过1模型实例获取其关联的M模型对象列表
      5. 重写模型关联名称related_name
      6. add(obj1,** obj2, **…) 加入关联对象
      7. create(**kwargs)创建关联对象
      8. remove(obj1,obj2,…) 删除关联对象
      9. clear() 从关联对象集合删除所有对象
    5. 跨关联查询:多对多关联模型
      1. 在定义了 ManyToManyField 的模型中,使用字段名获得关联对象模型Manager
      2. 在 ManyToManyField的“反向”模型中,使用默认的源模型名的小写形式,加上 '_set' 获取管理对象模型Manager
    6. 跨关联查询:一对一关联模型
      1. 定义了 OneToOneField的模型,通过其字段获取关联模型对象
      2. 在反向查询中,以定义了 OneToOneField的模型类名小写作为字段获取关联模型对象
    7. 修改对象
      1. 通过实例对象修改
      2. 通过QuerySet批量修改
    8. 删除对象
      1. 通过实例对象删除
      2. 通过QuerySet批量删除
  5. 数据库配置
    1. SQLite
    2. MySQL
  6. 数据迁移同步

模型 Model

Django 提供了一个抽象的模型(“models”)层,为了构建和操纵你的 Web 应用的数据

一般来说,每一个模型都映射一张数据库表。

  • 每个模型都是一个 Python 的类,这些类继承 django.db.models.Model
  • 模型类的每个属性都相当于一个数据库的字段
  • 模型类中可以自定义或重写改变数据的行为(方法)
  • Django 提供了一个自动生成访问数据库的 API

设计数据库Model

from django.db import models
import datetime
from django.utils import timezone


class CommonInfo(models.Model):
    """ 抽象基类 """
    create_time = models.DateField(verbose_name='创建日期', auto_now_add=True)
    update_time = models.DateTimeField(verbose_name='修改时间', auto_now=True)

    class Meta:
        abstract = True  # 该模型将不会创建任何数据表。它的字段会自动添加至子类。


class Blog(CommonInfo):
    """ 博客表 """
    name = models.CharField(verbose_name='名称', max_length=100)
    tagline = models.TextField(verbose_name='标语')
    # file will be saved to MEDIA_ROOT/logos/2022/03/09
    logo = models.FileField(upload_to='logos/%Y/%m/%d/', default='logo.jpg')

    def __str__(self):
        return self.name


# upload_to 也可以是一个可调用对象,如函数。
# 这个可调用对象必须接受两个参数:instance,filename,并返回一个 Unix 风格的路径(带斜线)
def user_directory_path(instance, filename):
    """
    instance:FileField 的模型实例
    filename:最初给文件的文件名
    """
    # file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
    return 'user_{0}/{1}'.format(instance.user.id, filename)


class Author(CommonInfo):
    """ 作者表 """
    name = models.CharField(verbose_name='名称', max_length=200)
    email = models.EmailField(verbose_name='邮箱地址')

    def __str__(self):
        return self.name


class AuthorDetail(CommonInfo):
    """ 作者详情表 """
    author = models.OneToOneField(Author, verbose_name='关联作者', on_delete=models.CASCADE)  # OneToOneField 一对一的关系
    avatars = models.ImageField(verbose_name='头像', upload_to=user_directory_path, default='logo.jpg')  # 需要安装Pillow库
    settings = models.JSONField(verbose_name='设置', default=dict)
    SEX_CHOICES = [(1, '男性'), (2, '女性')]
    sex = models.IntegerField(verbose_name='性别', choices=SEX_CHOICES, default=1)
    married = models.BooleanField(verbose_name='婚否')
    website = models.URLField(verbose_name='个人网页', null=True, blank=True)

    def __str__(self):
        return self.author.name


class Entry(CommonInfo):
    """ 文章表 """
    blog = models.ForeignKey(Blog, verbose_name='关联博客', on_delete=models.CASCADE,
                             null=True)  # ForeignKey 多对一的关系 CASCADE 级联删除
    headline = models.CharField(verbose_name='文章标题', max_length=255)
    body_text = models.TextField(verbose_name='文章内容')
    authors = models.ManyToManyField(Author, verbose_name='关联作者')  # ManyToManyField 多对多的关系
    number_of_comments = models.IntegerField(verbose_name='评论数', default=0)
    number_of_likes = models.IntegerField(verbose_name='点赞数', default=0)
    rating = models.IntegerField(verbose_name='评级', default=1)

    def __str__(self):
        return self.headline

    class Meta:
        ordering = ['-create_time']

    def was_modified_recently(self):
        now = timezone.now()
        return now - datetime.timedelta(days=3) <= self.create_time <= now

    @property
    def numbers(self):
        return self.number_of_comments + self.number_of_likes

    def save(self, *args, **kwargs):
        # do_something_before_save...
        super().save(*args, **kwargs)  # Call the "real" save() method.
        # do_somethin_after_save
        print(f"Save Entry success! headline:{self.headline}")

字段类型与属性选项说明

null:

避免在基于字符串的字段上使用 null,如 CharFieldTextField。如果一个基于字符串的字段有 null=True,这意味着它有两种可能的“无数据”值:NULL,和空字符串

blank:

如果一个字段有 blank=True,表单验证将允许输入一个空值。如果一个字段有 blank=False,则该字段为必填字段。

choices:

默认的表单部件将是一个带有这些选择的选择框,而不是标准的文本字段。

ImageField:

  • 需要安装Pillow来支持
pip install Pillow
  • FileField,ImageField upload_to 需要配置settings.py 中的 MEDIA_ROOT 来管理上传根目录
## 设置文件上传的根目录
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

JSONField

一个用于存储 JSON 编码数据的字段。在 Python 中,数据以其 Python 本地格式表示:字典、列表、字符串、数字、布尔值和 None

JSONField 在 MariaDB 10.2.7+、MySQL 5.7.8+、Oracle、PostgreSQL 和 SQLite(在 JSON1 扩展被启用的情况下)都支持。

**注意:要在 SQLite 上使用 JSONField,你需要在 Python 的 sqlite3 库中启用 JSON1 扩展 **

多对一关联设计

定义一个多对一的关联关系,使用 django.db.models.ForeignKey

通常,我们在多的一端设置ForeignKey

image-20220310172606215

多对多关联设计

定义一个多对多的关联关系,使用 django.db.models.ManyToManyField

通常,我们根据逻辑关系,将ManyToManyField实例放到需要在表单中被剪辑的对象中

image-20220315090916505

一对一关联设计

使用 OneToOneField 来定义一对一关系,当一个对象以某种方式“继承”另一个对象时,这对该对象的主键非常有用。

通常,我们在继承(扩展)的一方设置OneToOneField

image-20220323085823293

使用模型

一旦你定义了你的模型,你需要告诉 Django 你准备 使用 这些模型。你需要修改设置文件中的 INSTALLED_APPS ,在这个设置中添加包含 models.py 文件的模块名称。

INSTALLED_APPS = [
    # ...
    'app_demo',
    # ...
]

当你向 INSTALLED_APPS 添加新的应用的时候,请务必进行表结构迁移。

python manage.py makemigrations
python manage.py migrate

Django默认数据库为SQLite3,表结构迁移后,可见在根目录下生成了一个db.sqlite3 的数据库文件。打开该文件即可使用这个数据库。

image-20220309223934074

数据库Model API

在控制台中通过命令 python manage.py shell 或 通过pycharm->Tools->Run manage.py Task... 然后输入dbshell进入django shell 环境

创建对象

>>> from app_demo.models import Blog,Author,AuthorDetail,Entry
>>> b = Blog(name='学习之家',tagline='好好学习,天天向上!')
>>> b.save()
>>> 
>>> b1 = Blog.objects.create(name='我爱编程',tagline='世界和平,人间有爱~')
>>> b1
<Blog: 我爱编程>
>>> 
>>> a1 = Author.objects.create(name='a1',email='a1@126.com')
>>> 
>>> a1_detail = AuthorDetail.objects.create(author=a1,married=True,website='a1.com')
>>> 
>>> a2 = Author.objects.create(name='a2',email='a2@126.com')
>>> 
>>> a2_detail = AuthorDetail(married=False,website='a2.com')
>>> a2_detail.author = a2
>>> a2_detail.save()
>>> 
>>> entry = Entry(blog=b1,headline='Django',body_text='Django入门到精通...')
>>> entry.save()
Add Entry success! headline:Django
>>> entry.authors.add(a1,a2)
  • save() 没有返回值
  • create() 返回对象实例

为模型提供初始化数据

在进行查询练习前,让我们先在数据库中初始化一批练习数据。

  1. 创建固定内容数据 app_demo/fixtures/test_data.json
[
  {
    "model": "app_demo.Blog",
    "pk": 1,
    "fields": {
      "name": "学习之家",
      "tagline": "好好学习,天天向上~",
      "create_time": "2022-03-01",
      "update_time": "2022-03-01 11:11:11"
    }
  },
  {
    "model": "app_demo.Blog",
    "pk": 2,
    "fields": {
      "name": "我爱编程",
      "tagline": "世界和平,人间有爱~",
      "create_time": "2022-03-01",
      "update_time": "2022-03-01 11:11:11"
    }
  },
  {
    "model": "app_demo.Author",
    "pk": 1,
    "fields": {
      "name": "张三",
      "email": "zhangsan@126.com",
      "create_time": "2022-03-01",
      "update_time": "2022-03-01 11:11:11"
    }
  },
  {
    "model": "app_demo.Author",
    "pk": 2,
    "fields": {
      "name": "李四",
      "email": "lisi@126.com",
      "create_time": "2022-03-01",
      "update_time": "2022-03-01 11:11:11"
    }
  },
  {
    "model": "app_demo.Author",
    "pk": 3,
    "fields": {
      "name": "王五",
      "email": "wangwu@126.com",
      "create_time": "2022-03-01",
      "update_time": "2022-03-01 11:11:11"
    }
  },
  {
    "model": "app_demo.AuthorDetail",
    "pk": 1,
    "fields": {
      "author_id": 1,
      "married": true,
      "website": "http://zhangsan.com",
      "settings": {
        "ext_info": {
          "lang": "zh-hans",
          "focus": ["python","java"]
        },
        "collaps": true
      },
      "create_time": "2022-03-01",
      "update_time": "2022-03-01 11:11:11"
    }
  },
  {
    "model": "app_demo.AuthorDetail",
    "pk": 2,
    "fields": {
      "author_id": 2,
      "married": true,
      "website": "http://lisi.com",
      "settings": {
        "ext_info": {
          "lang": "en-us",
          "focus": ["php","java"]
        },
        "collaps": false
      },
      "create_time": "2022-03-01",
      "update_time": "2022-03-01 11:11:11"
    }
  },
  {
    "model": "app_demo.AuthorDetail",
    "pk": 3,
    "fields": {
      "author_id": 3,
      "married": false,
      "website": "http://wangwu.com",
      "settings": {
        "ext_info": {
          "lang": "en-us",
          "focus": ["c++","English"]
        },
        "collaps": true,
        "flag":true
      },
      "create_time": "2022-03-01",
      "update_time": "2022-03-01 11:11:11"
    }
  },
  {
    "model": "app_demo.Entry",
    "pk": 1,
    "fields": {
      "blog_id": 1,
      "headline": "python入门到精通",
      "body_text": "人生苦短,我用python!",
      "authors": [
        1
      ],
      "number_of_comments": 10,
      "number_of_likes": 9,
      "rating": 1,
      "create_time": "2020-03-01",
      "update_time": "2020-03-01 11:11:11"
    }
  },
  {
    "model": "app_demo.Entry",
    "pk": 2,
    "fields": {
      "blog_id": 1,
      "headline": "php入门到精通",
      "body_text": "PHP是世界上最好的语言!",
      "authors": [
        1,
        2
      ],
      "number_of_comments": 9,
      "number_of_likes": 8,
      "rating": 1,
      "create_time": "2020-03-01",
      "update_time": "2020-03-01 11:11:11"
    }
  },
  {
    "model": "app_demo.Entry",
    "pk": 3,
    "fields": {
      "blog_id": 1,
      "headline": "java入门到精通",
      "body_text": "一门面向对象的编程语言...",
      "authors": [
        1,
        3
      ],
      "number_of_comments": 7,
      "number_of_likes": 8,
      "rating": 1,
      "create_time": "2020-03-01",
      "update_time": "2020-03-01 11:11:11"
    }
  },
  {
    "model": "app_demo.Entry",
    "pk": 4,
    "fields": {
      "blog_id": 2,
      "headline": "c语言入门到精通",
      "body_text": "Basic Combined Programming Language...",
      "authors": [
        2,
        3
      ],
      "number_of_comments": 4,
      "number_of_likes": 4,
      "rating": 1,
      "create_time": "2021-03-01",
      "update_time": "2021-03-01 11:11:11"
    }
  },
  {
    "model": "app_demo.Entry",
    "pk": 5,
    "fields": {
      "blog_id": 1,
      "headline": "汇编语言入门到精通",
      "body_text": "面向机器的程序设计语言...",
      "authors": [
        1,
        3
      ],
      "number_of_comments": 4,
      "number_of_likes": 0,
      "rating": 1,
      "create_time": "2022-03-01",
      "update_time": "2022-03-01 11:11:11"
    }
  }
]
  1. 加载数据到数据库
>>>python manage.py loaddata test_data.json

查询对象

获取所有对象(记录)

>>>Blog.objects.all()
<QuerySet [<Blog: 学习之家>, <Blog: 我爱编程>]>
>>>Blog.objects.first()
<Blog: 学习之家>
>>>Blog.objects.last()
<Blog: 我爱编程>
>>>Blog.objects.get(pk=1)
<Blog: 学习之家>
>>>Blog.objects.get(name='学习之家')
<Blog: 学习之家>
>>>Blog.objects.count()
2

通过过滤器检索指定对象

  • all() 返回的 QuerySet 包含了数据表中所有的对象
  • filter(\kwargs)** 返回一个新的 QuerySet,包含的对象满足给定查询参数。
  • exclude(\kwargs)** 返回一个新的 QuerySet,包含的对象 满足给定查询参数。

image-20220310165630076

>>>Entry.objects.filter(headline='c语言入门到精通')
<QuerySet [<Entry: c语言入门到精通>]>

**基本的查询关键字参数遵照 field__lookuptype=value。(有个双下划线) **

字符串类型字段:__startswith,__endswith,__contains
>>>Entry.objects.filter(headline__startswith='c语言')
<QuerySet [<Entry: c语言入门到精通>]>
>>>
>>>Entry.objects.filter(headline__endswith='精通')
<QuerySet [<Entry: 汇编语言入门到精通>, <Entry: c语言入门到精通>, <Entry: python入门到精通>, <Entry: php入门到精通>, <Entry: java入门到精通>]>
>>>
>>>Entry.objects.filter(headline__contains='精通').exclude(headline__contains='java')
<QuerySet [<Entry: 汇编语言入门到精通>, <Entry: c语言入门到精通>, <Entry: python入门到精通>, <Entry: php入门到精通>]>
时间类型字段:__year
>>>Entry.objects.filter(create_time__year=2021)
<QuerySet [<Entry: c语言入门到精通>]>
>>>
>>>Entry.objects.filter(create_time__year__lt=2021)
<QuerySet [<Entry: python入门到精通>, <Entry: php入门到精通>, <Entry: java入门到精通>]>
>>>
>>>Entry.objects.filter(create_time__year__lt=2021)[1:3]
<QuerySet [<Entry: php入门到精通>, <Entry: java入门到精通>]>
F()为模型指定字段
>>>from django.db.models import F
>>>Entry.objects.filter(number_of_comments__gt=F('number_of_likes'))
<QuerySet [<Entry: 汇编语言入门到精通>, <Entry: python入门到精通>, <Entry: php入门到精通>]>
>>>
>>>Entry.objects.filter(create_time__year=F('update_time__year'))
<QuerySet [<Entry: 汇编语言入门到精通>, <Entry: c语言入门到精通>, <Entry: python入门到精通>, <Entry: php入门到精通>, <Entry: java入门到精通>]>
查询 JSONField

image-20220314135133257

>>>AuthorDetail.objects.filter(settings__collaps=True)
<QuerySet [<AuthorDetail: 张三>, <AuthorDetail: 王五>]>
>>>
>>>AuthorDetail.objects.filter(settings__ext_info__lang='zh-hans')
<QuerySet [<AuthorDetail: 张三>]>
>>>
>>>AuthorDetail.objects.filter(settings__ext_info__focus__0='python')
<QuerySet [<AuthorDetail: 张三>]>
>>>
>>>AuthorDetail.objects.filter(settings__flag__isnull=True)
<QuerySet [<AuthorDetail: 张三>, <AuthorDetail: 李四>]>
>>>
>>>AuthorDetail.objects.filter(settings__has_key='flag')
<QuerySet [<AuthorDetail: 王五>]>
>>>
>>>AuthorDetail.objects.filter(settings__has_keys=['collaps','flag'])
<QuerySet [<AuthorDetail: 王五>]>
>>>
>>>AuthorDetail.objects.filter(settings__has_any_keys=['collaps','flag'])
<QuerySet [<AuthorDetail: 张三>, <AuthorDetail: 李四>, <AuthorDetail: 王五>]>
>>>
通过 Q 对象完成复杂查询

在类似 filter() 中,查询使用的关键字参数是通过 “AND” 连接起来的。如果你要执行更复杂的查询(例如,由 OR 语句连接的查询),你可以使用 Q 对象

Q 对象能通过 &| 操作符连接起来。当操作符被用于两个 Q 对象之间时会生成一个新的 Q 对象。

image-20220314144122125

>>>from django.db.models import Q
>>>Entry.objects.filter(Q(headline__startswith='java') | Q(headline__startswith='c语言'))
<QuerySet [<Entry: c语言入门到精通>, <Entry: java入门到精通>]>
>>>
>>>Entry.objects.filter(Q(headline__startswith='java') | Q(headline__startswith='c语言'),create_time__year__lt=2021)
<QuerySet [<Entry: java入门到精通>]>

跨关联查询:多对一关联模型

image-20220310172606215

image-20220314145011528

通过1模型的条件过滤获得关联的M模型实例列表

>>>Entry.objects.filter(blog__name='我爱编程')
<QuerySet [<Entry: c语言入门到精通>]>
>>>
>>>Entry.objects.filter(blog__name='学习之家')
<QuerySet [<Entry: 汇编语言入门到精通>, <Entry: python入门到精通>, <Entry: php入门到精通>, <Entry: java入门到精通>]>

通过M模型实例获取其关联的1模型对象

若模型有个 ForeignKey,该模型的实例能通过其属性访问关联(外部的)对象。

>>>e = Entry.objects.get(pk=2)
>>>e.blog
<Blog: 学习之家>

通过M模型的条件过滤获得关联的1模型实例列表

>>>Blog.objects.filter(entry__headline='python入门到精通')
<QuerySet [<Blog: 学习之家>]>

通过1模型实例获取其关联的M模型对象列表

若模型有 ForeignKey外键关联的模型实例将能访问 Manager,后者会返回第一个模型的所有实例。默认情况下,该 Manager 名为 FOO_setFOO 即源模型名的小写形式。例如 某个Blog实例对象blog,可通过blog.entry_set.all() 可获得该blog对应的所有Entry实例列表。

>>>blog = Blog.objects.get(pk=1)
>>>blog.entry_set.all()
<QuerySet [<Entry: 汇编语言入门到精通>, <Entry: python入门到精通>, <Entry: php入门到精通>, <Entry: java入门到精通>]>
>>>blog.entry_set.filter(headline='python入门到精通')
<QuerySet [<Entry: python入门到精通>]>

重写模型关联名称related_name

你可以在定义 ForeignKey 时设置 related_name 参数重写这个 FOO_set 名。例如,若修改 Entry 模型为 blog = ForeignKey(Blog, on_delete=models.CASCADE, related_name='entries'),前文示例代码会看起来像这样:

>>>blog = Blog.objects.get(pk=1)
>>>blog.entry_set.all()

add(obj1,** obj2, **…) 加入关联对象

image-20220314145011528

>>>blog = Blog.objects.get(pk=2)
>>>e = Entry.objects.get(pk=1)
>>>blog.entry_set.add(e)

create(**kwargs)创建关联对象

>>>blog = Blog.objects.get(pk=1)
>>>blog.entry_set.create(headline='重要思想理论',body_text='马克思思想...')
Add Entry success! headline:重要思想理论
<Entry: 重要思想理论>

remove(obj1,obj2,…) 删除关联对象

注意:remove()方法仅在Foreign Key对象设置了null=True时才存在

>>>blog = Blog.objects.get(pk=2)
>>>blog.entry_set.all()
<QuerySet [<Entry: c语言入门到精通>, <Entry: python入门到精通>]>
>>>e=Entry.objects.get(headline='python入门到精通')
>>>
>>>blog.entry_set.remove(e)
>>>
>>>blog.entry_set.all()
<QuerySet [<Entry: c语言入门到精通>]>

clear() 从关联对象集合删除所有对象

注意:clear()方法仅在Foreign Key对象设置了null=True时才存在

>>>blog.entry_set.all()
<QuerySet [<Entry: c语言入门到精通>]>
>>>
>>>blog.entry_set.clear()
>>>
>>>blog.entry_set.all()
<QuerySet []>

跨关联查询:多对多关联模型

多对多关联的两端均自动获取访问另一端的 API

不同点在为属性命名上:定义了 ManyToManyField 的模型使用字段名作为属性名,而 “反向” 模型使用源模型名的小写形式,加上 '_set' (就像反向一对多关联一样)

image-20220315090916505

观察数据库,可见数据库中,为多对多关联关系,创建了一张额外的关联表 entry_authors

image-20220321155113354

在定义了 ManyToManyField 的模型中,使用字段名获得关联对象模型Manager

>>>e=Entry.objects.get(id=3)
>>>e.authors.all()
<QuerySet [<Author: 张三>, <Author: 王五>]>

ManyToManyField的“反向”模型中,使用默认的源模型名的小写形式,加上 '_set' 获取管理对象模型Manager

>>>a = Author.objects.get(id=2)
>>>a.entry_set.all()
<QuerySet [<Entry: c语言入门到精通>, <Entry: php入门到精通>]>

跨关联查询:一对一关联模型

一对一关联与多对一关联非常类似。若在模型中定义了 OneToOneField,该模型的实例只需通过其属性就能访问关联对象。

image-20220323085823293

image-20220323090137924

定义了 OneToOneField的模型,通过其字段获取关联模型对象

>>>ad = AuthorDetail.objects.get(id=2)
>>>ad.author
<Author: 李四>
>>>ad.author.email
'lisi@126.com'

在反向查询中,以定义了 OneToOneField的模型类名小写作为字段获取关联模型对象

>>>a=Author.objects.get(id=2)
>>>a.authordetail
<AuthorDetail: 李四>
>>>a.authordetail.website
'http://lisi.com'

修改对象

通过实例对象修改

>>>e = Entry.objects.get(pk=1)
>>>e.headline
'python入门到精通'
>>>e.headline='python入门到放弃'
>>>e.save()
Add Entry success! headline:python入门到放弃

要将修改保存至数据库中已有的某个对象,使用 save()

通过QuerySet批量修改

>>>Entry.objects.filter(headline__contains='精通').update(number_of_likes=1000)
4

删除对象

通过实例对象删除

>>>e = Entry.objects.get(pk=1)
>>>e.delete()
(2, {'app_demo.Entry_authors': 1, 'app_demo.Entry': 1})

通过QuerySet批量删除

>>>Entry.objects.filter(headline__contains='精通').delete()
(12, {'app_demo.Entry_authors': 8, 'app_demo.Entry': 4})

数据库配置

SQLite

django默认使用SQLite数据库,settings.py中数据库配置如下

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}

MySQL

Django 支持 MySQL 5.7 及以上版本。

在使用MySQL数据库前,需在对应数据库服务器上创建相应的数据库,然后修改settings.py中的数据库连接配置

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'django_demo',  # 指定连接的数据库名称
        'USER': 'xxx',         # 数据库连接账号
        'PASSWORD': 'xxx',# 数据库连接密码
        'HOST': 'xxx.xxx.xxx.xxx', # 数据库连接地址
        'PORT': '3306'			# 数据库连接端口
    }
}

注意,使用mysql数据库,还需要安装mysql数据驱动如下

pip install mysqlclient

数据迁移同步

python manage.py makemigrations
python manage.py migrate

注意:一旦model发生了变化,都需要执行以上俩命令进行数据结构同步。


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。
My Show My Code