Django学习(二)- 模型
1. 数据库设置
系统默认的数据库是SQLite,但是如果你想使用其他的数据库也可以在设置里面更改数据库配置信息
我们找到DATABASES板块,接触过数据库的同学们应该就能知道这是什么,然后我们需要对里面的一些键值进行修改
系统默认配置:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
主要是修改这里的ENGINE和NAME,如果你使用SQLite以外的数据库,请确认是否需要事先建立数据库以及用户是否具有建立数据库、表的权利,并且这里需要加入一些额外设置比如USER、PASSWORD、HOST
-
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')
- 有关更多详细信息,请参阅参考文档
DATABASES
。
这里我们以mysql做示例演示一下设置
mysql设置:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'douban',
'USER': 'root',
'PASSWORD': '299521'
}
}
2. 时区/语言设置
TIME_ZONE
用作设置时区,LANGUAGE_CODE用作设置语言。默认都是非中文和国外时区,这里修改为中文,上海
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
3. 安装应用
承应前文最后的内容,当你创建好一个应用之后必须将应用安装至INSTALLED_APPS内才能够正常显示
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles'
]
另请注意INSTALLED_APPS
文件顶部的设置。它意指在这个Django实例中激活的所有Django应用程序的名称。应用程序可以在多个项目中使用,您可以打包和分发它们以供项目中的其他人使用。
默认情况下,INSTALLED_APPS
包含以下应用程序,所有这些应用程序都随Django一起提供:
-
django.contrib.admin
- 管理站点。你很快就会用到它。 -
django.contrib.auth
- 认证系统。 -
django.contrib.contenttypes
- 内容类型的框架。 -
django.contrib.sessions
- 会话框架。 -
django.contrib.messages
- 消息传递框架。 -
django.contrib.staticfiles
- 用于管理静态文件的框架。
4. 数据迁移
这里设置好数据库配置之后,如果你用到了其中的数据库,我们就会涉及到数据迁移的问题,这里有两个命令
python manage.py migrate
python manage.py makemigrations
python manage.py makemigrations这个命令是记录我们对models.py的所有改动,并且将这个改动迁移到migrations这个文件下生成一个文件例如:0001_initial.py文件,如果你接下来还要进行改动的话可能生成就是另外一个文件不一定都是0001文件,但是这个命令并没有作用到数据库,而当我们执行python manage.py migrate 命令时,这条命令的主要作用就是把这些改动作用到数据库也就是执行migrations里面新改动的迁移文件更新数据库,比如创建数据表,或者增加字段属性
迁移是Django如何存储对模型(以及数据库模式)的更改 - 它们只是磁盘上的文件。如果您愿意,可以阅读新模型的迁移; 这是文件 polls/migrations/0001_initial.py
。不要担心,每次Django制作它时都不会读它们,但是如果你想手动调整Django如何改变它们的话,它们的设计是人为可编辑的。
有一个命令可以为您运行迁移并自动管理您的数据库模式 - 这是被调用的migrate
,我们马上就会看到它 - 但首先,让我们看看迁移将运行的SQL。该 sqlmigrate
命令获取迁移名称并返回其SQL:
python manage.py sqlmigrate polls 0001
您应该看到类似于以下内容的东西(这里的示例是为PostgreSQL生成的,格式化处理过,与实际生成有出入)
BEGIN;
--
-- Create model Choice
--
CREATE TABLE "polls_choice" (
"id" serial NOT NULL PRIMARY KEY,
"choice_text" varchar(200) NOT NULL,
"votes" integer NOT NULL
);
--
-- Create model Question
--
CREATE TABLE "polls_question" (
"id" serial NOT NULL PRIMARY KEY,
"question_text" varchar(200) NOT NULL,
"pub_date" timestamp with time zone NOT NULL
);
--
-- Add field question to choice
--
ALTER TABLE "polls_choice" ADD COLUMN "question_id" integer NOT NULL;
ALTER TABLE "polls_choice" ALTER COLUMN "question_id" DROP DEFAULT;
CREATE INDEX "polls_choice_7aa0f6ee" ON "polls_choice" ("question_id");
ALTER TABLE "polls_choice"
ADD CONSTRAINT "polls_choice_question_id_246c99a640fbbd72_fk_polls_question_id"
FOREIGN KEY ("question_id")
REFERENCES "polls_question" ("id")
DEFERRABLE INITIALLY DEFERRED;
COMMIT;
另外一个需要注意的是这两个命令默认情况下是作用于全局,也就是对所有最新更改的models或者migrations下面的迁移文件进行对应的操作,如果要想仅仅对部分app进行作用的话 则执行如下命令:
python manage.py makemigrations appname,
python manage.py migrate appname,
#如果要想精确到某一个迁移文件则可以使用:
python manage.py migrate appname 文件名
5. 创建模型
模型是关于数据的单一,明确的真实来源。它包含您要存储的数据的基本字段和行为。Django遵循DRY原则。目标是在一个地方定义您的数据模型,并自动从中获取数据。
我们通过命令生成的迁移文件就来源自这里你建立的模型,类似对数据表字段的设计,我们还是承接前面的实例进行演示,我们在models.py里面建立两个模型Question和Choice
from django.db import models
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
日期时间。这告诉Django每个字段包含哪种类型的数据。 -
每个
Field
实例的名称(例如question_text
或pub_date
)是字段名称,采用机器友好格式。您将在Python代码中使用此值,并且您的数据库将使用它作为列名称。 -
您可以使用可选的第一个位置参数
Field
来指定一个人类可读的名称。这在Django的几个内省部分中使用,并且它兼作文档。如果未提供此字段,Django将使用机器可读的名称。在这个例子中,我们只定义了一个人类可读的名称Question.pub_date
。对于此模型中的所有其他字段,字段的机器可读名称就足以作为其可读的名称。这里可以只用模型名称加上字段名称两个字符串就能调用到具体对象Question.pub_date -
有些
Field
类需要参数。CharField
例如,要求你给它一个max_length
。这不仅在数据库模式中使用,而且在验证中使用,我们很快就会看到。 -
最后,请注意使用的定义关系
ForeignKey
。这告诉Django每个Choice
都与单个相关Question
。Django支持所有常见的数据库关系:多对一,多对多和一对一。
6. 激活模型
当我们设计好模型之后就需要将应用安装至INSTALLED_APPS内(这个需要时刻注意)并且利用前面提到的数据迁移命令对数据执行迁移
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
Rendering model states... DONE
Applying polls.0001_initial... OK
7. Python shell
利用Python shell可以使用Django为您提供的免费API。要调用Python shell,请使用以下命令:
python manage.py shell
manage.py 设置了DJANGO_SETTINGS_MODULE环境变量,这为Django提供了mysite/settings.py文件的Python导入路径。所以我们可以用python shell对代码进行测试
>>> 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)>]>
- 我们使用模型时必须先导入模型
- 我们在最后的查询过程中发现
<QuerySet [<Question: Question object (1)>]>
并不是这个对象的有用表示,如果没有进行处理的话之后我们在管理员页面直接去查看模型也会遇到这个问题,你无法从这样的字符串数据中知晓它具体是哪一条数据,所以这里衍生除了str方法来应对它
models.py:
from django.db import models
class Question(models.Model):
# ...
def __str__(self):
return self.question_text
class Choice(models.Model):
# ...
def __str__(self):
return self.choice_text
__str__()
向模型添加方法非常重要,不仅是为了您在处理交互式提示时的方便,还因为在Django自动生成的管理中使用了对象的表示。
这里我们也可以自行定义方法,如下:(仅作演示)
models.py:
import datetime
from django.db import models
from django.utils import timezone
class Question(models.Model):
# ...
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
之后我们可以再次去shell里面测试看看,就会发现,已经清晰明了不少了
>>> 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()
8. Django管理员
执行如下命令之后按照要求输入用户名以及密码和二次验证密码即可,之后也使用这个账户去管理员页面登录使用
python manage.py createsuperuser
image.png
但是这里去查看应该是看不到之前建立的模型内容的,因为我们还没有对模型进行注册,注册之后才能够让管理员知道我们的某个模型有一个管理页面,你们应该还没忘记我们的polls下还有个admin.py文件吧
image.pngadmin.py:
from django.contrib import admin
from .models import Question
admin.site.register(Question)
我们注册好之后就可以去页面上对管理数据进行查看,对英文不太熟悉的话可以参照之前的语言设置将语言设置为中文,页面大家应该一看就懂,可以直接对数据进行增删查改
9. 扩展
这里给大家扩展一个小技巧,如果觉得自己设计模型比较麻烦,也可以将建立好的数据表,有无数据都可以,直接同步到Django,我以前的文章也有概述,这里简单说明指令
在项目目录下执行:
python manage.py inspectdb #查看现有的模型文件(models.py)
python manage.py inspectdb > models.py #直接同步也没有问题