根据他们在Django ORM中的最后一个孩子获取所有匹配记录?

时间:2016-12-07 12:06:59

标签: django python-3.x django-models django-orm

我在models.py中有这两个类:

class BaseObject(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    create_date = models.DateTimeField(auto_now_add=True)
    update_date = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ['create_date']


class Person(BaseObject):

    first_name = models.CharField(max_length=30, null=True, blank=True)
    last_name = models.CharField(max_length=30, null=True, blank=True)
    phone_number = models.CharField(max_length=15,unique=True)
    birthday = models.DateField(null=True, blank=True)
    email = models.EmailField(null=True, blank=True)

class Driver(Person):
    balance = models.PositiveIntegerField(null=True, blank=True)
    score = models.PositiveIntegerField(null=True, blank=True)

class Position(BaseObject):
    person = models.ForeignKey(Driver, on_delete=models.CASCADE)
    latitude = models.FloatField()
    longitude = models.FloatField()

正如您所看到的,每个驾驶员可以通过时间来拥有多个位置。
我想要一个使用Django ORM的查询,它给出了每个驱动程序的最后位置,想象我从客户端收到latitudelongitude并希望返回所有靠近的汽车。


我试过这个:

 radius = 5

 drivers = Driver.objects.filter(position__latitude__range=(data.get('latitude') - radius, data.get('latitude') + radius))\
                         .filter(position__longitude__range=(data.get('longitude') - radius, data.get('longitude') + radius))\

但问题是我根据他们的位置多次得到一个单独的驱动程序 现在我只想让司机得到他们最后的更新位置,而不是他们以前的位置。
谢谢

1 个答案:

答案 0 :(得分:2)

这是一个想法,以获得不同的驱动程序(这就是为什么我理解你并试图获得它)的最后位置。

首先,按照驾驶员位置排序,从最后一位到第一位 .order_by('-person__create_date',)

然后使用distinct以获得每个位置的驱动程序(最后一个):
.distinct()

这是第二个提议,让每个司机都有它的最后位置(感谢你的自动' create_date'和Django Annotate):

my_drivers = Driver.objects.all().annotate(last_position=Max('person__create_date'))

my_drivers[0].last_position
datetime.datetime(2016, 11, 17, 14, 25, tzinfo=<UTC>)

此处,my_drivers查询集中的每个项目都会有last_position属性。

最后,到@ mehrdad-pedramfar请求,想要从驱动程序中获取last_position

class Driver(Person):
    balance = models.PositiveIntegerField(null=True, blank=True)
    score = models.PositiveIntegerField(null=True, blank=True)

    def get_last_position(self):
        return Position.object.filter(person=self).order_by('-create_date').first()

我没有尝试过反对你的代码,但这个想法就在这里。每次调用它都会花费DB调用。 结果是当前Position的最后一个Driver对象:)