2015-10-22 1 views
1

J'ai deux modèles qui sont utilisés avec une base de données que je ne contrôle pas. Les deux sont définis avec managed = False. Le premier modèle a un champ qui est une clé étrangère au deuxième modèle, mais il est implémenté comme CharField, pas comme ForeignKey.Django: Utiliser select_related sans un champ ForeignKey

Est-il possible d'utiliser select_related sur le premier modèle pour accéder aux propriétés du second modèle key'd?

Voici un exemple:

class Foo(models.Model): 
    class Meta: 
     managed = False 
    fieldone = models.CharField(max_length=10) 
    myfk = models.CharField(max_length=20) # In practice, this points to Bar.localkey 

class Bar(models.Model): 
    class Meta: 
     managed = False 
    localkey = models.CharField(max_length=20) 
    someotherattribute = models.CharField(max_length=100) 

Foo.objects.all().select_related('Bar') # I know this won't work, but is there something that will? 
+0

Pourquoi ne pas utiliser 'ForeignKey'? – Ivan

+0

Je pensais que je ne serais pas en mesure d'utiliser un ForeignKey parce que la base de données réelle que ce modèle utilise est hors de mon contrôle (d'où 'managed = False'). Cependant, même si cette relation n'est pas implémentée comme une vraie clé étrangère dans cette base de données, l'utilisation d'une ForeignKey a semblé fonctionner ici et je suis maintenant capable d'utiliser 'select_related'. – Joseph

Répondre

1

Non, parce qu'il n'y a rien lié.

Mais si vous (ou quelqu'un pour une raison quelconque) avez stocké l'ID (ou une valeur unique telle que localkey) à partir de l'objet 'related', vous pouvez effectuer un filtre basé dessus.

foo = Foo.objects.first() # Pick one Foo object 
foo_bar = Bar.objects.get(localkey=foo.myfk) 

Pour faire cela ressemble select_related vous pouvez essayer ceci:

class Foo(models.Model): 
    class Meta: 
     managed = False 
    fieldone = models.CharField(max_length=10) 
    myfk = models.CharField(max_length=20) 

    def bar(self): 
     return Bar.objects.get(localkey=self.myfk) 
     # probably you will need to manage common error when performing a .get() 
     # DoesNotExist and MultipleObjectsReturned 

Utilisez ensuite comme ceci:

foos = Foo.objects.all() 

for foo in foos: 
    print foo.bar() 

Je ne sais pas si cela est une bonne idée mais vous pouvez décorer la méthode .bar() en tant que property:

... 

@property 
def bar(self): 
    return Bar.objects.get(localkey=self.myfk) 

Et puis appelez comme ceci:

foo # some random Foo object 
foo.bar # this should return the 'related' Bar object