I've got quite the mysterious MultipleObjectsReturned error that just popped up after weeks of not having an issue. I'm hoping is just something simple that I'm missing.
I've got an Order model, an OrderLine model, which has an Item foreign key. Each Item has a foreign key to a Product. Here are the dumbed down models:
class OrderLine(models.Model):
order = models.ForeignKey(Order, related_name="lines", on_delete=models.CASCADE)
item = models.ForeignKey(Item, on_delete=models.SET_NULL, blank=True, null=True)
class Product(TimeStampedModel):
...
class Item(TimeStampedModel):
product = models.ForeignKey(Product, related_name='items', on_delete=models.CASCADE)
OrderLineForm and OrderLineAdmin for reference:
class OrderLineForm(forms.ModelForm):
class Meta:
model = OrderLine
...
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['category'].queryset = ItemType.objects.all()
self.fields['product'].queryset = Product.objects.none()
self.fields['item'].queryset = Item.objects.none()
if self.instance.pk:
try: # When changing an existing OrderLine
...
current_item = Item.objects.filter(pk=self.instance.item.pk)
available_items = current_item.union(
get_available_items(...)
)
self.fields['item'].queryset = available_items
self.fields['category'].initial = item_type_id
except:
self.fields['item'].queryset = Item.objects.all()
...
@admin.register(OrderLine)
class OrderLineAdmin(admin.ModelAdmin):
form = OrderLineForm
Now, when I use Django admin to edit an OrderLine which has more than one Item in the ModelChoiceField queryset:

I get the following error during form clean: get() returned more than one Item -- it returned 2!
Upon closer inspection of the logs, it appears the ModelChoiceField is getting passed the correct Item id/pk, but the self.queryset.get(**{key:value}) is somehow returning 2 Items from a single id/pk, even though the Items have different id/pks (49 and 50):

Again, this only happens when the OrderLine form's Item field has more than one object in the queryset. If it's only a single Item, it saves just fine. Any ideas why I'm getting this error now? Thanks!
The only thing I can think has changed in terms of database relationhips is that I added formset.save_m2m() to the Item model admin, however Item isn't a m2m relationship, so perhaps that could have led to some database indexing error?
P.S. I found this https://code.djangoproject.com/ticket/23354 from years ago that seems to reference the error in this context, but the ticket said it was fixed.
From these two lines we can see that you perform a union and set this as the fields queryset:
From the documentation on
union:Considering that the field will call
geton this queryset to validate the selected choice a union is not feasible for it. Considering your use case in fact there is a better option of us just using the SQL OR operator. There are mainly 2 ways to do this:Use the
|operator:This is equivalent to saying
SELECT ... WHERE (condition for current item) OR (conditions for available items).Use
Qobjects:The previous method was not very great considering we may want to make queries having quite complex conditions. This would result in us writing a bunch of querysets and then using
|and&on them. Rather than doing this we have the great option of usingQobjects which can take as keyword arguments the same arguments you would have passed to filter: