Code

CookBook - Data Model

Multiple Levels and Multiple Components

Description

There are times when you have data/content that has many-to-one relationships. This is very easy to accomodate, just as this example demonstrates. Here is code similar to that of the example:

from django.core import meta

class Document(meta.Model):
    short_name = meta.CharField(maxlength=30)
    title = meta.CharField(maxlength=100)

    def __repr__(self):
        return self.title

    class META:
        admin = meta.Admin()

class Paragraph(meta.Model):
    document = meta.ForeignKey(
            Document, 
            edit_inline=True, 
            num_in_admin=3, 
            num_extra_on_change=1 )
    content = meta.TextField()

    def __repr__(self):
        return self.headline

This is fantastic. It's convenient. But... what if we have more than just two "levels"? What if our document data is divided into two types of data, say "summary" and "details"? And what if each of these views then has potentially multiple paragraphs?

Stay tuned; more to come...

Code

API Usage

See Also

A New Beginning

I haven't a clue where this was intended to go, but I've recently started working with something that has such multilevel 1:many relations. And I've seen questions about this even in the relatively little time I've spent on #django, so maybe even these sketchy notes will be useful.

Imagine a Perfectly Spherical Poll…

So a poll is one, with many related questions; likewise, each question has multiple related answers. One of my first cuts, inspired no doubt by having just learned about Django's template faciltiies, hence wanting to use them, looked something like this:

<form action="/poll/submit/{{ poll.poll_id }}/{{ raw_args }}" method="post">
<ol>
{% for q in poll.get_question_list %}
  <li>{{ q.prompt }}
  {% for a in q.get_answer_list %}
    <br /><input type="radio" name="question_{{ q.question_id }}" value="{{a.answer_id }}">{{ a.response }}
    {% endfor %}
  {% if arg.show_blank %}
    <br /><input type="radio" name="question_{{ q.question_id }}" value="-1"><input type="text" name="new_q_{{ q.question_id }}">
  {% endif %}
{% endfor %}
</ol>
<input type="submit">
</form>

This requires really minimal setup in the view code - load the poll, set it up in the context dictionary that you'll pass to the rendering function, and there you go. The virtue of simplicity, but also the limitations, as I discovered.

It was about that time that the Vogons came along

Well, maybe it was a few minutes later. But I wanted to add some other features, such as an add-your-own-answer choice, but that needed to be conditional, and so forth. And I ran into the simple reality that the template language gets really ugly really fast if you need to do too much logic in it. Like, for example, adding the logic to set the radio button for a set of choices already made in the above display. Or if the ordering of the nested data isn't what you wanted. So I migrated some of the logic back into the view, and added a chosen_one attribute to the answers to make the template as simple as possible. I think this is a generally good approach, even though I didn't get any opinions one way or the other when I asked #django for such. So we'll see...

Last modified 8 years ago Last modified on 03/03/06 17:45:42