Wie man richtig eine Abfrage ManyToManyField für alle Objekte in einer Liste (oder einem anderen ManyToManyField)?
Ich bin ziemlich ratlos über die beste Möglichkeit zum erstellen einer Django-Abfrage, die prüft, ob alle die Elemente einer ManyToMany
Feld (oder eine Liste) vorhanden sind, die in einem anderen ManyToMany
Feld.
Als Beispiel, habe ich mehrere Person
s, wer haben können mehr als eine Spezialität. Es gibt auch Job
s, dass die Menschen beginnen können, aber Sie erfordern ein oder mehrere Specialty
s um förderfähig zu sein, um gestartet werden.
class Person(models.Model):
name = models.CharField()
specialties = models.ManyToManyField('Specialty')
class Specialty(models.Model):
name = models.CharField()
class Job(models.Model):
required_specialties = models.ManyToManyField('Specialty')
Kann eine person beginnen, einen job nurwenn Sie alle die Spezialitäten, die der job erfordert. So, wieder für den sake des Beispiels, wir haben drei Spezialitäten:
- Codierung
- Singen
- Tanzen
Und ich habe eine Job
erfordert, dass der Gesang und Tanz Spezialitäten. Eine person, die mit Gesang und Tanz Spezialitäten können Sie es starten, aber eine andere, mit Codierung und Singen Spezialitäten nicht -- wie der Job erfordert eine Person, die können beide singen und tanzen.
So, jetzt muss ich einen Weg finden, alle jobs, die eine person annehmen kann. Dies war mein Weg zur Lösung, aber ich bin sicher, es gibt eine elegantere Lösung:
def jobs_that_person_can_start(person):
# we start with all jobs
jobs = Job.objects.all()
# find all specialties that this person does not have
specialties_not_in_person = Specialty.objects.exclude(name__in=[s.name for s in person.specialties])
# and exclude jobs that require them
for s in specialties_not_in_person:
jobs = jobs.exclude(specialty=s)
# the ones left should fill the criteria
return jobs.distinct()
Dies ist da mithilfe Job.objects.filter(specialty__in=person.specialties.all())
zurück jobs entsprechen alle von der person, die Spezialitäten, nicht alle von Ihnen. Mithilfe dieser Abfrage, der job, der erfordert Singen und Tanzen würde, erscheinen für den Gesang coder, die nicht die gewünschte Ausgabe.
Ich hoffe das Beispiel ist jetzt nicht zu verworren. Der Grund warum ich bin besorgt über diese ist, dass die Spezialitäten in dem system wird wahrscheinlich viel mehr, und Durchlaufen Sie scheint nicht der beste Weg, dies zu erreichen. Ich wundere mich, wenn jemand verleihen könnte einen Kratzer auf dieses Jucken!
InformationsquelleAutor der Frage rlafuente | 2009-12-03
Du musst angemeldet sein, um einen Kommentar abzugeben.
Eine Andere Idee
Ok, ich denke, ich sollte dies nur Hinzugefügt, um die andere Antwort, aber wenn ich begann, es schien, wie es sein würde, in eine andere Richtung haha
Keine Notwendigkeit zu Durchlaufen:
Hinweis: ich weiß nicht genau wie schnell das ist. Sie können es besser mit meinen anderen Kommentaren.
Auch: Dieser code ist ungetestet
InformationsquelleAutor der Antwort Jiaaro
Ich denke, Sie sollten Blick auf die Verwendung values_listum der person, die Spezialitäten
Ersetzen:
mit:
Geben Sie eine nur-Liste (ie. ['spec1', 'spec2', ...]), die Sie verwenden können wieder. Und die sql-Abfrage verwendet, die in der bg wird auch schneller sein, weil es werden nur select 'name', statt ein
select *
zum Auffüllen der ORM-ObjekteBekommen Sie evtl. auch eine Verbesserung der Geschwindigkeit von filtern Arbeitsplätze, dass die person definitiv NICHT durchführen kann:
so ersetzen:
ist mit 2 Abfragen - funktioniert für django 1.0+)
oder mit (1-Abfrage? - Werke für django1.1+)
Sie kann auch eine Verbesserung durch die Verwendung select_related() auf Ihre jobs/person Abfragen (da Sie in einem fremden Schlüssel, den Sie verwenden)
InformationsquelleAutor der Antwort Jiaaro