一个让人们查看和投票的公共站点。
一个让你能添加、修改和删除投票的管理站点。
本博客参考官方文档建立数据库部分:参考链接
项目环境:python
==3.8.10, Django
==3.2.6
首先,恢复上一步的工作,用于复习和准备环境:
python -m django --version # 查看Django版本
# cd 到一个你想放置你代码的目录后,执行
django-admin startproject mysite #在当前目录下创建一个 mysite 目录
# 在外层mystie目录,执行
python manage.py runserver #启动 Django 自带的用于开发的简易服务器
此时可以访问页面: http://127.0.0.1:8000/
注意,不是https
# cd到外层mystie目录
python manage.py startapp polls #创建一个polls应用,此时有了目录
定义一个 Django 中最简单的视图。打开 polls/views.py ,把下面这些 Python 代码输入进去:
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello, world. You're at the polls index.")
为了看见它,我们需要将一个 URL 映射到它(也就是URLconf)。新建 polls/urls.py 文件,然后打开,输入如下代码:
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
]
为了登记这个映射,还要在根 URLconf 文件中指定我们创建的 polls.urls 模块。打开 mysite/urls.py 文件,插入一个 include()来引用上面的URLconf, 如下:
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path('polls/', include('polls.urls')),
path('admin/', admin.site.urls),
]
注意,list中2个次序很重要.
python manage.py runserver
浏览器访问http://localhost:8000/polls/
注意,不是 http://localhost:8000/
数据库配置参照另一篇博文:0322Django连接mysql数据库
Python 内置 SQLite,本次使用 SQLite 数据库.
TIME_ZONE = 'Asia/Shanghai'
文件头部的 INSTALLED_APPS 设置项:
这里包括了会在你项目中会启用的所有 Django 应用。 它默认包括了多个 Django 的自带应用,如果你不需要某个或某些应用,可以注释或删除。
python manage.py migrate
写一个数据库驱动的 Web 应用的第一步是定义模型.Django 里,你只需要定义数据模型.
这里需要创建两个模型:问题 Question 和选项 Choice。
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)
其中:
Question,Choice被表示为 django.db.models.Model 类的子类,类变量如question_text,pub_date 等表示模型里的一个数据库字段,将作为数据库的列名。
类变量(字段)是 Field 类的实例 - 比如,字符字段被表示为 CharField ,日期时间字段被表示为 DateTimeField 。这将告诉 Django 每个字段要处理的数据类型。
pub_date = models.DateTimeField('date published')
中,使用可选的选项来为 Field 定义了一个人类可读的名字.
Choice中,我们使用ForeignKey
定义了一个关系。这将告诉 Django,每个 Choice 对象都关联到一个 Question 对象。
其中,某些 Field 类实例需要参数,例如 CharField 需要一个 max_length 参数。
Field也能够接收多个可选参数,在上面的例子中:我们将 votes 的 default 也就是默认值,设为0。
经由创建模型的代码,Django 可以:
为这个应用创建数据库 schema(生成 CREATE TABLE 语句)。
创建可以与 Question 和 Choice 对象进行交互的 Python 数据库 API。
INSTALLED_APPS
打开 mysite/settings.py
首先,为了在我们的工程中包含poll应用,我们需要在配置类 INSTALLED_APPS 中添加设置。
INSTALLED_APPS = [
'polls.apps.PollsConfig', # 增加的app声明
]
makemigrations polls
cmd运行命令: python manage.py makemigrations polls
,会看到类似于下面这样的输出
Migrations for 'polls':
polls/migrations/0001_initial.py
- Create model Question
- Create model Choice
运行 makemigrations 命令,Django 会检测你对模型文件的修改,并且把修改的部分储存为一次 迁移。模型的迁移数据,被储存在 polls/migrations/0001_initial.py 里.
python manage.py sqlmigrate polls 0001
其中,数据库表名为:
polls_question
,polls_choice
,即应用名(polls)和模型名的小写形式( question 和 choice)连接.
外键字段名后追加字符串 “_id” ,即question_id
migrate
再次运行 migrate 命令,在数据库里创建模型的数据表
python manage.py migrate
Django 通过在数据库中创建一个特殊的表 django_migrations, 来跟踪执行过哪些迁移. 这个 migrate 命令选中所有还没有执行过的迁移,并应用在数据库上 。也就是同步。
总结下,改变模型需要这三步:
编辑 models.py 文件,改变模型。
运行 python manage.py makemigrations 为模型的改变生成迁移文件。
运行 python manage.py migrate 来应用数据库迁移。
如上,数据库迁移被分解成生成和应用两个命令.
初试API部分请移步官方文档 : 初试API
cmd输入: python manage.py shell
这个命令会设置 Python 包的导入路径。
>>> from polls.models import Choice,Question
>>> Question.objects.all() # 用于查看现有的问题对象
<QuerySet []>
>>> from django.utils import timezone
>>> q = Question(question_text="What is new ?", pub_date = timezone.now()) #创建一个Question对象
>>> q.save() # 须显式保存,才能保存进数据库
>>> q.id # 保存后就有id了,此外还有字段名:question_text,pub_date
1
>>> q.question_text
'What is new ?'
>>> q.pub_date
datetime.datetime(2021, 8, 11, 8, 58, 38, 559463, tzinfo=<UTC>)
>>> q.question_text="what is up ?" #此时q还是q, id未变. 其实是更改question_text字段罢了
>>> q.save() # 保存更改
>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>]>
创建,检索对象参考:检索对象
为了更好的展示Question的内容,避免出现
这样的非人读的显示,我们对两个类(Question,Choice)增加魔法函数__str__():
from django.db import models
import datetime
from django.utils import timezone
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
重启python交互行,进行测试:
...\mysite>python manage.py shell
Python 3.8.10 | packaged by conda-forge | (default, May 11 2021, 06:25:23) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from polls.models import Choice,Question
>>> Question.objects.all() #显示发生了变化
<QuerySet [<Question: what is up ?>]>
>>> Question.objects.filter(id=1) # 相当于where语句,详情见码块外参考
<QuerySet [<Question: what is up ?>]>
>>> Question.objects.get(id=1) # 俺也一样
<Question: what is up ?>
>>> Question.objects.get(id=2)
Traceback (most recent call last):
...
polls.models.Question.DoesNotExist: Question matching query does not exist.
>>> Question.objects.get(pk=1) # 俺也一样,pk:primary key
<Question: what is up ?>
>>> Question.objects.filter(question_text__startswith='What') #这里用双下划线__调用了models.Model的对象方法startswith
<QuerySet [<Question: what is up ?>]>
>>> from django.utils import timezone
>>> current_year = timezone.now().year #这是一个struct_time对象吧
>>> current_year
2021
>>> Question.objects.get(pub_date__year=current_year) # 可见DateTimeField是类似于struct_time的
<Question: what is up ?>
>>> q = Question.objects.get(id=1)
>>> q.was_published_recently() # 自定义方法,判断是一天内发布的不?
True
>>> q.choice_set.all() # 查看问题的选项,暂时没有,注意: 主表查询次表
<QuerySet []>
>>> q.choice_set.create(choice_text='Not Much',votes=0) # 创建选项,4个
<Choice: Not Much>
>>> q.choice_set.create(choice_text='The Sky',votes=0)
<Choice: The Sky>
>>> q.choice_set.create(choice_text='Just Soso',votes=0)
<Choice: Just Soso>
>>> c =q.choice_set.create(choice_text='Just Soso',votes=0)
>>> c.question # 查该选项隶属的问题, 注意: 次表查询主表
<Question: what is up ?>
>>> q.choice_set.all() # 可以查到了,q问题有4个选项
<QuerySet [<Choice: Not Much>, <Choice: The Sky>, <Choice: Just Soso>, <Choice: Just Soso>]>
>>> q.choice_set.count()
4
>>> Choice.objects.filter(question__pub_date__year=current_year) # 次表join主表来查询,返回pub_date在current_year发布的question的Choice对象
<QuerySet [<Choice: Not Much>, <Choice: The Sky>, <Choice: Just Soso>, <Choice: Just Soso>]>
>>> c2 = q.choice_set.filter(choice_text__startswith='Just') # 查q的选项中以Just开头的
>>> c2
<QuerySet [<Choice: Just Soso>, <Choice: Just Soso>]>
>>> c2.delete() #返回一个元组,分别指示删除的选项数,和剩余的部分
(2, {'polls.Choice': 2})
>>> q.choice_set.count()
2
制定 SQL WHERE 子句, QuerySet 方法 filter(), exclude() 和 get()等详细参考:字段查询
cmd执行: python manage.py createsuperuser
然后,会自动跳出问题,依次填用户名,邮件地址,密码和确认一次.
首先启动服务: cmd执行 python manage.py runserver
然后,转到本地域名的admin目录:http://127.0.0.1:8000/admin/
登录,显示组和用户。它们是由 django.contrib.auth 提供的,这是 Django 开发的认证框架。
为了显示Question对象,我们需要更改polls.admin.py文件:
from django.contrib import admin
from .models import Question
admin.site.register(Question)
然后就可以看到Question选项卡了.这是一个管理页面,由网站管理员使用的.
生成一个用户添加,修改和删除内容的后台是一项缺乏创造性和乏味的工作。因此,Django 全自动地根据模型创建后台界面。
埋下Bug钥匙~后续可能用到:
在进行数据迁移前,可以试试运行 python manage.py check ;这个命令帮助你检查项目中的问题,并且在检查过程中不会对数据库进行任何操作。参考