Pass instance pk or user.id into a model field for use in dynamic choices.

Hello Folks,

I am trying to find a way to have a model field with dynamic choices, filtering is based on these three items:

  1. user.id from the FK in the instance.
  2. model_verbose_name
  3. field_verbose_name

This is an overview of my setup using a custom field.

class MyCustomField(JSONField):

    def formfield(self, **kwargs):            
            # Return a MultipleChoiceField with appropriate widget
            kwargs["widget"] = forms.SelectMultiple()
            return forms.MultipleChoiceField(**kwargs)

My preferred way to do this would be to have the instance primary key or user.id available somewhere in MyCustomField, that way I could override get_choices and the whole process of using MyCustomField will be simpler.

I have spent quite some time exploring the field object, getting a better understanding of how it all fits together, but getting the instance ID into the field object has eluded me so far.

Here is the second option I had considered and explored. Likewise this has eluded me.

class MyModel(models.Model):

   user = models.ForeignKey(
        CustomUser,
        on_delete=models.CASCADE,
    )

    dynamic_choices_field =  MyCustomField(
        choices=get_choices(
                 user="How do I get user.id here?",
                 etc...             
    )

I would appreciate any thoughts about this, a solution would be amazing :slight_smile:

thank you

When you want the choices to be determined at runtime, and a class-level function isn’t going to work for you, then you want to adjust the options on the field in the __init__ method of the form.

See the discussion at How to filter the choices in forms.Select widget?. (There are a few other discussions here that talk about this as well.)

Thanks Ken, I will take a look.