带有参数的Django管理器

mccptt67  于 2023-06-25  发布在  Go
关注(0)|答案(2)|浏览(132)

我想在Django中创建一个管理器,用于过滤id和传感器。这是我的经理:

class BrokenDeviceManager(models.Manager):
    def get_queryset(self, device_id, sensor):
        return (
            super()
            .get_queryset()
            .filter(brokensensor__exact=device_id, brokensensor__sensor=sensor,)
        )

当在测试类中尝试此操作时:

Device.broken_objects.filter(
            device_id=device.id, sensor=Sensor.COUGHS
        ).count()

它给了我:

TypeError: get_queryset() missing 2 required positional arguments: 'device_id' and 'sensor'

也尝试了其他方法,没有成功。这是brokensensor类:

class BrokenSensor(models.Model):
    sensor = models.PositiveIntegerField(choices=Sensor.choices())
    device = models.ForeignKey(
        Device, on_delete=models.CASCADE, related_name="brokensensor"
    )

    def __str__(self):  # pragma: no cover
        return "pk{} - device: {} - sensor: {}".format(
            self.pk, self.device_id, self.sensor
        )
carvr3hs

carvr3hs1#

查看您的问题和您问题的评论部分的给定解决方案:

class BrokenDeviceManager(models.Manager):
    def broken_sensor_check(self, device_id, sensor):
        return (
            super(BrokenDeviceManager, self)
            .get_queryset()
            .filter(brokensensor__exact=device_id, brokensensor__sensor=sensor)
        )

它似乎可以完成这项工作,但是对于该解决方案,我相信更好的方法是使用QuerySet。这是一个更简单的接口,它扩展了链接方法,并允许您以任何您喜欢的顺序调用它。另外,Manager应该在没有特殊方法或参数的情况下工作,因为它的想法是在后台工作并自己完成所有的“魔术”,通常覆盖get_queryset()
因此,要使用Queryset,您必须首先声明一个Queryset及其方法,然后使用.as_manager()添加到模型中。

class BrokenDeviceQuerySet(models.query.QuerySet):

    def broken_sensor_check(self, device_id, sensor):
        return self.filter(brokensensor__exact=device_id, brokensensor__sensor=sensor)

class Device(models.Model):
    # your fields and stuff
    broken_objects = BrokenDeviceQuerySet.as_manager()

我看到你的解决方案的问题是它不允许链接,例如:Device.broken_objects.all().broken_sensor_check()不能用它来做。

yhived7q

yhived7q2#

对于那些寻找经理根据条件进行过滤的人来说,以下是我的解决方案:

class BrokenDeviceManager(models.Manager):
    has_device = DEFAULT_VALUE

    def __init__(self, has_device, *args, **kwargs):
        self.has_device = has_device
        super().__init__()

    def get_queryset(self, *args, **kwargs):
        if self.has_device:
           return super().get_queryset().exclude(device_id=None)
        return super().get_queryset().filter(device_id=None)

因此,您可以在模型上创建两个管理器,例如:

class BrokenSensor(models.Model):
    ...

    objects = models.Manager()
    w_device_objects = LayerManager(has_device=True)
    wo_device_objects = LayerManager(has_device=False)

然后打电话给

BrokenSensor.w_device_objects.all()
BrokenSensor.wo_device_objects.all()

这对我很有用,因为过滤器是外键的级联,所以我可以简化编写:

def get_queryset(self, *args, **kwargs):
   qs = super().get_queryset()
   if self.is_db:
      return qs.exclude(history__database_class_str=None)
   return qs.filter(history__database_class_str=None)

相关问题