JPLaverdure
JPLaverdure

Reputation: 43

Django: How to limit_choices_to when using custom intermediate table

Let me start by saying that I am working with a legacy database so avoiding the custom intermediate table is not an option.

I'm looking for an alternative way to get the limit_choices_to functionality as I need to only present the options flagged by the sample_option boolean in the Sampletype Model in my ModelForm:

class PlanetForm(ModelForm):
    class Meta:
        model = Planet
        fields = ['name', 'samples']

Here is a simplified view of my models

class Planet(models.Model):
    name= models.CharField(unique=True, max_length=256)
    samples = models.ManyToManyField('Sampletype', through='Sample')

class Sample(models.Model):
    planet = models.ForeignKey(Planet, models.DO_NOTHING)
    sampletype = models.ForeignKey('Sampletype', models.DO_NOTHING)

class Sampletype(models.Model):
    name = models.CharField(unique=True, max_length=256)
    sample_option = models.BooleanField(default=True)

Sample is the intermediate table. Normally, if the project had been started with Django in the first place, I could just define the ManyToManyField declaration as:

samples = models.ManyToManyField('Sampletype', limit_choices_to={'sample_option'=True})

But this is not an option.. So how do I get this functionality ? Django clearly states in their documentation that:

limit_choices_to has no effect when used on a ManyToManyField with a custom intermediate table specified using the through parameter.

But they offer no information on how to get that limit in place when you DO have a custom intermediate table.

I tried setting the limit_choices_to option on the ForeignKey in the Sample Model like so:

sampletype = models.ForeignKey('Sampletype', models.DO_NOTHING, limit_choices_to={'sample_option': True})

but that had no effect.

Strangely, I find no answer to this on the web and clearly other people must have to do this in their projects so I'm guessing the solution is really simple but I cannot figure it out.

Thanks in advance for any help or suggestions.

Upvotes: 3

Views: 1349

Answers (1)

AKS
AKS

Reputation: 19861

You could set the choices in the __init__ method of the form:

class PlanetForm(ModelForm):

    class Meta:
        model = Planet
        fields = ['name', 'samples']

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

         sample_choices = list(
             Sampletype.objects.filter(sample_option=True).values_list('id', 'name')
         )
         # set these choices on the 'samples' field.
         self.fields['samples'].choices = sample_choices

Upvotes: 2

Related Questions