'Django ModelChoiceField validation error using a custom query Manager

I am getting a validation error when trying to submit a form using a ModelChoiceField with a queryset using a custom Manager. The standard objects manager is also replaced with a custom manager that filters out archived objects. This is working well throughout the site

My model (very simplified):

    # Use this as the default manager - filters out any records with an archivetype
    class ActiveManager(models.Manager):
        def get_queryset(self):
            return super().get_queryset().filter(archive__isnull=True)    
    
    # Alternative manager that returns non archived records and records archived with 'SYS' only
    class SysManager(models.Manager):
        def get_queryset(self):
            return super().get_queryset().filter(models.Q(archive__isnull=True) | models.Q(archive='SYS'))

    class Inventory(models.Model):
       item = models.CharField(primary_key=True)
       description = models.CharField()
       archive = models.CharField(null=True, blank=True)
        
       objects = ActiveManager()
       objects_sys = SysManager()
       objects_all = models.Manager()  # Default manager now objects_all
    
    class Building(models.Model):
       item = models.ForeignKey(Inventory, on_delete=models.PROTECT)

I have a Building form that uses the Item field and adjusts the widget attributes (I need extra attributes in the HTML):

class BuildingForm(forms.ModelForm):
    item = forms.ModelChoiceField(queryset=Inventory.objects_sys.all(),
                                  widget = forms.Select(attrs={
                            'class': 'important',       
                            'code': '1x1'}))

Inventory.objects_sys.all() returns a queryset that includes an Inventory record with an item called 'INSPECT' while Inventory.objects.all() does not. This is expected and desired behavior in my case.

The dropdown created shows the additional records returned by the custom manager (one of them being 'INSPECT'), but if I select 'INSPECT' and submit, I get a validation error "Inventory instance with item 'INSPECT' does not exist." An Inventory record with an item name of 'INSPECT' and archive field='SYS' does exist in the database. When I select any other item with a NULL archive, the form submits fine. It seems that it is correctly using the 'objects_sys' manager to get all the options to populate the Select, yet is using the 'objects' manager to validate if the submitted value is valid and in the Inventory table ('INSPECT' will not be returned using 'objects'). Is there someplace else I also need to specify the query for validation and use the 'objects_sys' manager?

Thank you for any insight.

EDIT: Stepping through the code in the debugger, when getting the query for validation, it does jump into the ActiveManager and not SysManager even though the query I specified for the ModelChoiceField specifies 'object_sys', the SysManager. If I change the queryset for ActiveManager to match that of SysManager, this form works fine, but unwanted records show up everywhere else in the site. I am obviously missing something - on the validation side, how do we get the query to run through the SysManager (objects_sys) instead of ActiveManager (objects)?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source