2009-11-30 5 views
2

Je suis en train de construire une forme très triviale. Restons-en aux livres/exemples d'éditeurs donnés dans les tutoriels django et construisons dessus.Django ModelForm, ayant une clé étrangère comme champ caché

J'ai un utilisateur se connecter à l'application web, à quel point la première chose qu'ils peuvent faire est de cliquer sur un éditeur. Cet éditeur est ensuite enregistré pour leur session. Sur ce, je les emmène à un formulaire de création de livre. Là, j'intègre l'identifiant de l'éditeur de la base de données dans un champ caché.

À l'utilisateur de soumettre une requête HTTP POST, je fais quelque chose comme:

mybookform = BookForm(request.POST) 
if mybookform.is_valid(): 
    abook = mybookform.save(commit=False) 
    abook.publisher_id = request.POST['publisher_id'] 
    mybookform.save() 

Oui, il y a quelques petites choses naïves faites ici, comme saisissant aveuglément la PUBLISHER_ID et de vérifier si elle est en effet un vrai id éditeur, parmi d'autres problèmes de sécurité. Ne faisons pas attention à ça pour le moment.

Ma question est, y at-il une meilleure façon de gérer cela? Bien qu'hypothétiquement, cet exemple n'ait pas de sens logistique, dans mon application particulière, l'exemple a du sens. Le problème est que j'obtiens une exception ValueError indiquant que publisher_id doit être une instance de Publisher.

Maintenant, je peux facilement récupérer une instance d'éditeur avec Publisher.objects.filter (id = ..) et l'utiliser à la place. La question est, est-ce vraiment nécessaire? Est-ce que je peux éviter la requête additionnelle à la base de données et mettre à jour d'une manière ou d'une autre cette instance de forme d'une façon plus «élégante»?

Aussi, est-il possible d'intégrer l'éditeur dans un champ caché de sorte que je n'ai pas besoin de faire mybookform.save (commit = False) et juste faire mybookform = BookForm (request.POST) suivi de mybookform.save() immédiatement?

Répondre

1

La récupération de l'instance de l'éditeur protège contre les modifications côté client susceptibles de faire référence à un éditeur totalement invalide.

Pour votre deuxième question, oui vous pouvez inclure ce champ en tant que champ masqué par overriding the field in the ModelForm avec le champ de formulaire approprié définissant le widget à HiddenInput.

+0

Merci John. Le seul problème est que votre réponse ne m'aide pas à comprendre comment m'assurer que mon entrée cachée contient l'instance correcte du publisher_id. – randombits

+0

Simon Willison a parlé des cookies signés et, plus généralement, de la signature générale dans le noyau Django (http://groups.google.com/group/django-developers/browse_thread/thread/133509246caf1d91). Vous pouvez signer cryptographiquement un cookie ou la valeur du champ masqué à l'aide de sign.py de Simon (http://github.com/simonw/django-openid/blob/master/django_openid/signed.py) –

+0

nono. Je ne m'inquiète pas de crypter les cookies. J'ai déjà du code pour ça. Mon problème est que la clé étrangère référence un éditeur, mais il ne peut s'agir que d'un éditeur. Je ne sais pas comment définir le champ éditeur caché pour être celui de l'instance à laquelle l'utilisateur a été initialement connecté lors de la connexion à l'application. – randombits

0

Il n'y a pas de meilleure façon de procéder.

Je voudrais utiliser la fonction get_object_or_404 pour cela.

Et oui, vous pouvez éviter cela à modifier par l'utilisateur en définissant le champ modèle à editable=False,

Questions connexes