简体   繁体   中英

Django queryset filter model attribute against other model attribute

I don't know if I made myself clear with this question title, but, heres my problem:

I have this model, which is just a transactional model:

class InstanceItemEvaluation(models.Model):
    instance = models.ForeignKey(Instance)
    item = models.ForeignKey(InstanceItem)
    user = models.ForeignKey(User)
    factor = models.ForeignKey(Factor)
    measure = models.ForeignKey(Measure)
    measure_value = models.ForeignKey(MeasureValue, null=True, blank=True)
    evaluated_at = models.DateTimeField(null=True, blank=True)

Here is a query I must run to only retrieve valid values from the database:

@staticmethod
def get_user_evaluations_by_instance(user, instance):
    qs = InstanceItemEvaluation.objects.filter(
        user=user, 
        instance=instance, 
        factor__is_active=True, 
        measure__is_active=True).exclude(
        factor__measure=None)
    return qs

The query set speaks for itself, I am just filtering the user, and the working instance and so on. This query set output this SQL:

SELECT "workspace_instanceitemevaluation"."id", 
       "workspace_instanceitemevaluation"."instance_id", 
       "workspace_instanceitemevaluation"."item_id", 
       "workspace_instanceitemevaluation"."user_id", 
       "workspace_instanceitemevaluation"."factor_id", 
       "workspace_instanceitemevaluation"."measure_id", 
       "workspace_instanceitemevaluation"."measure_value_id", 
       "workspace_instanceitemevaluation"."evaluated_at" 
  FROM "workspace_instanceitemevaluation" 
 INNER JOIN "measures_measure" ON ( "workspace_instanceitemevaluation"."measure_id" = "measures_measure"."id" ) 
 INNER JOIN "factors_factor" ON ( "workspace_instanceitemevaluation"."factor_id" = "factors_factor"."id" ) 
 WHERE ("measures_measure"."is_active" = True 
   AND "workspace_instanceitemevaluation"."user_id" = 1 
   AND "factors_factor"."is_active" = True 
   AND "workspace_instanceitemevaluation"."instance_id" = 5 
   AND NOT ("factors_factor"."measure_id" IS NULL));

So far so good. But now I need to put this clause on the query:

   AND "factors_factor"."measure_id" = "measures_measure"."id"

Which would mean I am only looking for measure values that are currently associated with my factors. Anyway, I tried to do something like this (look at the last filter ):

@staticmethod
def get_user_evaluations_by_instance(user, instance):
    qs = InstanceItemEvaluation.objects.filter(
        user=user, 
        instance=instance, 
        factor__is_active=True, 
        measure__is_active=True).exclude(
        factor__measure=None).filter(
        factor__measure=measure)
    return qs

But that doesn't even make sense. Now I am kinda stuck, and couldn't find a solution. Of course that's something I can do iterating the result and removing the results I don't need. But I am trying to figure out if it is possible to achieve this SQL query I mentioned using the Django queryset API.

I'm not sure if it will work in this case, but generally you can use F() objects for this.

from django.db.models import F
qs = InstanceItemEvaluation.objects.filter(
    user=user, 
    instance=instance, 
    factor__is_active=True, 
    measure__is_active=True).exclude(
    factor__measure=None).filter(
    factor__measure=F('measure_id'))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM