【问题标题】:Django TruncDate gives nullDjango TruncDate 给出 null
【发布时间】:2020-03-23 09:35:58
【问题描述】:

我正在使用 Django 2.2

我正在使用 Django 查询过滤记录,例如

from datetime import datetime
from django.db.models.functions import TruncDate

start_date = datetime.strptime('2020-02-01', '%Y-%m-%d').date()
end_date = datetime.strptime('2020-03-31', '%Y-%m-%d').date()

lead_list = LeadList.objects.all()

# Filter query
query = LeadListEntry.objects.filter(
    lead_list__in=lead_list
  )

# Filter by start date
query = query.filter(
    created__gte=start_date
  )

# Filter by end date
query = query.filter(
    created__lte=end_date
  )

# Annotate date
query = query.annotate(
     created_date=TruncDate('created')
   ).order_by(
     'created_date'
   ).values('created_date').annotate(
     **{'total': Count('created')}
   )

生成的SQL查询是

SELECT 
    DATE(CONVERT_TZ(`lead_generation_leadlistentry`.`created`, 'UTC', 'UTC')) AS `created_date`, 
    COUNT(`lead_generation_leadlistentry`.`created`) AS `total`
FROM `lead_generation_leadlistentry` 
WHERE (
    `lead_generation_leadlistentry`.`lead_list_id` IN (
        SELECT 
            U0.`id` FROM `lead_generation_leadlist` U0 
        WHERE 
            U0.`deleted` IS NULL
    )
    AND `lead_generation_leadlistentry`.`created` >= '2020-02-01 00:00:00' 
    AND `lead_generation_leadlistentry`.`created` <= '2020-03-31 00:00:00'
)
GROUP BY DATE(CONVERT_TZ(`lead_generation_leadlistentry`.`created`, 'UTC', 'UTC'))
ORDER BY `created_date` ASC

这在本地和登台服务器上表现不同

本地开发服务器

+--------------+-------+
| created_date | total |
| ------------ | ----- |
| 2020-02-25   | 15    |
| 2020-02-27   | 10    |
+--------------+-------+

暂存服务器

+--------------+-------+
| created_date | total |
| ------------ | ----- |
| null         | 15    |
+--------------+-------+

日期列是null

注意:Django 有USE_TZ=True 启用的时区

LeadListEntry模型

class LeadListEntry(models.Model):
    lead_list = models.ForeignKey(LeadList, on_delete=models.CASCADE, related_name='lead_list_entry')
    data = models.TextField(help_text='Lead List entry data. (JSON data)', blank=False)

    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)

【问题讨论】:

  • 请分享您的模型字段
  • 请检查我是否添加了模型字段。我认为它与模型字段无关,而应该是数据库中的错误,因为运行相同的 SQL 脚本在本地数据库中有效,但在暂存数据库中无效。

标签: python mysql django timezone


【解决方案1】:

这是用户遇到相同错误的解决方案

错误不在于 Django,而是在于 MySQL 数据库设置。

日期字段返回null,因为CONVERT_TZ 不起作用。这可能是因为 MySQL 数据库中没有时区数据。

要导入时区数据,请执行以下命令

mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql

导入后重启mysql服务器。

【讨论】:

    【解决方案2】:

    由于机器的DateTime不同,可能会出现本地到staging结果不同的问题,我之前在windows上开发但staging是ubuntu时得到了这个,结果strptime()日期参数不同并保留显示错误。

    对于日期过滤和代码示例,您不必创建日期对象,只需正确的字符串日期格式就足够了

    start_date = '2020-02-01'
    end_date = '2020-03-31'
    

    然后照常进行。

    我想做这样的事情,

    # As you only need LeadList id's for foreginkey filtering, this is more optimized
    lead_list = LeadList.objects.all().values_list('id')
    
    # Filter query
    query = LeadListEntry.objects.filter(
        lead_list__in=lead_list, created__date__gte = start_date, created__date__lte=end_date
      )
    

    按日期分组

    query = query.values('created__date').annotate(count=Count('created__date')).order_by('created__date')
    

    【讨论】:

    • 但是上面的 SQL 脚本在工作台中执行时,给出的结果与问题中给出的结果相同。这不是 MySQL 服务器的问题吗?
    • 您的解决方案仍然提供&lt;LeadListEntryQuerySet [{'created__date': None, 'count': 7}]&gt;created__date 为空。
    猜你喜欢
    • 1970-01-01
    • 2016-01-29
    • 2019-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-14
    • 2013-02-04
    • 2021-08-21
    相关资源
    最近更新 更多