8

J'ai un projet django avec 2 applications comme ceci:Évitez les importations de modèles circulaires dans Django Apps

## tags app, models.py 
class Tag(models.Model): 
    title = models.CharField(max_length=50) 


## items app, models.py 
from application.tags.models import Tag 

class Item(models.Model): 
    title = models.CharField(max_length=300) 
    tags = models.ManyToManyField(Tag, related_name="items") 

MISE À JOUR CLARIFIER MÉTIER LIEU

J'ai une méthode sur un autre modèle items.models qui obtient tous les éléments qui ont un ensemble de balises.

La requête résultante est comme:

## Gets all of the items that have tags t1 and t2 
Item.objects.filter(tags=t1).filter(tags=t2) 

Cette méthode utilise le modèle Item ainsi que le modèle Tag, ce qui est correct, car Tag est importé dans l'application des articles.

Cependant, je souhaite avoir accès à cette méthode dans l'application Tags, mais cela entraînerait une importation circulaire.

Maintenant, ma solution de contournement pour obtenir tous les éléments avec un ensemble de balises dans l'application de balises est de faire une intersection définie sur la relation inverse dans le champ plusieurs à plusieurs.

## Get all items that have the tags with ids tag_ids 
item_set = set(Tag.objects.get(pk=tag_ids[0]).items.all()) 
for cur_tag_id in tag_ids[1:]: ## for all of the rest of the tags 
    item_set = item_set & set(Tag.objects.get(pk=cur_tag_id).items.all()) 

Cela entraîne plusieurs autres requêtes et une intersection définie. Est-il possible de faire quelque chose comme Item.objects.filter(tags=t1).filter(tags=t2)... à partir du modèle Tag dans l'application tags?

J'ai été en mesure de contourner cela en utilisant contenttypes pour obtenir le modèle Item pour faire la même requête. Est-ce acceptable ou existe-t-il une meilleure façon d'organiser ce code?

+0

Vous n'avez pas vraiment donné toutes les informations pertinentes. Où est définie votre méthode de filtrage? Pourquoi ne pouvez-vous pas le mettre quelque part qui peut être importé par les deux applications? –

+0

C'est le problème que j'essaie de résoudre. C'est une méthode sur un modèle différent dans l'application des éléments. Le problème est que items.models importe Tag, et si cette méthode est dans un autre endroit, il faudra toujours importer Item et Tag. Alors Tag ne pourrait pas l'importer ou il serait encore circulaire. – jkeesh

Répondre

23

Lorsque vous définissez des modèles avec des clés étrangères, vous pouvez utiliser le format:

tags = models.ManyToManyField('tags.Tag', ...) 

Cela signifie que vous n'avez pas besoin d'avoir importé la classe Tag, vous venez d'installer l'application de balises.

Ensuite, vous pouvez stocker une fonction dans un emplacement différent, qui pourrait importer à la fois Tag et Item, et ne pas avoir à s'inquiéter des importations circulaires.

+0

Merci. Cela aide, mais le problème est que si je veux utiliser cette fonction à partir d'un emplacement différent dans les modèles pour les deux applications, alors je reçois encore des importations circulaires. – jkeesh

+9

Vous pouvez utiliser django.db.models.get_model ('app.Model') pour obtenir une référence à un modèle sans avoir à l'importer. Est ce que ça aide? –

+1

Ça le fait! J'avais besoin de faire get_model ('app', 'Model'), mais cela a fonctionné. Est-ce une mauvaise pratique de récupérer des modèles de cette façon? – jkeesh

Questions connexes