django-tables2上的自定义列混合了多个外键

时间:2018-02-14 22:50:45

标签: django django-tables2

我正在尝试使用一个函数在django-tables2上创建一个自定义列,该函数从3个可能的外键返回非空字段(只有一个可以不为空)。这就是我所做的:

Models.py

class Sitiocancelado(models.Model):
    x = models.OneToOneField(X, on_delete=models.CASCADE, null=True,blank=True)
    y = models.OneToOneField(Y, on_delete=models.CASCADE, null=True, blank=True)
    z = models.OneToOneField(Z, on_delete=models.CASCADE, null=True, blank=True)
    fecha_de_cancelacion = models.DateField(null=True, blank=True)
    comentarios = models.TextField(max_length=200, null=True, blank=True)
    slug = models.SlugField(max_length=100, editable=False)

    def __str__(self):
        return self.z.y.x.nombre_del_sitio

Tables.py

class SitiocanceladoTable(tables.Table):

    def columna_combinada(table):
        if x == None:
            if y == None:
                return z
            else:
                return y
        else:
            return x

    Sitio = tables.Column(columna_combinada)

    class Meta:
        model = Sitiocancelado
        attrs = {
        'class': 'table table-striped table-bordered', 
        'id': 'example', 
        'width' : '100%', 
        }
        fields = ('Sitio',)
        exclude = ('id', 'slug','sitioproyecto', 'sitiocontratado', 'sitiooperando',)

它有意义吗?

1 个答案:

答案 0 :(得分:0)

这不是自定义列的工作方式。你基本上有两个选择:

render_<columnname>

这看起来有点像你的例子。在名为render_<column name>的表类上定义列和方法。无需将该名称提供给您定义的列。你的例子看起来像这样:

class SitiocanceladoTable(tables.Table):
    Sitio = tables.Column(empty_values=())

    class Meta:
        model = Sitiocancelado

    def render_Sitio(self, record):
        if record.x == None:
            if record.y == None:
                return record.z
            else:
                return record.y
        else:
            return record.x

这种方法适合一次性使用。它没有多少额外的代码,代码与表的其余部分非常接近。

请注意,我添加了emtpy_values=()。这将确保使用渲染函数的自定义实现,即使django-tables2认为您的列为空。自定义列的责任是呈现正确的默认值。

Subclassing Column

如果您需要在多个表中使用此列的功能,或在同一个表中多次需要此功能,那么继承Column或其中一个specific Column实现可能会更清晰。

您的示例可能如下所示:

class CombinedFKColumn(tables.Column):
    def render(self, record):
        return getattr(record, 'x', getattr(record, 'y', getattr(record, 'z', self.default)))

class SitiocanceladoTable(tables.Table):
    Sitio = tables.CombinedFKColumn(empty_values=())

    class Meta:
        model = Sitiocancelado