Вопрос

In a ModelForm, how can I filter a Select widget content with only values related with current instance? (The instance which called the ModelForm)

For example:

class smsForm(ModelForm):

    class Meta:
        model = SMS
        fields = ['phone', 'state']
        widgets = {
            'phone': Select(choices=phoneSMS.objects.all().values_list('id', 'phone'), attrs={'class':'form-control',}),
            'state': bootStrapButtonSelect( attrs={'class': 'buttons-sms', }), }

What I want to do is to filter that phoneSMS with only the phones which contains the sms reference. Here're the models:

class SMS(models.Model):
    student = models.ForeignKey(Student)
    day = models.DateField(db_index=True)
    tries = models.IntegerField(default=0)
    phone = models.CharField(max_length=9, default='---')
    sent = models.BooleanField(default=False)
    state = models.CharField(max_length=20, choices=OPTIONS, default='nothing')



class phoneSMS(models.Model):
    phone= models.CharField(max_length=120)
    sms = models.ForeignKey(SMS)

I tried with objects.filter(sms=SMS) but no result.

Это было полезно?

Решение

In the moment of declaration you have no information about model instance ModelForm will be initialized with.

You have to dynamically set choices when model instance is already known and it happens not earlier than in __init__() method:

class SmsForm(ModelForm):

    class Meta:
        model = SMS
        fields = ['phone', 'state']
        widgets = {
            'phone': Select(attrs={'class':'form-control',}),
            'state': bootStrapButtonSelect( attrs={'class': 'buttons-sms', })
        }

    def __init__(self, *args, **kwargs):
        super(SmsForm, self).__init__(*args **kwargs)

        self.fields['phone'].widget.choices = \
             phoneSMS.objects.filter(sms=self.instance.sms) \
                             .values_list('id', 'phone')

Still be careful as nobody guaranties that self.instance is set - it depends on optional instance argument. So better attach proper conditions and way of handling such case.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top