2017-07-06 3 views
1

J'ai un comportement étrange sur mon serveur de production. Lorsque je tente de filtrer par clé étrangère inversée alors je reçois une erreur qu'il ne soit pas possible, mais localement il fonctionne très bien, par exemple:Django ORM Impossible de filtrer par clé étrangère inversée

class Foo(models.Model): 
    pass 

class Bar(models.Model): 
    name = models.CharField() 
    foo = models.ForeignKey('Foo', related_name='bars', blank=True, null=True, default=None) 

maintenant essayer de faire:

Foo.objects.filter(bars__name=xyz) 

se traduira par

Impossible de résoudre le mot-clé 'barres' dans le champ. Les choix sont: ...

J'utilise Ubuntu 16.04 et django 1.8.7

EDIT 1: peut-il être lié au fait que ForeignKeys sont définies en utilisant la représentation de chaîne? J'ai trouvé une relation qui est définie en utilisant la classe not string, donc cela ne fonctionne pas aussi bien pour de telles relations.

Fondamentalement, le modèle Foo a de nombreuses relations ForeignKey. Quelques-uns dans Foo, peu dans les modèles cibles. Ces modèles cibles n'existent pas en production lors de l'exécution de la requête depuis la perspective Foo. Ceux-ci dans Foo peuvent être utilisés comme paramètres de requête.

EDIT 3: J'ai reçu des informations plus détaillées sur la configuration du serveur et quand exactement une erreur se produit.

Informations sur la configuration de production où la question est vu:

  • version apache: 2.4.18-2ubuntu3.3
  • Version libapache2-mod-wsgi: 4.3.0-1.1build1

Apache config mpm_event:

StartServers 2 
MinSpareThreads 25 
MaxSpareThreads 75 
ThreadLimit 64 
ThreadsPerChild 25 
MaxRequestWorkers 150 
MaxConnectionsPerChild 0 

partie pertinente de configuration du site apache:

WSGIDaemonProcess some_name group=some_name maximum-requests=1000 processes=2 threads=15 user=some_name 
WSGIProcessGroup some_name 
WSGIScriptAlias/"/usr/lib/python2.7/dist-packages/some_name/wsgi.py" 
WSGIPassAuthorization On 

Fondamentalement, aucune erreur ne se produit à chaque requête. Quand il apparaît alors il vient d'un travailleur. Redémarrer apache corrige les erreurs pendant un certain temps. L'une des réflexions est qu'il peut y avoir une condition de concurrence dans le chargement des modèles de django.

+0

Le 'fk' devrait être sur' foo' et le nom lié 'bars' –

+1

Il devrait fonctionner dans les deux sens. Withouth related_name la requête devrait être filter (bar_set__name = xyz) – szaman

+0

Quoi de plus localement tout semble aller bien. – szaman

Répondre

1

Vous avez pas défini fk correctement:

class Foo(models.Model): 
    pass 

class Bar(models.Model): 
    name = models.CharField() 
    foo = models.ForeignKey(Foo, related_name='bars', blank=True, null=True, default=None) 

Pour faire face aux importations circulaires:

foo = models.ForeignKey('<app_name>.Foo', related_name='bars', blank=True, null=True, default=None) 
+1

oh oui vous avez raison, j'ai fait une erreur dans le pseudocode. maintenant corrigé. – szaman

+0

Cool =) Passez 'Foo' directement plutôt que sous forme de chaîne. –

+0

Il y a un problème, que nous avons beaucoup de modèle et il y a des importations circulaires – szaman

1

Vous devez utiliser related_query_name dans votre filtre de requête. Par défaut dans Django 1.8 c'est le nom du modèle, donc définir related_query_name personnalisé ou changer votre code à ceci:

Foo.objects.filter(bar__name=xyz) 
+0

from docs: Nom à utiliser pour le nom du filtre inverse du modèle cible. Par défaut, la valeur de related_name ou default_related_name est définie, sinon le nom du modèle est utilisé par défaut. – szaman

+1

Donc ça devrait marcher avec related_name défini, mais ça vaut le coup d'essayer. – szaman

+0

@Dima Kudosh 'related_name' fonctionne définitivement. C'est ce que j'utilise dans mon code tout le temps et je ne rencontre jamais de problème. –