chatgpt说这个字段默认情况下: blank=False
,null=False
,也就是在数据库层面和表单层面都不能为空,我们不妨来测试一下在数据库层面是不是这样。
沿用博文 https://blog.csdn.net/wenhao_ir/article/details/135499962的配置。
模型代码如下:
from django.db import models
class User(models.Model):
username = models.CharField(max_length=4)
post_time = models.DateTimeField(verbose_name='发布时间')
# 其他字段...
def __str__(self):
return self.username
在运行命令 manage.py makemigrations 时,报下面的错:
You are trying to add a non-nullable field 'post_time' to user without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
2) Quit, and let me add a default in models.py
Select an option:
这个错误是由于你尝试向现有的数据库表(User
模型)中添加一个非空字段(post_time
字段),而该字段没有默认值。由于已有的数据库表中已经存在数据,Django 不知道如何为这个新字段提供默认值,因此它要求你在迁移过程中选择一种方式来解决这个问题。
在你的情况下,当你运行 manage.py makemigrations
时,Django 检测到你添加了一个非空字段 post_time
,但没有提供默认值。现在,Django 要求你选择一种方式来处理现有的数据。
你可以选择以下其中一种选项:
-
提供一个一次性的默认值 (1): 选择这个选项,Django 将为已存在的行设置一个默认值。你需要输入一个合适的默认时间值,该值将被应用到所有已有的行。
-
退出,并允许我在 models.py 中添加默认值 (2): 选择这个选项,你将手动在
models.py
中为新字段提供默认值,然后再运行makemigrations
。这样,Django 将在生成迁移文件时使用你提供的默认值。
在你的模型中,如果你希望 post_time
字段可以为空,你可以在模型字段中添加 null=True
和 blank=True
,并确保你的数据库迁移文件中有这些更改。这样,Django 将允许在数据库中存储 null
值,而不需要提供默认值。
from django.db import models
class User(models.Model):
username = models.CharField(max_length=4)
email = models.EmailField(unique=True)
post_time = models.DateTimeField(verbose_name='发布时间')
# 其他字段...
def __str__(self):
return self.username
如果你选择提供一次性的默认值,Django 会在生成的迁移文件中为你处理这个默认值。如果选择退出并手动在 models.py
中添加默认值,你需要在模型中设置默认值,然后再运行 manage.py makemigrations
。
从这里就可以看出默认情况下这个的确是非空值的。出现上面的原因是我是在原有的数据库表的基础上升级数据库表,这导致原来已经存在的一些行是没有数据的。原来的表的情况如下:
在这里我们选择 1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
需要输入一个默认值作为默认值,这里就根据建议用当前时间作为默认值,所以输入:timezone.now
从这一步的操作再一次应证了DateTimeField字段默认情况下是非空的。
然后执行迁移:
manage.py migrate
此时发现之前存在的行已经被添加默认值了:
此时我们手动插入一条数据,我们首先试下在插入时对于DateTimeField字段留空,看能不能正常运行:
# 创建一个用户
user = User(username='名字02', email='a003@example.com')
user.save()
可见,报错了,这里就证明了DateTimeField字段默认情况下是不能留空的。
正确的插入代码如下:
import os
import django
from django.utils import timezone
# 设置Dango运行时需要的环境变量DJANGO_SETTINGS_MODULE
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myshop.settings')
# 加载Django的设置
django.setup()
# 导入模型,注意必须在加载完Django的设置后下面的这句导入模型语句才能被正确执行
from app1.models import User
# # 清空User数据表
# User.objects.all().delete()
#
# print('Successfully written data to the database.')
time01 = timezone.datetime(2024, 1, 9, 14, 24, 23)
time01_aware = timezone.make_aware(time01) # 添加setting.py中设置的时区信息
# 创建一个用户
user = User(username='名字06', email='a006@example.com', post_time=time01_aware)
user.save()
运行效果如下:
但是这个时区是标准时区,如何设置为北京时间的时区呢?
经过我自己各种实测操作,都不行…
不过我觉得这一点对于我的网站来说并不重要,实在不行,可以把时间值取出来后,加上8个小时调整为北京时间嘛。
相关代码如下:
import os
import django
from datetime import timedelta
# 设置Dango运行时需要的环境变量DJANGO_SETTINGS_MODULE
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myshop.settings')
# 加载Django的设置
django.setup()
# 导入模型,注意必须在加载完Django的设置后下面的这句导入模型语句才能被正确执行
from app1.models import User
# # 清空User数据表
# User.objects.all().delete()
#
# print('Successfully written data to the database.')
# 查询并获取id为9的行
user_instance = User.objects.get(id=9)
# 获取post_time字段的值
post_time_value = user_instance.post_time
# 假设 post_time_value 是你从数据库中获取到的 UTC 时间
utc_time = post_time_value
# 添加8小时
beijing_time = utc_time + timedelta(hours=8)
# 打印结果或进行其他操作
print(beijing_time)
运行效果如下: