tags:

views:

341

answers:

1

I have a model that is something like this:

class Input(models.Model):
        details = models.CharField(max_length=1000)
        user = models.ForeignKey(User)

class Case(Input):
    title  = models.CharField(max_length=200)
    views = models.IntegerField()

    class Argument(Input):
        case = models.ForeignKey(Case)
        side = models.BooleanField()

A user can submit many arguments, per case. I want to be able to say how many users have submitted side=true arguments.

I mean if 1 user had 10 arguments and another user had 2 arguments (both side=true) I'd want the count to be 2, not 12.

Update:

I am using these methods on the Case object:

 def users_agree(self):
        return self.argument_set.filter(side=True).values('user').distinct()
    def users_disagree(self):
        return self.argument_set.filter(side=False).values('user').distinct()

My template code calls count() on them.

+3  A: 

Can you try:

Argument.objects.filter(side=True).values('case__user').distinct().count()

I think it does what you want. It issues one SQL query:

SELECT COUNT(DISTINCT "example_input"."user_id") FROM "example_argument" INNER JOIN "example_case" ON ("example_argument"."case_id" = "example_case"."input_ptr_id") INNER JOIN "example_input" ON ("example_case"."input_ptr_id" = "example_input"."id") WHERE "example_argument"."side" = True

Edit:

For this_case, get all users whose argument.side is True:

Argument.objects.filter(case__id=this_case.id, side=True).values('user').distinct()
Ayman Hourieh
Come to think of it, this should probably be done of the Case object. Like 'for this case show me how many users are on what side'
Johnd
I've added another query to address your new requirement. Can you try?
Ayman Hourieh
NameError: name 'this_case' is not defined
Johnd
Yeah, you said "for this case show ...". Replace this_case with the Case object for which you want users whose argument.side is True.
Ayman Hourieh
oh yea, sorrythis looks good
Johnd
I'm gong to call this on a instance of a Case object, so I don't think I'll need to specify a case
Johnd
If this is going to be in a Case method, replace this_case.id with self.id. By the way, I made a correction to the query.
Ayman Hourieh
def get_users_agree(self): return self.argument_set.filter(side=True).values('user').distinct()do you see an issue with this?
Johnd
This looks fine.
Ayman Hourieh