【问题标题】:How to change a model after creating a ModelViewset?创建 ModelViewset 后如何更改模型?
【发布时间】:2021-07-06 16:13:11
【问题描述】:

我正在使用 django rest 框架创建一个 API。 但是当我已经创建了关联的 ModelViewset 时,每次想修改模型时都会遇到问题。

例如,我有这个模型:

class Machine(models.Model):
    name = models.CharField(_('Name'), max_length=150, unique=True)
    provider = models.CharField(_("provider"),max_length=150)
    build_date = models.DateField(_('build date'))
    category = models.ForeignKey("machine.CategoryMachine",
                                 related_name="machine_category",
                                 verbose_name=_('category'),
                                 on_delete=models.CASCADE
                                )
    site = models.ForeignKey(
        "client.Site",
        verbose_name=_("site"),
        related_name="machine_site",
        on_delete=models.CASCADE
    )

    class Meta:
        verbose_name = _("Machine")
        verbose_name_plural = _("Machines")

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse("Fridge_detail", kwargs={"pk": self.pk})

还有这个视图集:

class MachineViewSet(viewsets.ModelViewSet):
    """
    A simple ViewSet for listing or retrieving machine.
    """
    permission_classes = [permissions.IsAuthenticated]
    
    serializer_class = MachineSerializer
    queryset = cache.get_or_set(
                        'machine_machines_list',
                        Machine.objects.all(),
                        60*60*24*7
                    )
    
    @swagger_auto_schema(responses={200: MachineSerializer})
    def list(self, request):
        serializer_context = {
            'request': request,
        }
        queryset = cache.get_or_set(
            'machine_machines_list',
            Machine.objects.all(),
            60*60*24*7
        )
        serializer = MachineSerializer(queryset, many=True, context=serializer_context)
        return Response(serializer.data)

    @swagger_auto_schema(responses={404: 'data not found', 200: MachineSerializer})
    def retrieve(self, request, pk=None):
        serializer_context = {
            'request': request,
        }
        queryset = Machine.objects.all()
        machine = get_object_or_404(queryset, pk=pk)
        serializer = MachineSerializer(machine, context=serializer_context)
        return Response(serializer.data)

如果我想向我的模型添加一个字段,例如描述。当我运行命令python manage.py makemigrations 我得到错误: django.db.utils.ProgrammingError: column machine_machine.description does not exist

我必须注释我的视图集才能运行makemigrationsmigrate。 当我想修改模型时,如何避免每次查看视图集时都必须评论?

【问题讨论】:

  • 你能分享回溯吗?
  • 你会将查询集的结果缓存一周??你真的确定吗?您可能会以这种方式向用户显示陈旧的数据。
  • 我在结果改变时从缓存中删除数据(例如添加对象后...)

标签: django django-models django-rest-framework


【解决方案1】:

在您看来,您的班级中有以下行:

queryset = cache.get_or_set(
    'machine_machines_list',
    Machine.objects.all(),
    60*60*24*7
)

由于这一行出现在类声明中,而不是在类的方法中,它在创建/解释类时执行。这会导致它触发查询,因为需要评估查询集(pickling Querysets 将强制评估)以缓存它。这里的问题是您的模型尚未迁移并且您的查询失败。如果需要,您可以在 get_queryset 方法中重写该代码:

class MachineViewSet(viewsets.ModelViewSet):
    """
    A simple ViewSet for listing or retrieving machine.
    """
    permission_classes = [permissions.IsAuthenticated]
    
    serializer_class = MachineSerializer
    # Remove below lines
    # queryset = cache.get_or_set(
    #                     'machine_machines_list',
    #                     Machine.objects.all(),
    #                     60*60*24*7
    #                 )
    
    def get_queryset(self):
        return cache.get_or_set(
            'machine_machines_list',
            Machine.objects.all(),
            60*60*24*7
        )
    ...

但是这个实现存在严重缺陷!您正在为 缓存查询集。在该时间段内可能会出现大量新数据,而您实际上是在为用户提供陈旧数据。我建议您放弃这种缓存。此外,您似乎正在从您的视图中返回所有数据,请考虑对此进行某种过滤,以便此类内容需要更少的内存。

【讨论】:

  • 感谢您的回答。它工作得很好。对于一周缓存,我会根据需要删除密钥,例如在添加新机器之后。知道每月添加/修改的机器不会超过 1 或 2 台,一周的缓存似乎并不算太​​糟糕。
猜你喜欢
  • 2015-10-12
  • 2015-10-20
  • 1970-01-01
  • 2013-11-21
  • 1970-01-01
  • 2014-04-28
  • 2015-01-19
  • 2023-04-07
  • 1970-01-01
相关资源
最近更新 更多