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
毎回取得する必要があり、これはあまり DRY ではありません。
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 スレッドで検索しましたが、ほとんどの場合、次のような解決策にたどり着きます。
- メソッド
Hardware.save()
がオーバーライドされます(HardwareType
そこで を取得する必要がありますか?)または、 - マネージャーは
create_something
を呼び出す新しいメソッドを定義しますself.create()
。
私もコードを詳しく調べ始めて、 がManager
何らかの特別なものであることを知りましたQuerySet
が、そこから先をどう進めればよいかわかりません。 メソッドを置き換えたいのですcreate
が、どうもうまくいきません。やりたいことを実行できないのはなぜでしょうか?
ベストアンサー1
からの洞察アラスデアの回答は、文字列と Unicode 文字列の両方をキャッチするのに大いに役立ちましたが、実際に欠けていたのは、メソッド内のreturn
の呼び出しの前のステートメントでした。super(HardwareManager, self).create(*args, **kwargs)
HardwareManager.create()
昨日の夕方のテストで発生したエラー (コーディング中に疲れるのは得策ではありません :P) は、メソッドに がなかったためにdを使用した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)