79269558

Date: 2024-12-10 19:45:57
Score: 0.5
Natty:
Report link

After a lot of debugging, I found the issue!

The Issue

This code did not work as intended because LoggedModelManager.__init__ fails when provided no parameters.

I made the assumption that mycustom manager is only instantiated when my model B is defined:

class B(models.Model):
    objects = LoggedModelManager(logging_model='BLog') # I thought this was the only place the constructor was called.

However, this is not the case. When resolving related model sets, the ModelSerializer class from the Django Rest Framework library will instantiate a manager for the related model. This instantiation is done with none of the parameters I expected, therefore an exception was raised and the related set ignored. Sadly, this error is not reported by the serializer, making it very hard to debug.

The Solution

Make sure your custom manager can be instantiated at a later time with no parameters. I did this by returning the default QuerySet if this was the case:

# Defining the Manager
class LoggedModelManager(models.Manager):

     # Save the name of the logging model, which are `ALog` and `BLog` in our example.
    def __init__(self, *args, **kwargs):
        if 'logging_model' in kwargs:
            logging_model = kwargs.pop('logging_model')
            self.logging_model_name = logging_model.lower()
        else:
            self.logging_model_name = None
        super().__init__(*args, **kwargs)

    # Here we filter out the logs from the logged instances.
    def get_queryset(self) -> models.QuerySet:
        if self.logging_model_name is None:
            return super().get_queryset()
        return super().get_queryset().filter(**{self.logging_model_name+"__isnull": True})

Hope this was helpful! I wonder if this is worth a ticket to ensure the Django Rest Framework serializers actually raise an error instead of silencing it.

Reasons:
  • Blacklisted phrase (1): did not work
  • Long answer (-1):
  • Has code block (-0.5):
  • Self-answer (0.5):
  • Low reputation (0.5):
Posted by: Clement Faisandier