2012-08-15 2 views
0

Je voudrais créer un formset, où chaque formulaire a une liste déroulante pointant vers un ensemble d'articles de vente.Comment passer un paramètre au formulaire dans le formset?

Modèle:

class SalesItem(models.Model):   
    item_description = models.CharField(max_length=40) 
    company    = models.ForeignKey(Company) 

Ici, je crée un formulaire avec un menu déroulant, dans l'espoir de passer dans l'entreprise comme source pour le menu déroulant. Accrochez-vous à cette pensée, car je pense que ce n'est pas possible dans mon scénario.

Forme:

class SalesItemFSForm(Form):   
    sales_item  = forms.ModelChoiceField(required=False, queryset = '') 

    def __init__(self, company, *args, **kwargs): 
     super(SalesItemFSForm, self).__init__(*args, **kwargs) 
     self.fields.sales_item.queryset = company.salesitem_set.all() 

maintenant à mon avis, je voudrais créer un formset avec cette forme:

formset_type = formset_factory(SalesItemFSForm, extra=0) 

Le problème devient tout de suite évident, car il semble y avoir aucune façon que je pourrais passer dans l'entreprise pour déterminer la source de la liste déroulante.

Comment suis-je censé faire cela?

Merci beaucoup,

Mise à jour:

il semble Jingo craquée. :)

Un ModelForm fonctionne mieux qu'un formulaire. En plus, j'ai dû ajouter fields = {} à SalesItemFSForm, pour m'assurer que les champs de SalesItem n'apparaissent pas dans le modèle. Parce que tout ce qui nous intéresse est notre liste déroulante (SalesItem).

Jusqu'ici tout va bien. Mais maintenant, je vois autant de listes déroulantes que j'ai Salesitems. Il ne devrait pas apparaître à moins que l'utilisateur n'appuie sur un bouton jquery.

Et je pense que c'est le problème, nous ne devrions pas passer

formset_type = modelformset_factory(SalesItem, form=SalesItemFSForm, extra=0) 

Parce que notre formulaire n'a pas besoin d'instance de la SalesItem. Nous avons besoin d'un modèle factice.

C'est la raison pour laquelle j'ai essayé de le résoudre avec Classic Formset au lieu de ModelFormset. Donc c'est à mi-chemin. :)

Mise à jour 2:

Jingo, bon point. Effectivement, je pensais à une sauvegarde personnalisée, où je vois juste combien de formsets sont ajoutés par l'utilisateur via jQuery et l'enregistre moi-même dans la vue. Littéralement SalesItem est un champ ManyToMany. Mais le widget M2m standard est horrible. Par conséquent, je voulais le remplacer par formsets, où chaque salesItem est une liste déroulante. L'utilisateur peut alors ajouter autant de listes déroulantes (formulaires dans formset) à la page et les soumettre. Ensuite, je voudrais ajouter la relation dans la vue.

class DealType(models.Model):  
    deal_name   = models.CharField(_(u"Deal Name"), max_length=40) 
    sales_item   = models.ManyToManyField(SalesItem)  
    price    = models.DecimalField(decimal_places=2, max_digits=12) 

Espérons que cela soit clair. Peut-être qu'il existe un moyen plus facile de le faire. :)

Btw J'ai également trouvé cet excellent jquery snippet code comment ajouter/supprimer des formulaires de/à un formset.

Mise à jour 3:

En effet, lorsque instanciation de l'objet comme celui-ci, nous n'obtenir un formulaire dans le formset et peut ajouter plus via jquery. Parfait!! À moins qu'il n'y ait un moyen plus facile d'y parvenir. :)

salesitem_formsets = formset_type(queryset=SalesItem.objects.filter(pk=1)) 

Cependant cela vous vient chasser de retour dans la request.POST, puisque vous ne pouvez pas le faire:

salesitem_formsets = formset_type(request.POST) 

Il faut encore le queryset à régler. Tricky situation ...

+0

Même problème général que http://stackoverflow.com/questions/11692190/dynamic-modelchoicefield-queryset-with-an-inline-model-formset – supervacuo

+0

@supervacuo Le problème sous-jacent est le même mais fonctionne avec différents widgets. Donc, vous essayiez de le résoudre avec des formsets inline, intéressant, mais il semble que vous n'ayez pas non plus de solution à ce problème, n'est-ce pas? – Houman

+0

Lorsque vous instanciez le formulaire (ie: formset_type()), vous pouvez passer un dans un jeu de queues vide comme (normalement Django va pour ".all()"). Comme: formset_type (queryset = SalesItem.objects.none()). Voir ici https://docs.djangoproject.com/fr/dev/topics/forms/modelforms/#changing-the-queryset, attendez non, toujours pas à droite:/ – Jingo

Répondre

0

J'espère avoir compris l'objectif que vous voulez atteindre. Ensuite, vous pourriez peut-être utiliser ModelForm et son instance disponible comme ceci:

class SalesItemFSForm(forms.ModelForm): 
    class Meta: 
     model = SalesItem 

    def __init__(self, *args, **kwargs): 
     super(SalesItemFSForm, self).__init__(*args, **kwargs) 
     self.sale_items = self.instance.company.salesitem_set.all() 
     self.fields['sales_item'] = forms.ModelChoiceField(queryset=self.sale_items) 

Ce n'a pas été testé bien et juste une pensée. J'espère que cela mène dans la bonne direction, mais si c'est totalement faux, laissez-moi savoir et je vais supprimer ma réponse, de sorte que les autres ne seront pas confus :).

+0

Intéressant. Je pourrais essayer ceci, mais logiquement cela pourrait être problématique, puisque le salesitem.company.sales_item_set.all() serait le même que SalesItem.objects.all(), non? Et c'est un problème, parce que je veux le filtrer pour l'entreprise donnée. :) Pas sûr ... besoin de tester. Merci à – Houman

+0

oups, sonne bien, faut penser: P, et mieux tirer sur un shell python ... – Jingo

+0

Au moins dans la coquille ces deux queryset ne sont pas les mêmes. Pourriez-vous déjà tester? Id vraiment être intéressé par les résultats :), parce que j'essaie de résoudre des questions similaires tout en essayant de programmer un petit système d'enquête ... – Jingo

Questions connexes