3. 数据库SQLite——Django

1. 数据库配置

 (python3.8) [root@node8 mysite]# vim settings.py 
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }

使用其他数据库,需要安装合适的 database bindings ,然后改变设置文件中 DATABASES ‘default’ 项目中的键值:
ENGINE – 可选值有 ‘django.db.backends.sqlite3’,‘django.db.backends.postgresql’,‘django.db.backends.mysql’,或 ‘django.db.backends.oracle’。。
NAME - 数据库的名称。如果使用的是 SQLite,数据库将是一个文件,在这种情况下, NAME 应该是此文件的绝对路径,包括文件名。默认值 os.path.join(BASE_DIR, ‘db.sqlite3’) 将会把数据库文件储存在项目的根目录。
INSTALLED_APPS 设置项。包括了项目中启用的所有 Django 应用。应用能在多个项目中使用,你也可以打包并且发布应用。
INSTALLED_APPS 默认包含的Django 的自带应用:
django.contrib.admin – 管理员站点, 你很快就会使用它。
django.contrib.auth – 认证授权系统。
django.contrib.contenttypes – 内容类型框架。
django.contrib.sessions – 会话框架。
django.contrib.messages – 消息框架。
django.contrib.staticfiles – 管理静态文件的框架。
默认开启的某些应用需要至少一个数据表,所以,在使用他们之前需要在数据库中创建一些表。

(python3.8) [root@node8 mysite]# python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, 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 admin.0003_logentry_add_action_flag_choices... 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 auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying sessions.0001_initial... OK

2. 创建模型

Django 遵循 DRY Principle 。目标是需要定义数据模型,会自动从模型生成。本质上是个历史记录,Django 可以用它来进行数据库的滚动更新,通过这种方式使其能够和当前的模型匹配。
在这个投票应用中,需要创建两个模型:问题 Question 和选项 Choice。Question 模型包括问题描述和发布时间。Choice 模型有两个字段,选项描述和当前得票数。每个选项属于一个问题。

(python3.8) [root@node8 mysite]# cd polls/
(python3.8) [root@node8 polls]# ls
admin.py  apps.py  __init__.py  migrations  models.py  __pycache__  tests.py  urls.py  views.py
(python3.8) [root@node8 polls]# vim models.py 
from django.db import models
# Create your models here.
class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')
class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

每个模型被表示为 django.db.models.Model 类的子类。每个模型有类变量,表示模型里的数据库字段。
每个字段都是 Field 类的实例,字符字段 CharField ,日期时间字段DateTimeField 。
每个 Field 类实例变量的名字(例如 question_text 或 pub_date )也是字段名,所以最好使用对机器友好的格式。数据库会将ield 类实例变量作为列名。
如果某个字段没有提供此名称,Django 将会使用对机器友好的名称,也就是变量名。
定义某些 Field 类实例需要参数。CharField 需要一个 max_length 参数。参数的用处不止于用来定义数据库结构,也用于验证数据。
Field 也能够接收多个可选参数; votes 的 default 默认值设为0。
使用 ForeignKey 定义关系。,每个 Choice 对象都关联到一个 Question 对象。
Django 支持所有常用的数据库关系:多对一、多对多和一对一。

3. 激活模型

Django 应用是“可插拔”的。可以在多个项目中使用同一个应用。可以发布应用,应用并不会被绑定到当前安装的 Django 上。
PollsConfig 类写在文件 polls/apps.py 中,所以它的点式路径是 ‘polls.apps.PollsConfig’。在文件 mysite/settings.py 中 INSTALLED_APPS 子项添加点式路径。

(python3.8) [root@node8 mysite]# cd mysite/
(python3.8) [root@node8 mysite]# ls
asgi.py  __init__.py  __pycache__  settings.py  urls.py  views.py  wsgi.py
(python3.8) [root@node8 mysite]# vim settings.py 
INSTALLED_APPS = [
    'polls.apps.PollsConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]
(python3.8) [root@node8 mysite]#  python manage.py makemigrations polls
Migrations for 'polls':
  polls/migrations/0001_initial.py
    - Create model Question
    - Create model Choice

运行 makemigrations 命令,Django 会检测你对模型文件的修改,并且把修改的部分储存为一次 迁移。

迁移是 Django 对于模型定义的变化的储存形式 。储存在 polls/migrations/0001_initial.py 里。

执行qlmigrate 命令接收一个迁移的名称,然后返回对应的 SQL。

(python3.8) [root@node8 mysite]#  python manage.py makemigrations polls
Migrations for 'polls':
  polls/migrations/0001_initial.py
    - Create model Question
    - Create model Choice
(python3.8) [root@node8 mysite]#  python manage.py sqlmigrate polls 0001
BEGIN;
--
-- Create model Question
--
CREATE TABLE "polls_question" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "question_text" varchar(200) NOT NULL, "pub_date" datetime NOT NULL);
--
-- Create model Choice
--
CREATE TABLE "polls_choice" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "choice_text" varchar(200) NOT NULL, "votes" integer NOT NULL, "question_id" integer NOT NULL REFERENCES "polls_question" ("id") DEFERRABLE INITIALLY DEFERRED);
CREATE INDEX "polls_choice_question_id_c5b4b260" ON "polls_choice" ("question_id");
COMMIT;

