Django и ModelForm. Как изменить целочисленное поле на выпадающее

#django #django-forms

#django #django-формы

Вопрос:

У меня есть модель, которая выглядит следующим образом

 class RSVP (models.Model):
    def __unicode__(self):
            return self.firstName   " "   self.lastName
    firstName = models.CharField(max_length=30)
    lastName = models.CharField(max_length=30)
    rsvpID = models.CharField(max_length=9, unique = True)
    allowedAdults = models.IntegerField(default = 2)
    allowedChildren = models.IntegerField(default = 0)
    adultsAttending = models.IntegerField(default = 0)
    childrenAttending = models.IntegerField(default = 0)
  

и у меня есть ModelForm, которая выглядит следующим образом

 class RsvpForm(ModelForm):
    class Meta:
        model = RSVP
        exclude= ('firstName', 'lastName', 'allowedAdults', 'allowedChildren')
  

Чего бы я хотел, так это чтобы вместо текстового поля для adultsAttending отображалось выпадающее окно со значениями от 0 до allowedAdults. Это для сайта свадебного приглашения, и я хотел бы установить максимальное количество 1, которое приглашенный может привести на индивидуальной основе

Есть мысли о том, как это сделать?

Ответ №1:

Я думаю, вы хотите перенести разрешенные дочерние элементы / взрослых, а также имя на другую модель:

models.py

 class Invited(models.Model):
    f_name = models.CharField()
    l_name = models.CharField()
    allowed_adults = models.IntegerField()
    allowed_children = models.IntegerField()

class RSVP(models.Model):
    invited = models.ForeignKey(Invited)
    adults_attending = models.IntegerField()
    children_attending = models.IntegerField()
  

Затем вы должны создать приглашенные объекты и назначить разрешенные взрослые и дочерние. И форма RSVP будет учитывать эти числа при генерации вариантов для вашего выпадающего списка.

Выпадающий список может быть реализован путем переопределения виджета IntegerField с помощью ChoiceField

forms.py

 class InvitedForm(forms.ModelForm):
    class Meta:
        model = Invited

class RSVPForm(forms.ModelForm):
    class Meta:
        model = RSVP
        exclude = ['invited',]

    def __init__(self, *args, **kwargs):
        max_adults = kwargs.pop('max_adults',2) #default to 2 if no max set
        max_children = kwargs.pop('max_children',2) #default to 2 if no max set

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

        adult_choices = ( (x,str(x)) for x in range(max_adults 1)) )
        children_choices = ( (x,str(x)) for x in range(max_children 1)) )

        self.fields['adults_attending'] = forms.ChoiceField(choices = adult_choices)
        self.fields['children_attending'] = forms.ChoiceField(choices = children_choices)
  

views.py

 def rsvp_view(request, invited_id):
    invited = get_object_or_404(Invited, pk=invited_id)
    if request.method=='POST':
        form = RSVPForm(request.POST, max_adults=invited.allowed_adults,
                        max_children=invited.allowed_children)
        if form.is_valid():
            rsvp = form.save(commit=False)
            rsvp.invited = invited
            rsvp.save()
            return HttpResponse("Success")
    else:
        form = RSVPForm(max_adults=invited.allowed_adults, max_children=invited.allowed_children)

    context = { 'form':form,
                'invited':invited }
    return render_to_response('rsvp.html', context,
                               context_instance=RequestContext(request))
  

Комментарии:

1. Огромное спасибо! Это сработало идеально. В чем преимущество разделения моделей? Просто организация?

2. Для тех, кто все еще задается вопросом, forms.ChoiceField должен быть расположен в RSVPForm конструкторе класса, А НЕ в Meta конструкторе класса.