定制django foreignfield

dur*_*enk 6 django django-models

任何人都知道如何创建一个foreignkey字段,并使它始终指向相同的模型,到目前为止,我得到了这些.

class PanMachineTimeUnitField(models.ForeignKey):
    def __init__(self, **kwargs):
        to = 'panbas.PanBasTimeUnit'
        kwargs['verbose_name'] = _('Machine Unit')
        kwargs['related_name'] = 'machine_unit'
        super(PanMachineTimeUnitField, self).__init__(to, **kwargs)
Run Code Online (Sandbox Code Playgroud)

但是我在开始时遇到了错误.我的目标是使用它,

machine_unit = PanMachineTimeUnitField()
Run Code Online (Sandbox Code Playgroud)

无需进一步声明.

编辑:我想要这个,因为,我会在几个地方安静地使用这个外键.如果我想更改字段的verbose_name,我希望我的所有字段都受此更改的影响.详细名称就是一个例子,它可能是另一个属性.

我不想使用设置py来声明默认值.

hyn*_*cer 7

我建议你只使用一个简单的函数来创建一个类似的预先配置的ForeignKey实例:(不是ForeignKey的子类的实例)

def pan_machine_time_unit_field(**kwargs):
    othermodel = 'panbas.PanBasTimeUnit'
    on_delete = models.DO_NOTHING  # or what you need
    kwargs['verbose_name'] = 'Machine Unit'
    kwargs.setdefault('related_name', '+')
    # or: kwargs.setdefault('related_name', "%(app_label)s_%(class)s_related",
    return models.ForeignKey(othermodel, on_delete, **kwargs)

class C(models.Model):
    machine_unit = pan_machine_time_unit_field()
    # or:
    # machine_unit = pan_machine_time_unit_field(related_name='klass_c_children')
Run Code Online (Sandbox Code Playgroud)

related_name属性是用于从目标对象othermodel到引用它的所有对象的向后关系的名称.这名必须是othermodel("panbas.PanBasTimeUnit",通常是一些与应用程序和类名是足够唯一的)唯一或者该名称可以'+',如果你不希望创建一个落后的关系查询集.这两个变体都隐含在示例中.还记得on_delete.

如果您真的需要创建一个子类(如果需要自定义更多方法,这是有意义的),您还必须定义一个deconstruct迁移方法.如果您稍后需要修改这样的子类,那将会很复杂.由于自定义字段上的迁移,它永远不会被删除,重命名等.另一方面,如果您通过函数直接创建一个简单的ForeignKey实例,则可以忽略所有关于迁移的操作.


编辑

或者,您可以使用该字段创建抽象基础模型,并通过继承或多重继承创建新模型:

class WithPanBasTimeUnit(models.Model):
    machine_unit = models.ForeignKey(
        'panbas.PanBasTimeUnit',
        models.DO_NOTHING,
        verbose_name=_('Machine Unit'),
        related_name='%(app_label)s_%(class)s_related'
    )

    class Meta:
        abstract = True

class ExampleModel(WithPanBasTimeUnit, ...or more possible base models...):
    ... other fields
Run Code Online (Sandbox Code Playgroud)

如果您想要将方法添加到具有该字段的模型或将更多字段添加到一起,则此解决方案(受无效的Ykh启发)非常有用,否则原始解决方案更容易.


Ykh*_*Ykh 6

class PanBasTimeUnit(models.Model):
    machine_unit = models.ForeignKey('self', blank=True, null=True,
                               verbose_name=u'parent')
Run Code Online (Sandbox Code Playgroud)

使用'self''panbas.PanBasTimeUnit'将罚款.