V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
liulei281
V2EX  ›  Python

请教一个 Django ORM 中日期字段做比较的问题

  •  
  •   liulei281 · 2020-01-17 09:01:23 +08:00 · 4454 次点击
    这是一个创建于 1774 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有这样一个 Model:

    class InfoModel:
        title = models.CharField('标题', max_length=50)
        create_date = models.DateField('创建日期', auto_now_add=True)
        expiration = models.IntegerField('有效期 x 天', default=0)
    

    要查询当前时间点未过期的的数据.

    17 条回复    2020-01-17 18:36:27 +08:00
    chenstack
        1
    chenstack  
       2020-01-17 09:05:44 +08:00
    为什么不存一个到期日期的字段呢
    liulei281
        2
    liulei281  
    OP
       2020-01-17 09:10:12 +08:00
    @chenstack 历史遗留问题, 只能刚正面-_-!
    chenstack
        3
    chenstack  
       2020-01-17 09:24:30 +08:00
    Django 的 F 表达式可以在查询或更新时对字段做加、减、乘、除、取模和幂运算等算术操作,但你的字段是日期类型的,没有这样做过,我搜到了类似这样的回答 https://stackoverflow.com/questions/38703016/what-is-the-replacement-for-datemodifiernode-in-new-versions-of-django
    晚点我自己试一下
    liulei281
        4
    liulei281  
    OP
       2020-01-17 09:39:05 +08:00
    @chenstack 这些我昨天查了很多, 没找到合适的办法. 我目前想到的解决办法:
    InfoModel.objects.annotate(delta=ExpressionWrapper((Value(now().date(), DateField()) - F('display_date')) / (24 * 60 * 60 * 1000 * 1000), output_field=IntegerField())).filter(expiration__gte=delta)
    看着很恶心...
    liulei281
        5
    liulei281  
    OP
       2020-01-17 09:40:11 +08:00
    @chenstack 如果能调用 Mysql 的 CURDATE, TODAYS, INTERVAL 之类的方法就会简单很多, 但是貌似 django 不支持
    SpencerCJH
        6
    SpencerCJH  
       2020-01-17 09:44:05 +08:00
    @liulei281 谨慎使用这些函数,在 where 上不正确使用会走不了索引的吧
    SjwNo1
        7
    SjwNo1  
       2020-01-17 09:55:16 +08:00
    表数据量不大建议刷表 expiration 改成到期时间 后续 query
    Vegetable
        8
    Vegetable  
       2020-01-17 09:57:33 +08:00
    不是,不说 orm,你这个查询我用 sql 也不会写,写出来也不知道能不能走索引,也不知道会不会每行都计算一个 now
    ytymf
        9
    ytymf  
       2020-01-17 10:37:43 +08:00
    换个思路吧,不追求在数据库一次性返回好,把判断过期放在数据库外做,效率应该不会差特别多, 内存得注意。不知道数据库表有多大呢?
    伪代码,胡写的。
    resultList= []
    for each in InfoModel.objects.all():
    if datetime.now()-each.expiration < each.create_date:
    resultList.append()
    ytymf
        10
    ytymf  
       2020-01-17 10:38:25 +08:00
    resultList.append(each),写错了
    lonelinsky
        11
    lonelinsky  
       2020-01-17 10:46:58 +08:00
    1. data migration
    2. raw SQL

    :-)
    izoabr
        12
    izoabr  
       2020-01-17 10:55:52 +08:00
    你干脆加一个 model,两个字段,第一个字段关联 InfoModel,第二个字段到期时间。
    第一个字段做主键,第二个字段自动生成,可以直接写到 class 里。
    然后 Super 一下 InfoModel 的 create 方法,顺路去创建一个你的新 model 记录。
    daya
        13
    daya  
       2020-01-17 11:06:52 +08:00
    计算出当前日期跟创建日期相差多少天,然后跟有效期存的天数比较大小不行吗
    bogun
        14
    bogun  
       2020-01-17 14:07:09 +08:00
    存成日期格式,建表加上索引。可以参考 django session 的过期机制实现
    Jammar
        15
    Jammar  
       2020-01-17 15:53:57 +08:00
    写个脚本,计算一下剩余日期重新建议一个表,这个就删了吧
    oaix
        16
    oaix  
       2020-01-17 15:54:48 +08:00
    在 sql 层,可以使用 generated column,有个明显的优势就是可以在它上面建索引。
    wd
        17
    wd  
       2020-01-17 18:36:27 +08:00 via iPhone
    你加一个自定义的计算字段,然后根据那两个字段产生?另外,如果已经知道原来设计不合理就想想怎么改吧,继续往屎堆拉屎只能让他变得更难清理。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1259 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 18:06 · PVG 02:06 · LAX 10:06 · JFK 13:06
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.