python - 如何覆盖 Django 中的 model.Manager.create() 方法?

标签 python 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 线程中进行了搜索,但大多数情况下我最终找到了以下解决方案:

  • Hardware.save() 方法被覆盖(我应该在那里获取 HardwareType 吗?)或者,
  • 经理定义了一个新的 create_something 方法,该方法调用 self.create()

我也开始深入研究代码,发现 Manager 是某种特殊的 QuerySet 但我不知道如何从那里继续。我真的很想替换 create 方法,但我似乎无法管理它。是什么阻碍了我做我想做的事?

最佳答案

来自 Alasdair 的见解的答案对捕获字符串和 unicode 字符串有很大帮助,但实际上缺少的是调用 super(HardwareManager, self).create(*args, * 之前的 return 语句*kwargs)HardwareManager.create() 方法中。

昨天晚上我在测试中遇到的错误(当编码不是一个好主意时很累 :P)是 ValueError: Cannot assign None: [...] does not allow null values. 因为 create()d 的 new_hd 的后续使用是 None 因为我的 create() 方法没有返回。多么愚蠢的错误!

最终更正后的代码:

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)   

关于python - 如何覆盖 Django 中的 model.Manager.create() 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34899520/

相关文章:

python - 获取 Azure 中连接到不同订阅中的工作区的虚拟机的日志分析工作区 ID

django - 查询集引发 : Related Field got invalid lookup: icontains

Django 按字段聚合,没有相关名称

css - 从 Django CMS 中删除默认 CSS

python - Bokeh 点击工具在垂直线上选择

python - lxml.html 的值属性

Django模型选择字段: Huge List of choices

python - 将数据迁移作为大型 Django 迁移中的一项操作是否安全?

python 3从文本文件中查找并打印整数

python - 获取有向无环网络组件中的有序节点 x DiGraph