开发者

Django queryset that returns all unassigned fks

开发者 https://www.devze.com 2022-12-17 04:38 出处:网络
I have 2 models with a 1-1 relation (essentially a resource pool).For the example code, I will simply use nuts and bolts.There will be many more nuts (available resources) than bolts (which will each

I have 2 models with a 1-1 relation (essentially a resource pool). For the example code, I will simply use nuts and bolts. There will be many more nuts (available resources) than bolts (which will each require 1 nut). However, if a nut can only be assigned to one bolt.

The constraint is easy enough to set up with the unique=True named param to the ForeignKey method.

The problem arises from the ModelForm. When rendered, the form will contain every nut in the dropdown. I would like to restrict it to only show nuts that haven't already been claimed by a bolt.

I am aware of the fields attribute of the ModelForm class, but am unable to come up with a query set filter that adequately addresses the issue. Here is example code of my problem:

from django.db import models
from django.forms import ModelForm

# Create 开发者_StackOverflowyour models here.

class Nut(models.Model):
    size = models.CharField()

class Bolt(models.Model):
    size = models.CharField()
    nut = models.ForeignKey( Nut, unique=True )

class BoltForm(ModelForm):
    def __init__(self, *args, **kwargs):
        super(BoltForm, self).__init__(*args, **kwargs)
        self.fields['nut'].queryset = # All unassigned nuts


Try this:

self.fields['nut'].queryset = Nut.objects.exclude(
    pk__in=Bolt.objects.values('nut').query)

Update:

Of three expressions generating the same sql query:

pk__in=Bolt.objects.values('nut')
pk__in=Bolt.objects.values_list('nut')
pk__in=Bolt.objects.values('nut').query

I'd choose the last one as most straight-forward (although in other two cases the list and dict aren't created in fact: django 'understands' the intention without explicit mentioning of .query)

Also, consider Daniel Roseman's answer. It is another approach to do the same thing.


Nut.objects.filter(bolt=None)
0

精彩评论

暂无评论...
验证码 换一张
取 消