1

I have a couple of models that inherit from a parent model.

class ContentItem(models.Model):

    COLUMN_CHOICES = (
        (FIRST_COLUMN, 1),
        (SECOND_COLUMN, 2),
        (THIRD_COLUMN, 3),
    )

    row      = models.ForeignKey(RowItem)
    column   = models.SmallIntegerField(choices=COLUMN_CHOICES, default=FIRST_COLUMN)
    group    = models.IntegerField(default=0, unique=False, null=False, blank=False)

    objects  = InheritanceManager()


class TextItem(ContentItem):

    title    = models.CharField(max_length=500, unique=False, null=True, blank=True)
    content  = models.TextField(max_length=50000, unique=False, null=True, blank=True)

class FaqItem(ContentItem):

    question = models.TextField(max_length=1000, unique=False, null=True, blank=True)
    answer   = models.TextField(max_length=5000, unique=False, null=True, blank=True)

I'm using the InheritanceManager from Django Model Utils for help with returning the child model and not the parent.

Content objects belong to a row, a column, and optionally, a group of content objects.

When I query ContentItems with ContentItem.objects.filter(row__page=page).select_subclasses() I get something like this [<FaqItem: FaqItem object>, <FaqItem: FaqItem object>, <TextItem: TextItem object>].

I can get so far with the data in his structure but I've hit a wall and can't achieve the desired complex HTML layout in the template, specifically with the optional grouping of objects by the group field.

I think having the data in a nested structure would make it easy to loop over and create the desired template layout of rows containing columns containing content items - some of which are grouped, some of which stand alone. i.e like this interpretation:

content_items {
    'rows': {
        0: {
            'columns': {
                0: {
                    'faq_items': {
                        'groups': {
                            0: {
                                faq_obj,
                                faq_obj,
                            },
                            1: {
                                faq_obj,
                                faq_obj,
                                faq_obj,
                            },
                        },
                        faq_obj,
                    'text_items': {
                        'groups': {
                            0: {
                                text_obj,
                                text_obj,
                            },
                        },
                        text_obj,
                        text_obj,
                        text_obj,
                    }
                1: ...
            },
        },
        1: ...
    }
}

Is this possible / advisable? Or is there a way I can do it in the template. It currently looks like this:

{% for content_item in content_items %}
    {% if content_item.row == row and content_item.column == column_number %}
        <div class="content-item">
            {% include "content-item.html" %}
        </div>
    {% endif %}
{% endfor %}

'row' and 'column_number' are passed into this template include. This works ok. But when content items are in the same group, I want to bypass the <div class="content-item"> div so I can visually tie content items belonging to the same group together.

Jack
  • 307
  • 4
  • 15

1 Answers1

1

This answer showed me to create a nested object from a queryset, grouping on more than one model field - Nested GROUP BY in django: returning Objects. I came up with this:

content_items        = ContentItem.objects.filter(row__page=page).select_subclasses()
content_items_sorted = {}

for row, first_group in groupby(content_items, lambda x: x.row):
    content_items_sorted[row] = {}
    for column, second_group in groupby(first_group, lambda x: x.column):
        content_items_sorted[row][column] = {}
        for group, third_group in groupby(second_group, lambda x: x.group):
            content_items_sorted[row][column][group] = list(third_group)

Now I can loop through the rows, columns and groups in the template using nested for loops.

Community
  • 1
  • 1
Jack
  • 307
  • 4
  • 15