views:

42

answers:

3

Hi! So, time for a newbie question but so utterly important since the documentation seems to have missed this very very basic example.

All I'm trying to do is to return a value from a model to a view in Django. Here is some code.

The model

class Page(models.Model):
    def index(self):
      ex = 'foo string'
      return ex

The view

def index(request):
    start = Page.objects.all().index
    #start = Page.index
    return render_to_response('index.html', {'page_content': start})

And, nothing gets rendered. I get this error message with <unbound method Page.index>

...

The funny thing is that if I skip the functions and so on and creates the model like this

class Page(models.Model):
    ex = 'goo string'

And call it with

start = Page.ex

Everything renders out fine.

Any pointer or working example would be much appreciated! Thanks

A: 
Page.objects.all()

returns you a query set of Page objects, not a single Page object. You can call Page.objects.all()[0].index.

To render it right, I believe you should pass Page.objects.all() to the template and then iterate over it in the template, like this:

{% for page in page_content %}
  {{ page.index }}
{% endfor %}

If you define an attribute like this:

class Page:
  ex = 'some char'

then you are creating class attribute, which can be accessed in a class and in every instance of that class (it is shared by all those objects). This is not an instance attribute.

gruszczy
Ok, is there any way I could as the def directly? Just like`start = Page.index`?Thanks
Trikks
A: 

In Django you have two types of custom database objects methods: row (or instance) based methods, table based methods.

Row based methods:

You just define a method in the model class like you did:

class Page(models.Model):
    def row_method(self):
        return "Row method working on Page object with id " + str(self.id)

This methods are meant to be called from a single Page object!

So you can do: Page.objects.all()[0].row_method(), but you can NOT do Pages.objects.all().row_method because Pages.objects.all() returns an array of Page objects for which the row_method() method is not defined.

These methods are row based because they act at row level (a single row in the DB table and so a single instance of the relative model class).

Table based methods:

You can also define methods related to a specific model type and not to a specific instance using Managers. You can find documentation about Manager here: http://docs.djangoproject.com/en/1.2/topics/db/managers/

These type of methods are available when managing a collection of Page objects, for example you could write:

Page.objects.filter(title__startswith='The').calculate_total_title_length()

In this case the method has access to the collection of Page objects returned from the query and, in my example, it calculates the sum of all the titles length of all the Page objects found by the query.

Andrea Zilio
Thanks, but do I have do import something to make this work?
Trikks
+1  A: 

This sort of thing is rightly left out of the Django tutorial, since it has nothing to do with Django. If you don't know basic Python, then you need to follow a Python tutorial.

The main thing wrong with the code you gave is that you haven't actually called the index method, you've just referred to it. In Python, as in many other languages, to call a method you need to use method(). So you need:

Page.objects.all()[0].index()
Daniel Roseman
Hmm, do I have do import something to make this work?
Trikks
Thanks but passing variables and values between python and Django are two very different things since Django is a framework. And what I'm trying to figure out is how to pass static values from a model to a view. If everything where to function as in Python, my example above should have worked, or it does with Py, but not with Django.Now, your solution seems to be the correct since I got the same answer from others here. However, setting up with that gives me the error`list index out of range`Unfortunately
Trikks
No, it would not work in Python. Django is Python, anyway. Index is a method, and in Python you need to *call* methods. List index out of range is because you don't have any Page instances in your database.
Daniel Roseman
Right, ok thanks. So what I'm trying to do isn't really possible since Django bundles the models are explicit for usage with the database. I solved the problem by creating a model.py and imported it with `from model import *`Thanks!
Trikks