Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to refer to the current object in a Django ModelForm?

Tags:

python

django

I have two related models, Company and Package. Each company can have several packages, but only one default_package. Here are the models:

class Company(models.Model):
    default_package = models.OneToOneField(
        Package,
        blank=True,
        null=True,
        related_name='default_for_%(class)s')

and for Package,

class Package(TimeStampedModel):
    company = models.ForeignKey('lucy_web.Company')

I'm trying to make a generic CreateView and UpdateView for the company as follows:

class EditViewsMixin(DashboardAccessMixin, SuccessMessageMixin):
    model = Company
    success_url = reverse_lazy('dashboard:companies')
    form_class = CompanyForm


class CompanyCreate(EditViewsMixin, CreateView):
    template_name = 'companies/new.html'
    success_message = "Company '%(name)s' was created successfully"


class CompanyUpdate(EditViewsMixin, UpdateView):
    template_name = 'companies/edit.html'
    success_message = "Company '%(name)s' was updated successfully"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['packages'] = self.object.package_set.order_by('name')
        return context

The CompanyForm is similar to the following:

class CompanyForm(forms.ModelForm):
    class Meta:
        model = Company
        fields = [
            'name',
            'default_package',
        ]

The problem is that in this form, the default_package drop-down menu shows all packages, whereas I would like it to the packages in the package_set of the company under consideration, similar to what is done by referring to self.object in the view's get_context_data method.

In essence, I'd like to do something like this in the CompanyForm:

default_package = forms.ModelChoiceField(
    queryset=Package.objects.filter(company=self.instance)
)

However, this is not possible because self is not defined at this level. Is there some kind of method of the ModelForm like get_queryset for a specific field, in which I can define the queryset using self.instance?

like image 651
Kurt Peek Avatar asked Oct 21 '25 20:10

Kurt Peek


1 Answers

I managed to do this by updating the field in the ModelForm's __init__() as follows:

def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.fields['default_package'].queryset = Package.objects.filter(company=self.instance)
like image 101
Kurt Peek Avatar answered Oct 24 '25 11:10

Kurt Peek



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!