2017-04-19 1 views
1

Avoir un peu de mal à essayer d'ajouter en masse une liste d'éléments à un champ de plusieurs à plusieurs et bien qu'ayant essayé plusieurs choses n'ont aucune idée de la façon d'aborder ce. J'ai regardé la documentation de Django et je n'arrive pas à trouver ce que je cherche.Django Ajouter la liste générée à partir du texte d'un champ vers plusieurs à plusieurs champs

Voici le code pour mes modèles:

class Subject(models.Model): 
    noun = models.CharField(max_length=30, null=True, blank=True) 

class Knowledge(models.Model): 
    item_text = models.TextField() 
    item_subjects = models.ManyToManyField(Subject, null=True, blank=True) 

def add_subjects(sender, instance, *args, **kwargs): 

    if instance.item_info: 
     item_subjects = classifier.predict_subjects(instance.item_info) 

     if item_subjects: 
      .... 

post_save.connect(add_subjects, sender=Knowledge) 

La liste est générée par la fonction classifer.predict_subjects. J'ai essayé d'utiliser le connecteur m2m_changed et les connecteurs pre_save et post_save. Je ne suis même pas sûr que le champ de plusieurs à plusieurs est la bonne option serait-il préférable de faire une relation de clé étrangère. à la place du '...' J'ai essayé ceci mais il ne crée pas la relation entre et enregistre seulement le dernier.

for sub in item_subjects: 
    subject = Subject(id=instance.id, noun=sub) 
    subject.save() 

J'ai aussi essayé

instance.item_subjects = item_subjects 

et une charge plus de choses que je ne me souviens pas vraiment, je ne pense pas vraiment que je suis dans le bon ordre de grandeur pour être honnête. Aucune suggestion?

modifier:

ok, donc je l'ai obtenu il ajouter tous les éléments de la liste mais n'a pas réussi à relier ces éléments aux nombreux à plusieurs champs.

 for sub in item_subjects: 
      subject = Subject.objects.get_or_create(noun=sub) 

modifier 2:

Ce faisant à peu près exactement la même chose en dehors de la boucle dans la coquille Django semble fonctionner et enregistre l'entrée, mais il ne l'intérieur de la fonction.

>>> k[0].item_subjects.all() 
<QuerySet []> 
>>> d, b = Subject.objects.get_or_create(noun="cats") 
<Subject: cats> 
>>> k[0].item_subjects.add(d) 
>>> k[0].item_subjects.all() 
<QuerySet [<Subject: cats>]> 

modifier 3

Je pris ce que Robert a suggéré et cela fonctionne dans la coquille comme ci-dessus tout simplement pas lorsque vous l'utilisez dans l'interface d'administration. Les instructions d'impression dans mon code montrent l'élément de tableau en cours de mise à jour, mais il ne persiste pas. Je lis autour et cela semble être un problème à faire avec le formulaire d'administration de compensation avant d'enregistrer.

def sub_related_changed(sender, instance, *args, **kwargs): 

    print instance.item_subjects.all() 

    if instance.item_info: 
     item_subjects = classifier.predict_subjects(instance.item_info) 

     if item_subjects: 
      for sub in item_subjects: 
       subject, created = Subject.objects.get_or_create(noun=sub) 
       instance.item_subjects.add(subject) 

     print instance.item_subjects.all() 


post_save.connect(sub_related_changed, sender=Knowledge) 

J'ai essayé d'utiliser la fonction en tant que signal m2m_changed comme suit:

m2m_changed.connect(model_saved, sender=Knowledge.item_subjects.through) 

Mais cela soit génère une boucle récursive ou ne se déclenche pas.

Répondre

0

Une fois que vous avez les objets subject (que vous avez dans votre édition), vous pouvez les ajouter avec

for sub in item_subjects: 
    subject, created = Subject.objects.get_or_create(noun=sub) 
    instance.item_subjects.add(subject) 

L'attribut « item_subjects » est une façon de gérer les articles connexes. Les relations directes sont créées via la méthode "add".

Une fois que vous avez fait cela, vous pouvez faire des choses comme instance.item_subjects.filter(noun='foo') ou instance.item_subjects.all().delete() et ainsi de suite

Documentation Référence: https://docs.djangoproject.com/en/1.11/topics/db/examples/many_to_many/

EDIT Ahh Je ne savais pas que cela avait lieu dans l'Admin Django. Je pense que vous avez raison de dire que c'est le problème. Lors de la sauvegarde, l'administrateur appelle deux méthodes: La première est model_save() qui appelle la méthode save() du modèle (où je suppose que ce code existe). La seconde méthode qu'il appelle est «save_related» qui nettoie d'abord les relations ManyToMany, puis les enregistre en fonction des données de formulaire soumises. Dans votre cas, il n'y a pas de données de formulaire valides, car vous créez les objectifs lors de la sauvegarde.

Si vous placez les parties pertinentes de ce code dans la méthode save_related() de l'administrateur, les modifications doivent être conservées.

Je peux être plus précis sur où il devrait aller si vous postez à la fois votre application <> /models.py et vos fichiers app> /admin.py <.

Référence d'une autre question SO: Issue with ManyToMany Relationships not updating inmediatly after save

+0

Merci pour votre aide, sa ne fonctionne toujours pas pour une raison quelconque. essayer à peu près la même chose dans le shell django fonctionne bien. par exemple '>>> k [0] .item_subjects.all() >>> d, b = Subject.objects.get_or_create (nom = "chats") >>> d > >> k [0] .item_subjects.add (d) >>> k [0] .item_subjects.all() ]> 'y at-il autre chose que je dois faire ici? –

+0

Heureux que ça marche dans la coquille. Vous pouvez modifier le code pour afficher le nouveau code que vous utilisez en dehors du shell (le code qui ne fonctionne toujours pas?) Maintenant que vous avez ajouté la méthode .add(). –

+0

kk merci, je l'ai mis à jour à nouveau. –