2011-09-19 11 views
8

मैं इस मॉडल मिल गया है:एक बार में कई रिश्तों से मेल खाने के लिए Django Manytomany प्रबंधक से कैसे पूछें?

class Movie(models.Model): 
    # I use taggit for tag management 
    tags = taggit.managers.TaggableManager() 

class Person(models.Model): 
    # manytomany with a intermediary model 
    movies = models.ManyToManyField(Movie, through='Activity') 

class Activity(models.Model): 
    movie = models.ForeignKey(Movie) 
    person = models.ForeignKey(Person) 
    name = models.CharField(max_length=30, default='actor') 

और मैं एक फिल्म एक और एक के रूप में ही अभिनेताओं है कि मैच के लिए करना चाहते हैं। Not one actor in common, but all the actors in common

इसलिए मैं यह नहीं चाहता:

# actors is a shortcut property 
one_actor_in_common = Movie.object.filter(activities__name='actor', 
              team_members__in=self.movie.actors) 

मैं कुछ है कि बनाना होगा "द मैट्रिक्स मैं" मैच "द मैट्रिक्स द्वितीय" क्योंकि वे का हिस्सा 'कीनू रीव्स' और 'लॉरेंस फिशबर्न' चाहते हैं, लेकिन मेल नहीं "स्पीड" क्योंकि वे 'केनु रीव्स' साझा करते हैं लेकिन 'लॉरेंस फिशबर्न' नहीं।

उत्तर

7

कई सारे प्रबंधक कई बार कई रिश्तों से मेल नहीं खा सकते हैं। डेटाबेस स्तर पर नीचे यह सब चुनने और समूह करने के लिए नीचे आता है।

तो स्वाभाविक रूप से एकमात्र सवाल यह है कि डेटाबेस उत्तर देने में सक्षम है यह है: इन व्यक्तियों को शामिल करने वाले अभिनय सक्रियताओं की सूची, उन्हें फिल्म द्वारा समूहित करें और केवल उन फिल्मों को दिखाएं जिनकी संख्या में अभिनय गतिविधियों की संख्या समान है।

ORM को अनूदित बात यह इस तरह दिखता है:

actors = Person.objects.filter(name__in=('Keanu Reaves', 'Laurence Fishburne')) 

qs = Movie.objects.filter(activity__name='actor', 
          activity__person__in=actors) 
qs = qs.annotate(common_actors=Count('activity')) 
all_actors_in_common = qs.filter(common_actors=actors.count()) 

क्वेरी इस पैदा करता है वास्तव में बुरा नहीं है:

SELECT "cmdb_movie"."id", "cmdb_movie"."title", COUNT("cmdb_activity"."id") AS "common_actors" 
    FROM "cmdb_movie" 
    LEFT OUTER JOIN "cmdb_activity" ON ("cmdb_movie"."id" = "cmdb_activity"."movie_id") 
    WHERE ("cmdb_activity"."person_id" IN (SELECT U0."id" FROM "cmdb_person" U0 WHERE U0."name" IN ('Keanu Reaves', 'Laurence Fishburne')) 
      AND "cmdb_activity"."name" = 'actor') 
    GROUP BY "cmdb_movie"."id", "cmdb_movie"."title", "cmdb_movie"."id", "cmdb_movie"."title" 
    HAVING COUNT("cmdb_activity"."id") = 2 

मैं भी एक छोटे से आवेदन है कि मैं इस परीक्षण के लिए किया है, लेकिन मुझे नहीं पता कि किसी को इसकी जरूरत है और न ही इसे होस्ट करना है।

+1

मुझे यह समाधान पसंद है। व्यक्तियों को चतुर सोच से पहले गिनती का मिलान करना। – Gevious

+1

आपके उत्तर के लिए धन्यवाद! –

संबंधित मुद्दे