使用一个Django模型中的对象来过滤另一个Django模型中的对象。

huangapple go评论52阅读模式
英文:

Use objects from one django model to filter objects from another django objects

问题

我正在进行我的研究项目。我有2个模型:

class RoutePoint(geo_models.Model):
    vehicle = models.ForeignKey(Vehicle, on_delete=models.CASCADE, null=False, blank=False,
                                related_name='routepoints')
    point = geo_models.PointField()
    datetime = models.DateTimeField()

class Travel(models.Model):
    vehicle = models.ForeignKey(Vehicle, on_delete=models.DO_NOTHING, null=False, blank=False,
                                related_name='travels')
    begin = models.DateTimeField()
    end = models.DateTimeField()

第一个模型包含了车辆的地理坐标点以及车辆到达那里的日期和时间信息。第二个模型包含了车辆行程的开始和结束时间。

我有一些带有两个字段的Curl请求 - start_dateend_date,让我们称其为报告的某种请求。

所以,首先我需要获取类似这样的数据:

SELECT vehicle_id, begin, end
FROM park_travel
WHERE begin > "2022-12-30" AND end < "2023-01-06"

我将其称为result

然后,我需要获取类似以下的数据:

SELECT vehicle_id, point, datetime
FROM park_routepoint
WHERE vehicle_id = result.vehicle_id
  AND datetime > result.begin
  AND datetime < result.end

而且,我需要在不使用原始SQL的情况下完成这个任务...

英文:

I'm doing my studying project. I have 2 models:

class RoutePoint(geo_models.Model):
    vehicle = models.ForeignKey(Vehicle, on_delete=models.CASCADE, null=False, blank=False,
                                related_name=&#39;routepoints&#39;)
    point = geo_models.PointField()
    datetime = models.DateTimeField()


class Travel(models.Model):
    vehicle = models.ForeignKey(Vehicle, on_delete=models.DO_NOTHING, null=False, blank=False,
                                related_name=&#39;travels&#39;)
    begin = models.DateTimeField()
    end = models.DateTimeField()

First one contains geopoints for vehicle and date and time for vehicle getting there.
Second one countains the begining and the ending of the rides for vehicles.

I'm having some curl request with two fields - start_date and end_date, let's call it some kind request for report.

So, at first I need to get something like this:

SELECT vehicle_id, begin, end
FROM park_travel
WHERE begin &gt; &quot;2022-12-30&quot; AND end &lt; &quot;2023-01-06&quot;

I'll call it result.

And after that i need to get something like:

SELECT vehicle_id, point, datetime
FROM park_routepoint
WHERE vehicle_id = result.vehicle_id
  AND datetime &gt; result.begin
  AND datetime &lt; result.end

And I have to do it without raw sql...

答案1

得分: 1

你可以使用双下划线符号F表达式在一个查询中完成这个操作:

from django.db.models import F

route_points = RoutePoint.objects.filter(
    vehicle__travel__begin__lt=F("datetime"),
    vehicle__travel__end__gt=F("datetime")
)

然后简单地迭代route_points查询集:

for route_point in route_points:
    print(route_point.vehicle, route_point.point, route_point.datetime)
英文:

You can do this in one query using double underscore notation and F expressions:

from django.db.models import F

route_points = RoutePoint.objects.filter(
    vehicle__travel__begin__lt=F(&quot;datetime&quot;),
    vehicle__travel__end__gt=F(&quot;datetime&quot;)
)

then simply iterate over the route_points queryset:

for route_point in route_points:
    print(route_point.vehicle, route_point.point, route_point.datetime)

答案2

得分: 0

你可以筛选Travel的Queryset:

start_date = '2022-12-30'
end_date = '2023-01-06'
travel_qs = Travel.objects.filter(begin__gt=start_date, 
end__lt=end_date).values('vehicle_id', 'begin', 'end')

现在你可以使用travel_qs来检索RoutePoint的点:

route_point_qs = RoutePoint.objects.filter(vehicle_id__in=travel_qs.values('vehicle_id'),
                                        datetime__gt=travel_qs.values('begin'),
                                        datetime__lt=travel_qs.values('end')).values('vehicle_id', 'point', 'datetime')
英文:

You can filter the Travel Queryset:

start_date = &#39;2022-12-30&#39;
end_date = &#39;2023-01-06&#39;
travel_qs = Travel.objects.filter(begin__gt=start_date, 
end__lt=end_date).values(&#39;vehicle_id&#39;, &#39;begin&#39;, &#39;end&#39;)

Now you can use travel_qs to retrieve the Points from RoutePoint:

route_point_qs = RoutePoint.objects.filter(vehicle_id__in=travel_qs.values(&#39;vehicle_id&#39;),
                                        datetime__gt=travel_qs.values(&#39;begin&#39;),
                                        datetime__lt=travel_qs.values(&#39;end&#39;)).values(&#39;vehicle_id&#39;, &#39;point&#39;, &#39;datetime&#39;)

答案3

得分: 0

我是这样做的:

    vehicles_with_dates = travels.values('vehicle_id').annotate(min_dt=Min('begin'), max_dt=Max('end'))
    route_points = RoutePoint.objects.filter(
        vehicle_id__in=vehicles_with_dates.values('vehicle_id'),
        datetime__gt=vehicles_with_dates.values('min_dt'),
        datetime__lt=vehicles_with_dates.values('max_dt')
    )

它完全正常工作,感谢Iqbal Hussain。

英文:

I did it like this:

    vehicles_with_dates = travels.values(&#39;vehicle_id&#39;).annotate(min_dt=Min(&#39;begin&#39;), max_dt=Max(&#39;end&#39;))
    route_points = RoutePoint.objects.filter(
        vehicle_id__in=vehicles_with_dates.values(&#39;vehicle_id&#39;),
        datetime__gt=vehicles_with_dates.values(&#39;min_dt&#39;),
        datetime__lt=vehicles_with_dates.values(&#39;max_dt&#39;)
    )

It worked perfectly fine, thanks to Iqbal Hussain.

huangapple
  • 本文由 发表于 2023年3月9日 12:35:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/75680467.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定