Django视图返回过时的数据,服务器重启后已修复

时间:2018-06-27 18:25:37

标签: django database postgresql orm

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

我有一个视图(Django REST框架),该视图给出了奇怪的行为。

该视图列出了表中最近记录的日期。记录始终每分钟多次添加到此表中。我没有在此视图上实现任何缓存。

今天我观察到以下情况:

  • 生产服务器上的视图正在返回陈旧数据(两天前的最新数据)
  • 在本地开发服务器上的视图(连接到相同的远程数据库)返回了新鲜数据
  • 在生产服务器上运行的./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',)

在Gunicorn工作人员的视图序列化程序中调用方法get_data时,将返回陈旧数据。数据到工人开始工作为止都是过时的。

从新的辅助进程或新的shell实例调用时,get_data方法不会返回陈旧的数据。

1 个答案:

答案 0 :(得分:2)

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

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
    }