How to create crosstab SQL query with Django ORM?

Using Django 1.1, how can I create a crosstab (pivot table) SQL query using ORM?

UPDATED: These are models and release requirements:

class Store(models.Model):
    name = models.CharField(max_length=255)
    ...

class Order(models.Model):
    store = models.ForeignKey(Store, blank=True, null=True, related_name='orders')
    description = models.CharField(_('Description'), max_length=255)
    quantity = models.IntegerField(blank=True, null=True)       
    type_detail = models.CharField(_('Type Detail'), max_length=255)
    slug = models.SlugField(blank=True)
    cost = models.DecimalField(_("Cost"), max_digits=14, decimal_places=2)
    modified = models.DateTimeField(_('modified'), auto_now=True)

Currently, the view displays the following data:

Store   | Type Detail  | Quantity 
----------------------------------
Walmart | Floor polish | 2        
Walmart | Tiles        | 1        
Walmart | Milk         | 4      
Another | Floor polish | 2        
Another | Tiles        | 1        
Another | Milk         | 4        

I want to configure this to view the data as follows:

For the store I need to know the quantities

Store   | Floor polish  | Tiles | Milk
------------------------------------------------
Walmart | 2             | 1     | 4
Another | 2             | 1     | 4

Hope this explains what I need.

+3
source share
3 answers

You can do this in the template as follows (assuming that you pass line_items to your template, and also provided that store.name is a unique property):

{% regroup line_items by store.name as store_items %}
{% for store in store_items %}    
  <tr>
    <td>{{ store.grouper }}</td>
    {% for item in store.list %}
      <td>{{ item.count }}</td>
    {% endfor %}
  </tr>
{% endfor %}

, , (, 0 )

+3

- . (. ). Django, doctext. , 1) Store, 2) type_detail 3) type_detail. (store, type) = > .

class Cube(object):
    """Iterable sparse cube. Iterating gives an item for every dimension member.

    >>> pythons = ['eric', 'john', 'terry']
    >>> cheeses = ['limburg', 'feta', 'parmigiano']
    >>> cheese_consumption = {
        ('eric', 'limburg'): 2,
        ('eric', 'parmigiano'): 4,
        ('john', 'feta'): 5
    }
    >>> cheese_cube = Cube((pythons, cheeses), cheese_consumption)
    >>> for python, python_cheeses in cheese_cube:
        for cheese, consumption in python_cheeses:
            print python, cheese, consumption or 0

    eric limburg 2
    eric feta 0
    eric parmigiano 4
    john limburg 0
    john feta 5 
    john parmigiano 0
    terry limburg 0
    terry feta 0
    terry parmigiano 0
    """
    def __init__(self, dimensions, facts, slice=None):
        self.dimensions = dimensions
        self.data_dict = facts
        self.slice = slice or ()
    def __iter__(self):
        if len(self.slice) + 1 < len(self.dimensions):
            for item in self.dimensions[len(self.slice)]:
                yield item, Cube(self.dimensions, self.data_dict, self.slice + (item,))
        else:
            for item in self.dimensions[len(self.slice)]:
                yield item, self.data_dict.get(self.slice + (item,), None)
+2

I do not know about Django, but here is plain SQL

SELECT Store,
SUM(CASE WHEN Type_Detail = 'Floor polish' THEN Quantity ELSE 0 END) as 'Floor polish',
SUM(CASE WHEN Type_Detail = 'Tiles' THEN Quantity ELSE 0 END) as 'Tiles',
SUM(CASE WHEN Type_Detail = 'Milk' THEN Quantity ELSE 0 END) as 'Milk'
FROM Order
GROUP BY Store
-1
source

Source: https://habr.com/ru/post/1724931/


All Articles