4. 建表

运行 python manage.py check检查项目中的问题,检查过程中不会对数据库进行任何操作。

(python3.8) [root@node8 mysite]# python manage.py check
System check identified no issues (0 silenced).

运行 migrate 命令,在数据库里创建新定义的模型的数据表。

(python3.8) [root@node8 mysite]# python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
  Applying polls.0001_initial... OK

migrate 命令选中所有还没有执行过的迁移(Django 通过在数据库中创建一个特殊的表 django_migrations 来跟踪执行过哪些迁移)并应用在数据库上 ,也就是将你对模型的更改同步到数据库结构上。

迁移是非常强大的功能,在开发过程中持续的改变数据库结构而不需要重新删除和创建表 ,专注于使数据库平滑升级而不会丢失数据。
创建模型生成数据库需要三步:
编辑 models.py 文件,改变模型。
运行 python manage.py makemigrations 为模型的改变生成迁移文件。
运行 python manage.py migrate 来应用数据库迁移。
数据库迁移被分解成生成和应用两个命令是为了让你能够在代码控制系统上提交迁移数据并使其能在多个应用里使用;这不仅仅会让开发更加简单,也给别的开发者和生产环境中的使用带来方便。

5. 数据库 API

(python3.8) [root@node8 mysite]# python manage.py shell
Python 3.8.1 (default, Jul 20 2020, 17:33:01) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-39)] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)

>>> from polls.models import Choice, Question  # Import the model classes we just wrote.

# No questions are in the system yet.
>>> Question.objects.all()
<QuerySet []>

# Create a new Question.
# Support for time zones is enabled in the default settings file, so
# Django expects a datetime with tzinfo for pub_date. Use timezone.now()
# instead of datetime.datetime.now() and it will do the right thing.
>>> from django.utils import timezone
>>> q = Question(question_text="What's new?", pub_date=timezone.now())

# Save the object into the database. You have to call save() explicitly.
>>> q.save()

# Now it has an ID.
>>> q.id
1

# Access model field values via Python attributes.
>>> q.question_text
"What's new?"
>>> q.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)

# Change values by changing the attributes, then calling save().
>>> q.question_text = "What's up?"
>>> q.save()
 
# objects.all() displays all the questions in the database.
>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>]>

对于了解对象的细节没什么帮助,给 Question 和 Choice 增加 str() 方法。

(python3.8) [root@node8 polls]# vim models.py
from django.db import models
class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')
    def __str__(self):
        return self.question_text
    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)
    def __str__(self):
        return self.choice_text
>>> from polls.models import Choice, Question

# Make sure our __str__() addition worked.
>>> Question.objects.all()
<QuerySet [<Question: What's up?>]>

# Django provides a rich database lookup API that's entirely driven by
# keyword arguments.
>>> Question.objects.filter(id=1)
<QuerySet [<Question: What's up?>]>
>>> Question.objects.filter(question_text__startswith='What')
<QuerySet [<Question: What's up?>]>

# Get the question that was published this year.
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Question.objects.get(pub_date__year=current_year)
<Question: What's up?>

# Request an ID that doesn't exist, this will raise an exception.
>>> Question.objects.get(id=2)
Traceback (most recent call last):
    ...
DoesNotExist: Question matching query does not exist.

# Lookup by a primary key is the most common case, so Django provides a
# shortcut for primary-key exact lookups.
# The following is identical to Question.objects.get(id=1).
>>> Question.objects.get(pk=1)
<Question: What's up?>

# Make sure our custom method worked.
>>> q = Question.objects.get(pk=1)
>>> q.was_published_recently()
True

# Give the Question a couple of Choices. The create call constructs a new
# Choice object, does the INSERT statement, adds the choice to the set
# of available choices and returns the new Choice object. Django creates
# a set to hold the "other side" of a ForeignKey relation
# (e.g. a question's choice) which can be accessed via the API.
>>> q = Question.objects.get(pk=1)

# Display any choices from the related object set -- none so far.
>>> q.choice_set.all()
<QuerySet []>

# Create three choices.
>>> q.choice_set.create(choice_text='Not much', votes=0)
<Choice: Not much>
>>> q.choice_set.create(choice_text='The sky', votes=0)
<Choice: The sky>
>>> c = q.choice_set.create(choice_text='Just hacking again', votes=0)

# Choice objects have API access to their related Question objects.
>>> c.question
<Question: What's up?>

# And vice versa: Question objects get access to Choice objects.
>>> q.choice_set.all()
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
>>> q.choice_set.count()
3

# The API automatically follows relationships as far as you need.
# Use double underscores to separate relationships.
# This works as many levels deep as you want; there's no limit.
# Find all Choices for any question whose pub_date is in this year
# (reusing the 'current_year' variable we created above).
>>> Choice.objects.filter(question__pub_date__year=current_year)
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>

# Let's delete one of the choices. Use delete() for that.
>>> c = q.choice_set.filter(choice_text__startswith='Just hacking')
>>> c.delete()  

————Blueicex 2020/07/20 20:59 [email protected]

你可能感兴趣的:(Django)