2009-09-10 9 views
3

j'ai un modèle comme:choix rétrécissant sous forme Django

CAMPAIGN_TYPES = (
        ('email','Email'), 
        ('display','Display'), 
        ('search','Search'), 
       ) 

class Campaign(models.Model): 
    name = models.CharField(max_length=255) 
    type = models.CharField(max_length=30,choices=CAMPAIGN_TYPES,default='display') 

Et une forme:

class CampaignForm(ModelForm): 
    class Meta: 
     model = Campaign 

est-il un moyen de limiter les choix sont disponibles pour le champ « type »? Je sais pour un champ de valeur unique que je peux faire: CampaignForm(initial={'name':'Default Name'}) mais je ne trouve aucun moyen de le faire pour un ensemble de choix.

+0

Vous pouvez modifier le nom du champ depuis « type » est mot-clé réservé en Python. – Soviut

+0

En outre, y a-t-il une raison pour que vous ne fassiez pas que les types de campagne soient un champ ChoiceField plutôt qu'un champ CharField? – Soviut

+0

Campaign est un modèle, donc ChoiceField n'est pas une option. –

Répondre

6

Voilà comment je limité les options affichées:

Dans forms.py ajouter une méthode init pour votre formulaire

class TaskForm(forms.ModelForm): 
    .... 

    def __init__(self, user, *args, **kwargs): 
     ''' 
     limit the choice of owner to the currently logged in users hats 
     ''' 

     super(TaskForm, self).__init__(*args, **kwargs) 

     # get different list of choices here 
     choices = Who.objects.filter(owner=user).values_list('id','name') 
     self.fields["owner"].choices = choices 
1

Les choix sont pour les listes uniquement, pas pour CharFields. Ce que vous devez faire est de créer un custom validator on clean().

dans forms.py

CAMPAIGN_TYPES = ('email', 'display', 'search') 

# this would be derived from your Campaign modelform 
class EnhancedCampaignForm(CampaignForm): 
    # override clean_FIELD 
    def clean_type(self): 
     cleaned_data = self.cleaned_data 
     campaign_type = cleaned_data.get("type") 

     # strip whitespace and lowercase the field string for better matching 
     campaign_type = campaign_type.strip().lower() 

     # ensure the field string matches a CAMPAIGN_TYPE, otherwise 
     # raise an exception so validation fails 
     if not campaign_type in CAMPAIGN_TYPE: 
      raise forms.ValidationError("Not a valid campaign type.") 

     # if everything worked, return the field's original value 
     return cleaned_data 
+0

Je ne suis pas sûr comment cela fonctionne exactement. J'essaie d'obtenir juste "email" et "affichage" montrant sur la liste de sélection du formulaire. –

1

Il semble que ce soit la meilleure façon de le faire en remplaçant le champ 'type':

class CampaignForm(ModelForm): 
    type = forms.ModelChoiceField(queryset=OtherModel.objects.filter(type__id=1)) 
    class Meta: 
     model = Campaign 

Je ne suis pas sûr en ce moment comment passer '1' mais ce sera suffisant même s'il doit être codé en dur. De plus, il permet à Django de faire la plupart des gros travaux.

@soviut Je vais changer le nom du champ en un mot non réservé. Merci pour l'information.

+0

Toute aide sur le passage d'une variable à type__id serait grandement appréciée. Alors qu'à l'intérieur du formulaire, il n'y a pas de 'soi'. Je ne sais pas ce qui est accessible là-dedans. –

+0

Cela peut se faire au moment de l'instanciation avec:.. form = CampaignForm() de form.fields [ 'type'] = choix TestModel.objects \ filtre (filtercriterion__id = 1) .values_list ('id', 'nom ') –

+0

Cette page a vraiment aidé: http://excess.org/article/2009/07/django-forms-quick-reference/ –

Questions connexes