2016-07-28 6 views
3

Nehmen wir an, ich habe zwei Tabellen in Django, TableA und TableB. Tabelle A enthält ein boolesches Feld, bool, und TableB enthält ein Fremdschlüsselfeld, for_field bis TableA, das Null sein kann.Django filtert ein ForeignKey-Feld, wenn es null ist

class TableA(models.Model): 
    bool = models.BooleanField() 

class TableB(models.Model): 
    for_field = models.ForeignKey('TableA', null=True) 

Wenn ich will TableB filtern, um alle Einträge zu bekommen, wo for_field.boolTrue oder for_field ist Null ist, was ist der kürzeste Weg, um dies zu erreichen?

Ich benutze .filter((Q(for_field__is_null=True) | Q(for_field__bool=True)), aber ich frage mich, ob es kürzere Code dafür gibt.

+1

Haben Sie versucht '.exclude (for_field__bool = False)'? Gibt es dieselben Ergebnisse? – valignatev

+0

Ich dachte darüber nach, aber ich bin mir nicht sicher, ob Django einen Fehler auslösen wird, wenn er versucht, auf 'bool' in einem' Null'-Fremdschlüsselfeld zuzugreifen. – mtcg

+0

Eine kleine Verbesserung: 'Q (for_field__is_null = True)' ist äquivalent zu 'Q (for_field = None)'. – knbk

Antwort

3

Nach einigen Experimenten scheint es, dass .exclude(for_field__bool=False) auch for_field__isnull=True Einträge enthält und keine Ausnahmen auslösen wird. Sie können sicher sein, indem Sie .exclude(for_field__bool=False).filter(for_field__isnull=True) ausführen und einige Ergebnisse auch sehen.

Und ehrlich gesagt weiß ich nicht, welche Option ist schneller, aber IMO Ihre Variante mit zwei Q Objekte viel lesbarer, weil es Logik zeigt, die Sie wirklich wollen. Also schlage ich Ihnen vor, dabei zu bleiben.

+0

Danke! Dies wird wahrscheinlich tun. Ich stimme zu, dass das Zeigen der zugrundeliegenden Logik den Code in den meisten Fällen lesbarer macht, aber in diesem Fall habe ich viele ähnliche 'for_field's, die ich in der Filterabfrage verketten muss, so dass es eine wirklich lange und unschöne Codezeile erzeugen würde. – mtcg

+0

Die 'exclude'-Version ist nett, wenn Sie viele Felder haben, weil Sie sie verketten können. 'exclude (some_field = False) .exclude (some_other_field = False) usw. –

1

Ich bin mir ziemlich sicher, dass Ihre Option die kürzest mögliche ist (korrigieren Sie mich, wenn ich falsch liege). Dies liegt daran, dass Sie keine OR-Abfragen ohne Q-Objekte ausführen können.

Verwandte Themen