Home > front end >  Using Model.objects.filter in Form prevents me from updating Model
Using Model.objects.filter in Form prevents me from updating Model

Time:12-21

I have a form setup like this where I use the values from TestModel to create a select field in a form. However if I want to update the TestModel to add a new column, Django gives me a psycopg2.errors.UndefinedColumn saying the new column is not found on the table and the stack trace points back to this form ModelChoiceField. Its not until I comment out this select that I am able to make the migration to the database.

So my question is there a better way to setup this ModelChoiceField where I don't have to comment it out to update the underlying model on the database? I'm using Django 4.0 and python 3.8 for reference.

class TestModelChoiceField(forms.ModelChoiceField):
    """
    Overwriting model choice field attribute to use
    a different __str__ representation than the default
    model
    """

    def label_from_instance(self, obj):
        return obj.test_field


class TestForm(forms.Form):

    first_select = TestModelChoiceField(
        queryset=TestModel.objects.filter(model_attribute__isnull=False),
        initial=TestModel.objects.filter(model_attribute__isnull=False)
        .filter(test_field="Yes")
        .first()
        .team_id,
        label="Field One:",
    )

CodePudding user response:

When it comes to needing database access in a form like this, you're best waiting until the form is initialised rather than at runtime like you are doing here. With it setup like you have, when you start your app the form will get loaded and immediately try to query the database. If you wait until the app creates an instance of the form, you can be assured that the database will be ready/available.

So what you'd end up with is something like;

class TestForm(forms.Form):

    first_select = TestModelChoiceField(
        queryset=TestModel.objects.none(),
        label="Field One:",
    )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
    
        self.fields['first_select'].queryset = TestModel.objects.filter(model_attribute__isnull=False)

        self.fields['first_select'].initial = TestModel.objects.filter(
            model_attribute__isnull=False
        ).filter(test_field="Yes").first().team_id
  • Related