2012-06-09 2 views
0

MyISAM으로 MySQL에서 실행되는 Django에서 Queryset의 Count 주석이 잘못된 결과를 반환합니다. 나는 SQL 문을 살펴 봤으며 MySQL 또는 Django 코드에 문제가 있는지 알 수 없다.Django Annotate Count로 MySQL에서 Count를 생성하면 잘못된 외부 결과로 인해 Count가 생성됩니다.

장고 모델 :

class Resource(models.Model): 
    ... 
    voters = models.ManyToManyField(User, related_name="resources") 

코드 :

resources = Resource.objects.filter(
    ... 
).annotate(
    votes=models.Count('voters') 
).order_by('-votes') 
print resources.query 

SQL 인쇄 :

SELECT 
..., 
COUNT(`app_resource_voters`.`user_id`) AS `votes` 
FROM `app_resource` 
... 
LEFT OUTER JOIN `app_resource_voters` 
ON `app_resource`.`id` = `app_resource_voters`.`resource_id` 
... 

테스트에 phpMyAdmin에서 쿼리의 효과에 뭔가 투표에 대한 잘못된 값을 반환 . 유권자의 수와 자원에있는 다른 속성에 대한 ForeignKey 연관의 수를 곱한 값을 반환합니다 (매우 혼란 스럽습니다). Django와 SQL이 올바른지, 이것이 MySQL의 문제라는 것을 의미합니까? MyISAM이 아닌 다른 것으로 바꾸거나 PostgreSQL로 바꾸는 것을 권할 것입니까?

답변

0

해결 방법으로 사용할 수있는 다른 두 가지 가능성이 있습니다.

첫 번째 것은 더 간단하지만 덜 효율적입니다. Resource 모델에서 메소드 또는 속성을 만듭니다.

class Resource(models.Model): 
    ... 

    @property # or @django.utils.functional.cached_property 
    def votes(self): 
     return self.voters.count() 

두번째 extra() 사용하는 것이다

resources = Resource.objects.filter(
    ... 
).extra(
    select={ 
     'votes': 'SELECT COUNT(*) FROM app_resource_voters WHERE app_resource.id = app_resource_voters.resource_id' 
    }, 
).order_by('-votes') 
+0

장고 오피스 [추천 (https://docs.djangoproject.com/en/dev/topics/db/aggregation/#generating-aggregates -for-each-item-in-a-queryset)은 질문과 마찬가지로 m2m 관계의 항목을 계산하는 것과 같은 방식입니다. 그들은 또한 틀린가? – DrTyrsa

+0

흠 맞아. 나는 그것을 몰랐다. 내 대답을 편집해야합니다. 이 경우 SQL에'GROUP BY app_resource.id' 절이 있어야합니다. – Maccesch

+0

추가 작업. 실제 생성 된 쿼리 세트는 거대하므로'@ property' 메소드는 사용하지 않았습니다. 코드를 조금 확장하기 위해'model._meta.db_table'을 통해 테이블 ​​이름을 자동으로 생성하는 방법이 있지만 m2m 테이블에 대해이 데이터를 가져 오는 방법을 잘 모르겠습니다. @DrTyrsa, 몇 가지 추가 필터를 추가 할 때까지 설명서의 작동 방식이 갑작스럽게 중단되었습니다. 여분의 절을 통해 이런 식으로 고정되었습니다. – garromark

관련 문제