【问题标题】:Django-Tables2 add extra columns from dictionaryDjango-Tables2 从字典中添加额外的列
【发布时间】:2018-08-14 17:39:23
【问题描述】:

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

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

# 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
        ...

我现在如何使用这个返回的字典并将其拆分为我的 Product 表中的列?除了我的做法之外,还有其他方法可以使用访问器吗?

【问题讨论】:

    标签: python django django-models django-tables2


    【解决方案1】:

    您可以使用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”方法有点碍事,你应该改变你传递给表的 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})
    

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

    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

    【讨论】:

    • 谢谢!这正是我一直在寻找的。我很沮丧,虽然没有办法订购它。有没有一些解决方案可以让我对其进行排序?
    • 如果您使用不同的查询来选择表格的数据会更容易,我认为您可以使用 FilteredRelation 绕过您的自定义方法,也允许 django/django-tables2 知道如何在这些列上排序。
    • 你能给我一个例子来说明如何在我的情况下使用 FilteredRelation 或者至少是一个简短的描述吗?我应该在我的 Product 模型中创建一个方法来返回 ProductDetaisState.objects.annotate(currentState=FilteredRelation(...)) 之类的东西吗?
    • 等一下,我深入研究了这个,但仍在研究如何很好地进行排序。
    • 这也可能会给你更多灵感,至少这是我在更新答案时提到的:stackoverflow.com/questions/2074514/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-21
    • 1970-01-01
    • 2021-02-16
    • 1970-01-01
    • 2015-06-19
    • 2019-12-30
    • 2019-04-15
    相关资源
    最近更新 更多