How to override the model.Manager.create() method in Django?

Without seeing the traceback, I think the problem is on this line.

    if 'type' in kwargs and kwargs['type'] is str:

This is checking whether kwargs['type'] is the same object as str, which will always be false.

In Python 3, to check whether `kwargs['type'] is a string, you should do:

    if 'type' in kwargs and isinstance(kwargs['type'], str):

If you are using Python 2, you should use basestring, to catch byte strings and unicode strings.

    if 'type' in kwargs and isinstance(kwargs['type'], basestring):

I was researching the same problem as you and decided not to use an override.

In my case making just another method made more sense given my constraints.

class HardwareManager(models.Manager):
    def create_hardware(self, type):
        _type = HardwareType.objects.get_or_create(name=type)
        return self.create(type = _type ....)  

The insight from Alasdair's answer helped a lot to catch both strings and unicode strings, but what was actually missing was a return statement before the call to super(HardwareManager, self).create(*args, **kwargs) in the HardwareManager.create() method.

The errors I was getting in my tests yesterday evening (being tired when coding is not a good idea :P) were ValueError: Cannot assign None: [...] does not allow null values. because the subsequent usage of new_hd that I had create()d was None because my create() method didn't have a return. What a stupid mistake !

Final corrected code:

class HardwareManager(models.Manager):
    def create(self, *args, **kwargs):
        if 'type' in kwargs and isinstance(kwargs['type'], basestring):
            kwargs['type'] = HardwareType.objects.get(name=kwargs['type'])
        return super(HardwareManager, self).create(*args, **kwargs)   

Tags:

Python

Django