Django, şunu içeren çoktan çoğa filtre


90

Bir grup nesneyi çoka çok ilişkisi üzerinden filtrelemeye çalışıyorum. Çünkü trigger_rolesalan birden fazla giriş içerebilir Denedim containsfiltreyi. Ancak bu dizelerle kullanılmak üzere tasarlandığından, bu ilişkiyi nasıl filtreleyeceğim konusunda oldukça çaresizim ( values_list()atm'yi göz ardı edebilirsiniz ).

Bu işlev, kullanıcı profiline eklenir:

def getVisiblePackages(self):
    visiblePackages = {}   
    for product in self.products.all():
        moduleDict = {}
        for module in product.module_set.all():
            pkgList = []
            involvedStatus = module.workflow_set.filter(trigger_roles__contains=self.role.id,allowed=True).values_list('current_state', flat=True)

İş akışı modelim şöyle görünüyor (basitleştirilmiş):

class Workflow(models.Model):
    module = models.ForeignKey(Module)
    current_state = models.ForeignKey(Status)
    next_state = models.ForeignKey(Status)
    allowed = models.BooleanField(default=False)
    involved_roles = models.ManyToManyField(Role, blank=True, null=True)
    trigger_roles = models.ManyToManyField(Role, blank=True, null=True)

Çözüm oldukça basit olsa da beynim bana söylemeyecek.

Yardımınız için teşekkürler.

Yanıtlar:


110

Böyle bir şey denedin mi:

module.workflow_set.filter(trigger_roles__in=[self.role], allowed=True)

veya sadece self.role.idpks listesi değilse:

module.workflow_set.filter(trigger_roles__id__exact=self.role.id, allowed=True)

1
Bu işe yaramıyor gibi görünüyor. Self.role.id yalnızca bir int olduğundan ve trigger_roles bunların bir listesi olduğundan, contains gibi ters çevrilmiş bir içeri ihtiyacım olurdu, ancak bulduğum gibi, yalnızca dizeler içindir.
Grave_Jumper

8
İkinci örnek olmalıdır çalışır. İçindeki değer self.role.idtetikleme rollerinden biriyse, bu filtre tetikleme rollerinden birinin değer olduğu tüm iş akışlarını çekmelidir self.role.id. Temel olarak bu, tam olarak "içerir" işlevi gibi davranacaktır. Hepimiz bir şey kaçırmadıkça.
Jordan Reiter

@Jordan Reiter: "içerir", sql'de "beğenmek" e dönüştürülür, ki bu OP'nin istediği şey değildir ve sanırım bunu zaten belirtti, diğer yandan "tam", "=" veya "is" burada fikir.
mouad

@Grave_Jumper: Buraya bir göz atın ( djangoproject.com/documentation/models/many_to_many ) ManytoMany Field ile çalışırken bazı örnekler bulabilirsiniz, umarım bu size yardımcı olabilir, eğer cevabım değilse :)
mouad

1
aww .. üzgünüm ikinci çözümünüz gayet iyi çalışıyor :) Yanımda küçük bir yapılandırma hatası vardı. Teşekkürler arkadaşlar bu benim günümü kurtardı ;-)
Grave_Jumper

19

Bunu başarmak için en basit yaklaşım, .pst dosyasındaki tüm örnek (id yerine) üzerinde eşitliği kontrol etmektir ManyToManyField. Bu, örneğin çoktan çoğa ilişkisinin içinde olup olmadığına bakar. Misal:

module.workflow_set.filter(trigger_roles=self.role, allowed=True)

7

Bunun eski bir soru olduğunu biliyorum, ama görünüşe göre OP aradığı cevabı asla tam olarak alamadı. Karşılaştırmak istediğiniz iki ManyToManyField kümeniz varsa, işin püf noktası __inoperatörü kullanmak değil contains. Örneğin, alanında ManyToMany ile "Grup" arasında bir "Etkinlik" modeliniz varsa eventgroupsve Kullanıcı modeliniz (açıkça) Gruba ekleniyorsa, şu şekilde sorgulama yapabilirsiniz:

Event.objects.filter(eventgroups__in=u.groups.all())


4

tekillik ilk örnekte neredeyse doğrudur. Sadece bir liste olduğundan emin olmalısın. İkinci örnek, kontrol etmek trigger_roles__id__exactdaha iyi bir çözümdür.

module.workflow_set.filter(trigger_roles__in=[self.role.id],allowed=True)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.