Как переопределить модель.Менеджер.метод create () в Django?
у меня много Hardware
- модели, которые имеют HardwareType
с различными характеристиками. Вот так:
# models.py
from django.db import models
class HardwareType(model.Models):
name = models.CharField(max_length=32, unique=True)
# some characteristics of this particular piece of hardware
weight = models.DecimalField(max_digits=12, decimal_places=3)
# and more [...]
class Hardware(models.Model):
type = models.ForeignKey(HardwareType)
# some attributes
is_installed = models.BooleanField()
location_installed = models.TextField()
# and more [...]
если я хочу добавить новый Hardware
объект, я сначала должен получить HardwareType
каждый раз, который не очень сухой:
tmp_hd_type = HardwareType.objects.get(name='NG35001')
new_hd = Hardware.objects.create(type=tmp_hd_type, is_installed=True, ...)
поэтому я попытался переопределить HardwareManager.create()
метод автоматического импорта типа при создании нового Hardware
вот так:
# models.py
from django.db import models
class HardwareType(model.Models):
name = models.CharField(max_length=32, unique=True)
# some characteristics of this particular piece of hardware
weight = models.DecimalField(max_digits=12, decimal_places=3)
# and more [...]
class HardwareManager(models.Manager):
def create(self, *args, **kwargs):
if 'type' in kwargs and kwargs['type'] is str:
kwargs['type'] = HardwareType.objects.get(name=kwargs['type'])
super(HardwareManager, self).create(*args, **kwargs)
class Hardware(models.Model):
objects = HardwareManager()
type = models.ForeignKey(HardwareType)
# some attributes
is_installed = models.BooleanField()
location_installed = models.TextField()
# and more [...]
# so then I should be able to do:
new_hd = Hardware.objects.create(type='ND35001', is_installed=True, ...)
но я продолжаю получать ошибки и действительно странное поведение от ORM (у меня их нет прямо здесь, но я могу опубликовать их, если нужно). Я искал в документации Django и потоках SO, но в основном я заканчиваю на решениях, где:
- the
Hardware.save()
метод переопределен (должен ли я получитьHardwareType
есть ?) или - менеджер определяет новый
create_something
метод, который называетself.create()
.
я также начал копаться в коде и увидел, что Manager
это какой-то особый вид QuerySet
но я не знаю как продолжить оттуда. Я бы очень хотел заменить create
метод на месте, и я не могу с этим справиться. Что мешает мне делать то, что я хочу сделать?
2 ответов
не видя обратной связи, я думаю, что проблема находится на этой линии.
if 'type' in kwargs and kwargs['type'] is str:
это проверка, является ли kwargs['type']
- Это тот же объект, что и str
, которому всегда будет ложным.
в Python 3, чтобы проверить, является ли'kwargs ['type'] строкой, вы должны сделать:
if 'type' in kwargs and isinstance(kwargs['type'], str):
если вы используете Python 2, вы должны использовать basestring
, чтобы поймать байтовые строки и строки unicode.
if 'type' in kwargs and isinstance(kwargs['type'], basestring):
представление от Аласдерответ очень помог поймать как строки, так и строки unicode, но на самом деле не хватало return
оператор перед вызовом super(HardwareManager, self).create(*args, **kwargs)
на HardwareManager.create()
метод.
ошибки, которые я получал в своих тестах вчера вечером (устал, Когда кодирование не является хорошей идеей: P) были ValueError: Cannot assign None: [...] does not allow null values.
потому что последующее использование new_hd
что у меня было create()
д None
потому что мой create()
метод не имел return
. Какой глупая ошибка !
окончательный исправленный код:
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)