【问题标题】:Django: Please help with this querysetDjango:请帮助处理这个查询集
【发布时间】:2010-10-09 18:32:19
【问题描述】:

我有一个 Django 模型,如下所示,我用它来跟踪哪些 IP 地址访问了我的网站以及何时访问。

class Visit(models.Model):
    created         = models.DateTimeField(default=datetime.utcnow)
    ip              = models.IPAddressField(editable=False)

我想在这个模型上编写一个方法,返回来自特定 IP 的最后 100 次访问的天数。来自 IP 的一天(小时等)内的多次访问都算作单独访问。因此,如果有人在过去 2 天内访问该站点 100 次,它将返回 2,在过去 8 天内访问 100 次,将返回 8,以此类推。

【问题讨论】:

    标签: django django-models django-queryset


    【解决方案1】:

    您可能希望将 created_on 的 default= 更改为 auto_now_add,因为如果您使用的是开发服务器以外的服务器,则 d​​atetime.utcnow 不会更新:

    class Visit(models.Model):
        created         = models.DateTimeField(auto_now_add=True,editable=False)
        ip              = models.IPAddressField(editable=False)
    
    from datetime import datetime
    def days_for_100(ip_addr):
      now = datetime.now()
      dates = Visit.objects.filter(ip=ip_addr)
      if dates.count()<100:
        latest = dates.latest('-created')
      else:
        latest = dates.dates('created','day',order='DESC')[99]
      return (now-latest).days # timedelta.days
    

    这将返回第 100 次访问发生前的天数(如果访问次数少于 100,则返回第一次访问发生的时间)

    【讨论】:

    • 我尝试了这个(在将 created_on 更改为 created 之后),但出现列表索引超出范围错误。关于 auto_add_now 我使用自定义的 save() 方法,所以希望这没问题。
    • 自定义 save() 应该可以工作,但使用 Django 的 auto_now_add 代码可以减少您必须维护/测试的代码量。如果您收到超出范围的错误,那是因为该 IP 未访问 100 次,我将对其进行编辑以确保不会发生错误。
    • 感谢您尝试修复它。该 IP 有超过 600 次访问,所以不知道为什么会出现错误。我已经尝试了新代码,但它仍然给出错误。这次:无效的 order_by 参数:['--created']。
    • 这可能是由放置两个破折号引起的,或者如果这是 SO 上的拼写错误而不是代码中的错字,则可能是 DateQuerySets 的未记录问题,这意味着无法获得最新的( ) 之一。无论哪种方式,我都再次修改了代码以确保 .latest() 仅在普通 QuerySet 上调用。
    • 谢谢法赫姆。不幸的是它仍然没有工作。有机会我会进一步调查,现在可能要到下周。
    【解决方案2】:

    一种简单的方法是获取一个 IP 地址的最后 100 个访问对象,并计算其中唯一的 created 对象的数量。

    def num_of_dates(ip_addr)    
        dates = [v.created for v in Visit.objects.filter(ip=ip_addr).order_by('-created')[0:100]]
        unique_dates = set(dates)
        return len(unique_dates)
    

    【讨论】:

    • 谢谢,这看起来几乎是正确的。但是,它总是返回 100 而不是天数。我怀疑这是因为 created 是一个 DateTime 字段,所以每个日期都是唯一的。
    • 您可以从 DateTime 对象形成 Date 对象,以获取唯一日期而不是唯一时间戳。或者你可以按照@fahhem 的解决方案,看起来更整洁。
    猜你喜欢
    • 1970-01-01
    • 2011-01-06
    • 2021-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-15
    • 2012-07-18
    • 1970-01-01
    相关资源
    最近更新 更多