I want to list only usable items in OneToOneField not all items, its not like filtering values in ChoiceField because we need to find out only values which can be used which
Although this is an old topic I came across it looking for the same answer.
Adjust your BarForm so it looks like:
class BarForm(ModelForm):
class Meta:
model = Bar
def __init__(self, *args, **kwargs):
super(BarForm, self).__init__(*args, **kwargs)
#only provide Foos that are not already linked to a Bar, plus the Foo that was already chosen for this Bar
self.fields['foo'].queryset = Foo.objects.filter(Q(bar__isnull=True)|Q(bar=self.instance))
That should do the trick. You overwrite the init function so you can edit the foo field in the form, supplying it with a more specific queryset of available Foo's AND (rather important) the Foo that was already selected.
My original question was: How to only display available Users on a OneToOne relation?
The Actor model in my models.py
looks like this:
class Actor(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name = 'peactor')
# lots of other fields and some methods here
In my admin.py
I have the following class:
class ActorAdmin(admin.ModelAdmin):
# some defines for list_display, actions etc here
form = ActorForm
I was not using a special form before (just relying on the basic ModelForm that Django supplies by default for a ModelAdmin) but I needed it for the following fix to the problem.
So, finally, in my forms.py
I have:
class ActorForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(ActorForm, self).__init__(*args, **kwargs)
#only provide users that are not already linked to an actor, plus the user that was already chosen for this Actor
self.fields['user'].queryset = User.objects.filter(Q(peactor__isnull=True)|Q(peactor=self.instance))
So here I make an ActorForm and overwrite the __init__
method.
self.fields['user'].queryset =
Sets the queryset to be used by the user formfield. This formfield is a ModelChoiceField by default for a OneToOneField (or ForeignKey) on a model.
Q(peactor__isnull=True)|Q(peactor=self.instance)
The Q is for Q-objects that help with "complex" queries like an or
statement.
So this query says: where peactor is not set OR where peactor is the same as was already selected for this actor
peactor
being the related_name for the Actor.
This way you only get the users that are available but also the one that is unavailable because it is already linked to the object you're currently editing.
I hope this helps someone with the same question. :-)