Eric Herlitz
Eric Herlitz

Reputation: 26267

Returning values from methods in Django

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

Upvotes: 1

Views: 3927

Answers (3)

Andrea Zilio
Andrea Zilio

Reputation: 4534

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.

Upvotes: 0

Daniel Roseman
Daniel Roseman

Reputation: 599610

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()

Upvotes: 1

gruszczy
gruszczy

Reputation: 42188

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.

Upvotes: 0

Related Questions