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