J'ai un site Web utilisant Django. Chaque message est un objet appelé article. Je veux récupérer le code HTML de la poteau après l'avoir sauvegardé afin que j'ai écrit le crochet post_save suivant: Il attend essentiellement 20s (ajouté en tant que test) puis essaie de récupérer le code HTML de l'article Son URL et écrit le code d'état de la demande à un fichier de débogage. P> Le problème est que je reçois toujours le statut = 404 lors de la première sauvegarde, il fonctionne sur la 2e et les sauvegardes suivantes. Je pensais que la façon dont Django fonctionne serait, afin que: p> Mais je devrais alors pouvoir récupérer le HTML dans Post_save. Suis-je compréhension post_save de manière incorrecte? P> Notes ajoutées: P>
4 Réponses :
Avez-vous essayé de remplacer la méthode de sauvegarde de l'objet, appelant Super, en attente, puis essayez de récupérer le HTML? Utilisez-vous également le serveur de développement? Il peut avoir des problèmes de manipulation de la deuxième demande alors que le premier se passe toujours. Peut-être l'essayer sur un serveur approprié? P>
Oui. Le message n'a aucune URL sauf si la sauvegarde est complètement exécutée, ce qui semble correct. Et je fais tout cela sur un serveur réel.
J'avais le même problème causé probablement par la même question (Question posée différemment, https: //plus.google.com/u/0/1067298915868988564412/posts/aoq3x1g4mvx ). Je n'ai pas résolu de manière appropriée, mais vous pouvez essayer de jouer avec le cache de base de données ou (l'a vu dans un autre problème de base de données Django) fermer toutes les connexions et requête de base de données. P>
edit 2: strong> deux exemple de modèles. exemple vues.py et urls.py ont été omis comme ils sont simples. Je peux les ajouter si nécessaire. P> Création de signaux pré_save et post_save pour l'article: p> Importation de mes signaux.py Donc, Django peut l'utiliser: p> Après avoir défini ce qui précède, je suis allé de l'avant et j'ai créé un nouvel article dans Django Shell (python.exe geper.py shell). P>
J'ai créé un exemple simple (à l'aide de Django 1.5.5) pour tester si cela fonctionne comme prévu. Pour autant que je puisse dire, ça fait. Pre_save incendie avant une base de données commit et post_save incendie après.
Exemple détaillé:
L'article est utilisé pour déclencher des signaux.
L'articleurl est utilisé pour enregistrer les réponses de l'article.get_absolute_url (). P> >>> from article.models import *
>>> a = Article(name='abcdd')
>>> a.save()
>>> ArticleUrl.objects.all()
[<ArticleUrl: pre abcdd: 404>, <ArticleUrl: post abcdd: /article/article/8>]
Je ne vois pas comment. Par exemple, le code ci-dessus fonctionne si je sauvegarde le message une seconde fois et à chaque fois. Cela ne fonctionne pas sur la toute première sauvegarde.
J'ai ajouté un exemple détaillé de pré_save et de post_save travaillant comme prévu. Pourriez-vous comparer cela à votre propre code?
Votre exemple de code fonctionne. Il semble que le poste ait une URL extrêmement récupérée par l'inverse mais n'est pas accessible par d'autres agents, par exemple le navigateur avant la fin de Post_save. J'ai testé cela en ayant juste un sommeil de 60s dans Post_save et en accédant à la poste via le navigateur et qu'il n'a pas fonctionné. Il semble que @brice ait raison, même pensé que je ne comprends pas ce qu'il a dit.
@Brice soulignait que vous pouvez frapper des problèmes de validation de la transaction SQL. Votre code fonctionne essentiellement dans 2 threads distincts. Le premier est la sauvegarde () elle-même alors que la seconde est la demande de contenu de l'URL. Il semble que Django n'engage pas les modifications (et les nouvelles données) de la première à la base de données jusqu'à ce que Save () complète complètement. Cela ne se produit qu'après post_save. Avez-vous envisagé de faire ce dont vous avez besoin d'une manière différente? Peut-être accéder au contenu via le modèle plutôt que l'URL?
Bien que ce soit une approche complètement incorrecte (*), le problème est probablement dans les transactions de base de données. Le thread actuel enregistre l'article mais dans cette transaction non initiée, vous essayez d'obtenir ces données via un autre thread (via Web Server). Dans ce cas, ce comportement est complètement correct. Soit vous devez vous engager avant de récupérer un autre fil ou d'obtenir le code HTML d'une autre manière. P>
(*) doit être fait de manière asynchrone à l'arrière-plan (céleri ou autre application de file d'attente ASYNC plus léger) ou vous pouvez appeler la vue directement si vous souhaitez obtenir le code HTML (selon votre vue, vous devrez peut-être avoir à forger la demande. ; Si trop compliqué, vous pouvez créer une fonction d'assistance que Cherrypicks minimal code pour rendre le modèle). Si vous n'avez besoin que d'appeler une API de 3ème partie après avoir enregistré quelque chose, vous voulez le faire de manière asynchrone. Si vous ne le faites pas, le succès de votre code "Save ()" dépendra de la disponibilité de votre connexion ou du service tiers et vous aurez besoin de traiter les transactions sur place où vous ne pourrez pas traiter des transactions. ;) p>
Vous semblez juste à propos de la chose des threads, bien que je ne comprenne pas du tout. Je mettais un sommeil de 60s dans le post_save et pendant qu'il était en cours d'exécution essayé d'accéder à l'article par le navigateur et donne 404.
Dans des bases de données transactionnelles, si vous faites une requête d'insertion / mise à jour, les données modifiées ne sont pas vraiment enregistrées, elles sont temporaires. C'est le même principe que si vous ouvrez un fichier TXT, vous apportez des modifications, mais vous ne enregistrez pas le fichier. Vous voyez les modifications à l'écran (fil de courant), mais lorsque quelqu'un d'autre ouvre le même fichier (un autre fil de serveur Web), il y a l'ancien contenu. Peu importe la durée de l'ouverture du fichier (votre temps de sommeil), vous devez d'abord faire Ctrl + S (commit), puis visibles pour d'autres.
Oui, cela a du sens maintenant! Merci.
C'est une bonne explication. J'avais ce problème lorsque j'utilise post_save pour transmettre des objets ID et la tâche de céleri pour récupérer le même objet
Avez-vous envisagé une façon différente de le faire: au lieu de récupérer l'article à l'aide de HTTP, il suffit de rendre directement un modèle d'article à une chaîne. Voir docs.djangoproject.com/ FR / 1.6 / REF / Modèles / API / ...
Je souhaite utiliser les liens dans le HTML pour envoyer des "Pingbacks" ou réellement Webmentition . Mais tous mes pingbacks sont rejetés parce que le poste n'a pas encore d'URL. C'est le code minimum nu qui ne fonctionne pas.