【问题标题】:Django view returning stale data, fixed after server restartDjango 视图返回陈旧数据,在服务器重启后修复
【发布时间】:2018-12-06 17:33:28
【问题描述】:

我有一个带有 postgresql 数据库的 Django 网络服务器。

我有一个显示奇怪行为的视图(Django REST 框架)。

视图列出了表格中最新记录的日期。每分钟将记录多次添加到此表中。我没有在这个视图上实现任何缓存。

今天我观察到以下几点:

  • 生产服务器上的视图返回过时数据(2 天前的最新数据)
  • 本地开发服务器上的视图(连接到同一个远程数据库)返回新数据
  • 在生产服务器上运行的./manage.py shell 中的视图返回了新数据
  • 两天前我没有重启过生产服务器
  • 今天重新启动生产服务器后,视图中的数据又是新鲜的
  • 30 分钟后,数据现在已过期 30 分钟

这可能是什么原因造成的?为什么我必须刷新与数据库的连接才能获取新数据?

相关代码:

# models.py
class MyModel(models.Model):
    name = models.CharField(max_length=255)

    def get_data(self,
            start_date=timezone.now()-timedelta(hours=24),
            end_date=timezone.now()):
        latest_data = self.data.filter(date__gte=start_date, date__lte=end_date).latest('date')
        return {
            'latest': latest_data.date
        }


class MyOtherModel(models.Model):
    date = models.DateTimeField()
    foreign_key = models.ForeignKey(MyModel, related_name='data')


# views.py
class MyView(generics.ListAPIView):
    serializer_class = MySerializer
    def get_queryset(self):
        queryset = MyModel.objects.all()


# serializers.py
class MySerializer(serializers.ModelSerializer):
    data = serializers.DictField(source="get_data")

    class Meta:
        model = MyModel
        fields = ('data',)

get_data 方法在从 gunicorn 工作人员的视图序列化程序中调用时返回陈旧数据。数据在工作人员启动之日是陈旧的。

get_data 方法在从新工作进程或新 shell 实例调用时不会返回陈旧数据。

【问题讨论】:

  • 您在某处有模块或类级别的查询。但是由于您没有发布任何代码,我们无法帮助您。
  • @DanielRoseman 我一定会用代码更新我的问题。根据我的观察,在我看来,这似乎是一个数据库连接问题,而不是代码本身,因为查询在服务器的其他实例上返回了预期的结果。此外,“我们没有办法帮助你”有点粗鲁。当然,您无法帮助我提供所提供的信息,但这并不意味着其他人不能。另外,虽然我没有提供代码,但我确实提供了许多症状,可以为读者指出可能的原因。
  • 但是我已经告诉你问题出在哪里了。我只需要代码指出位置。
  • @DanielRoseman 代码已添加。最后的评论让我崩溃了。因此,您既“确切地告诉了我问题所在”又“无法帮助我”。好像有点矛盾。
  • 什么是self.data?这是在哪里设置的?

标签: django database postgresql orm


【解决方案1】:

发现问题。我正在获取时间范围的数据,并且该时间范围是在方法的默认参数中设置的。

Python 中的默认参数在方法声明时计算一次。

我需要改变:

def get_data(self,
        start_date=timezone.now()-timedelta(hours=24),
        end_date=timezone.now()):
    latest_data = self.data.filter(date__gte=start_date, date__lte=end_date).latest('date')
    return {
        'latest': latest_data.date
    }

收件人:

def get_data(self, start_date=None, end_date=None):
    if start_date is None:
        start_date = timezone.now()-timedelta(hours=24)
    if end_date is None:
        end_date = timezone.now()

    latest_data = self.data.filter(date__gte=start_date, date__lte=end_date).latest('date')
    return {
        'latest': latest_data.date
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-24
    • 1970-01-01
    • 2023-03-04
    • 1970-01-01
    • 2015-12-16
    • 1970-01-01
    • 2011-08-22
    • 2012-09-13
    相关资源
    最近更新 更多