Django-Tables2 从字典中添加额外的列

Django-Tables2 add extra columns from dictionary

如果之前有人问过这个问题,但我找不到我的具体用例的答案,我深表歉意。

我有一个显示基本产品信息的 table。价格、销售数量和卖家数量等产品详细信息会定期收集并存储在单独的数据库中 table。现在我想在前端使用 tables2 在一个 table 中显示基本产品信息和抓取的详细信息。为此,我在我的产品模型中编写了一个函数来获取最新的详细信息并将它们 return 作为字典,这样我就可以使用单个访问器调用。

# models.py

class Product(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)

    name = models.CharField(max_length=256)
    brand = models.ForeignKey(Brand)
    category = models.CharField(max_length=128, choices=CATEGORY_CHOICES)

    def __unicode__(self):
        return self.name

    def currentState(self):
        currentDetailState = ProductDetailsState.objects.filter(
            product=self
        ).latest('created_at')

        # return current details as a dictionary
        return {
            price: currentDetailState.price,
            num_sellers: currentDetailState.num_sellers,
            num_sales: currentDetailState.num_sales
        }


class ProductDetailsState(models.Model):
    product = models.ForeignKey(Product)
    created_at = models.DateTimeField(auto_now_add=True)

    price = models.DecimalField(max_digits=6, decimal_places=2, null=True)

    num_sellers = models.IntegerField(null=True)
    num_sales = models.IntegerField(null=True)

    def __unicode__(self):
        return self.created_at



# tables.py

class ProductTable(tables.Table):
    productBrand = tables.Column(
        accessor=Accessor('brand.name'),
        verbose_name='Brand'
    )
    currentRank = tables.Column(
        accessor=Accessor('currentRank')
    )

    class Meta:
        model = Product
        ...

我现在如何使用这个 returned 字典并在我的产品 table 中将其拆分为多个列?除了我的做法,还有其他使用访问器的方法吗?

你可以使用 Accessor 遍历字典,所以像这样的东西应该可以工作:

class ProductTable(tables.Table):
    # brand is the name of the model field, if you use that as the column name, 
    # and you have the __unicode__ you have now, the __unicode__ will get called, 
    # so you can get away with jus this:
    brand = tables.Column(verbose_name='Brand')
    currentRank = tables.Column()

    # ordering on the value of a dict key is not possible, so better to disable it.
    price = tables.Column(accessor=tables.A('currentState.price'), orderable=False)
    num_sellers = tables.Column(accessor=tables.A('currentState.num_sellers'), orderable=False)
    num_sales = tables.Column(accessor=tables.A('currentState.num_sales'), orderable=False)

    class Meta:
        model = Product

虽然这很有效,但排序也很不错。为此,您的 'currentState' 方法有点碍事,您应该将传递给 table 的 QuerySet 更改。此视图显示了它的工作原理:

from django.db.models import F, Max
from django.shortcuts import render
from django_tables2 import RequestConfig

from .models import Product, ProductDetailsState
from .tables import ProductTable


def table(request):
    # first, we make a list of the post recent ProductDetailState instances
    # for each Product.
    # This assumes the id's increase with the values of created_at, 
    # which probably is a fair assumption in most cases.
    # If not, this query should be altered a bit.
    current_state_ids = Product.objects.annotate(current_id=Max('productdetailsstate__id')) \
        .values_list('current_id', flat=True)

    data = Product.objects.filter(productdetailsstate__pk__in=current_state_ids)

    # add annotations to make the table definition cleaner.
    data = data.annotate(
        price=F('productdetailsstate__price'),
        num_sellers=F('productdetailsstate__num_sellers'),
        num_sales=F('productdetailsstate__num_sales')
    )
    table = ProductTable(data)
    RequestConfig(request).configure(table)

    return render(request, 'table.html', {'table': table})

这简化了 table 定义,使用上面创建的注释:

class ProductTable(tables.Table):
    brand = tables.Column(verbose_name='Brand')
    currentRank = tables.Column()

    price = tables.Column()
    num_sellers = tables.Column()
    num_sales = tables.Column()

    class Meta:
        model = Product

您可以找到完整的工作 django 项目 at github