1

I have Django models that inherit from an Archive class in which the default manager (objects) is replaced with a query that does not return archived records. This works well throughout the system.

However, in admin, when a record with a foreign key attempts to validate and that foreign key instance is an archived record, the validation attempts to use the new default manager, objects which filters out archived records as opposed to the objects_all manager which returns all records - and since an archived record is not returned using objects, the save fails with "instance does not exist".

Here is a simplified example:

class Inv(AbstractArchive):
    item_code = models.CharField(max_length=20, primary_key=True)
    qty = models.IntegerField()
    
    def __str__(self):
        return f"{self.item_code}"

class Txn(AbstractArchive):
    inv = models.ForeignKey(Inv)
    date = models.DateField()
    added = models.IntegerField

My admin for Txn looks like this (I defined a form in admin with a queryset that gets all the records, even those marked as archived - I also included a clean method hoping this would override the form's default validation that uses the objects manager)

class TxnForm(forms.ModelForm):
    class Meta:
        model=Txn

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['inv'].queryset = Inv.objects_all.all()

    def clean_inv(self):
        inv= self.cleaned_data['inv']
        if not Inv.objects_all.filter(inv=inv).exists():
            raise forms.ValidationError("Invalid inventory record selected.")
        return inv

@admin.register(Txn)
class TxnAdmin(AdminArchive):
    form = TxnForm
    def get_form(self, request, obj=None, **kwargs):
        form = super().get_form(request, obj=obj, **kwargs)
        if obj:
            form.instance = obj
        return form
    empty_value_display = '--'
    fields = (
        'inv',
        'date',
        'added',
    ) + AdminArchive.add_fields
    list_display = (
        'inv',
    ) + AdminArchive.list_display
    list_select_related = ('inv',) + AdminArchive.list_select_related
    autocomplete_fields = ('inv',) + AdminArchive.autocomplete_fields

This admin class inherits from a class called AdminArchive which simply handles consistently adding the archive fields to admin so they can be edited with the record.

In my models, I have an ActiveManager which returns non-archived records only and and ArchiveManager which returns all records and I have assigned those to objects and objects_all respectively

It seems, from stepping though in a debug session, the clean_inv method actually runs correctly (not raising a validation error for an archived record), but upon the clean_inv method's completion, somewhere later in the code, it is still using the objects manager to determine if the record exists or not.

What am I missing? What else do I need to override and use the objects_all manager instead of objects for records with archived FKs to be saved?

Mustafamond77
  • 330
  • 2
  • 15

0 Answers0