django初学教程 投票应用 02 使用数据库

django tutorial 02

数据库配置

默认使用内置SQLite的单数据库配置:

# mysite/settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'mydatabase',
    }
}

连接到其他数据库时,需要额外参数,如PostgreSQL:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'mydatabase',
        'USER': 'mydatabaseuser',
        'PASSWORD': 'mypassword',
        'HOST': '127.0.0.1',
        'PORT': '5432',
    }
}

参考 https://docs.djangoproject.com/zh-hans/3.2/ref/settings/#std:setting-DATABASES

INSTALLED_APPS 默认包括了以下 Django 的自带应用:

运行migrate命令,为INSTALLED_APPS中的每个应用创建数据表,进行数据库迁移:

python manage.py migrate

创建模型

投票应用需要Question问题和Choice选项两个模型,问题模型包括问题描述和发布时间,选项模型包括选项描述和当前得票数。每个选项属于一个问题。

用python类来描述:

# polls/models.py
from django.db import models


class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('data 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)

CharField:字符字段

DateTimeField:日期时间字段

IntegerField:整数字段

激活模型

先将poll应用安装到项目中:在installed_apps中添加polls.app.PollsConfig:

INSTALLED_APPS = [
    'polls.apps.PollsConfig', # 添加
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

运行makemigrations命令让django检测我们对模型文件的修改,并把修改的部分存储为一次迁移,存储在polls/migrations/0001_initial.py中:

python manage.py makemigrations polls

sqlmigrate命令接收一个迁移的名称,返回对应的SQL(用于查看,并未执行迁移):

python manage.py sqlmigrate polls 0001

输出(不同数据库输出也不一样,以下为默认SQLite):

运行migrate命令,应用数据库迁移:

python manage.py migrate

改变模型的三个步骤:

初试API

通过shell打开交互式python命令行:

python manage.py shell

注意: manage.py 会设置 DJANGO_SETTINGS_MODULE 环境变量,这个变量会让 Django 根据 mysite/settings.py 文件来设置 Python 包的导入路径,所以不要简单使用python命令进入命令行。

命令行:

>>> 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)>]>

给模型增加__str__()方法

# polls/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

给模型添加一个自定义方法

# polls/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)

继续命令行,处理Choice:

>>> 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()

介绍Django管理页面

创建一个管理员账号
python manage.py createsuperuser

密码过于简单会有提示:

启动开发服务器
python manage.py runserver

打开浏览器,网址http://127.0.0.1:8000/admin/,出现管理员登陆界面(LANGUAGE_CODE可以设置界面语言):

进入管理站点页面

使用创建的超级用户登录,可以看到Django管理页面的索引页:

组和用户是django.contrib.auth (django开发的认证框架)提供的。

向管理页面中加入投票应用

告诉管理问题Question对象需要一个后台接口,编辑polls/admin.py文件:

# polls/admin.py
from django.contrib import admin

from .models import Question

admin.site.register(Question)
体验便捷的管理功能

刷新页面,可以看到Question已经显示:

点击"Questions"→"What's up?"可以编辑问题对象:

页面的底部提供了几个选项:

  • 保存(Save) - 保存改变,然后返回对象列表。
  • 保存并继续编辑(Save and continue editing) - 保存改变,然后重新载入当前对象的修改界面。
  • 保存并新增(Save and add another) - 保存改变,然后添加一个新的空对象并载入修改界面。
  • 删除(Delete) - 显示一个确认删除页面。

这个Note提示时差问题,因为服务器默认TIME_ZONE设置时区是UTC,没有更改,时区列表在pytz的init文件中可以看到,改为"Asia/Shanghai"后刷新页面,时间正常:

通过点击now更改时间后,点击右上角history界面可以看到页面中列出了时间戳和进行修改操作的用户名:

这个时间46分过于巧合,又修改了一次,

下一部分学习为投票应用添加更多视图。

posted @ 2021-09-01 23:57  ikventure  阅读(74)  评论(0)    收藏  举报