Returning values from methods in Django - 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

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

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.

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.

Related

In Django what is the method of a `TextField` / `Field` object that returns its content?

In Django when needing to display the content of an object of type django.db.models.fields.TextField in a template, if this object is denoted as textfield, we can display it with the simple {{ textfield }} command.
However, while exploring the code of django.db.models.fields.TextField, I did not find any method returning the content of the TextField. Indeed, while checking django.db.models.fields.TextField and its super class django.db.models.fields.Field I did not find any method that do the job.
Thus, is there such a method returning the content of a TextField or even a Field, else what is the machinery used here to return it ?
That's not how Django fields work. Fields are attributes of the class, not the instance, and are used for loading and saving values from the database; the attribute on the instance is just the plain value.

Django: creating graphs in admin Inlines

I'm working in the admin interface, and I'm trying to create a InlineModelAdmin subclass that given a model will just give me certain values from related values (say, date and value fields) and use them in a subclassed template to build a graph.
Problem is: I don't know what to subclass in the inline!. The inline_admin_formset seems to have the form already cooked and I can't access the date. get_form I can't get to send the data I want to the template. I tried change_view to put the data as extra_context, but it's only called for the parent class. And so on.
Can anyone orient me as to where would be the best place to work?.
I know this would be a lot easier in a custom view, but the high command is adamant that this has to be done in the admin interface.
Thank you!
Looks like I managed to access the raw data from the inline objects using the following code in the template:
<script>
var data = google.visualization.arrayToDataTable([
["Date", "Value"],
{% for form in inline_admin_formset %}
["{{form.original.date}}", {{form.original.value}}],
{% endfor %}
]);
</script>
So it looks like now I only need to parameterize what fields the graph is going to plot from the inline, or from the object (date and value in this case). Perhaps add a graph_fields() method to both.
In any case, thanks to whoever gave this a thought.

How to make a dynamic menu in base template using django

I'm about to start a new project and I think this time django is the way to go. I've been reading the documentation for the past two weeks and it looks promissing.
Ok, the thing is that I could not find anything about (in C# MVC called) Partial Rendering. For example if I want a dynamic menu where the menu-items comes from the database, then I would expect that the base template (or master page) renders the menu on each request (the partial renderer invokes another action or renders a template with some session data). So, the menu comes for free as long as my template inherits from this base template.
Honestly, I have no clue on how to achieve this.
What I would like is some code in the base template that uses data that is not contained in the child template. I don't want to include an extra variable (maybe 'menu_list_items') every time I call render_to_response('child_content.html',context). Is this possible?
Thanks!
You could either use a context processor, or a custom template tag to provide this functionality.
A context_processor is a simple function which can add objects to every RequestContext. A custom template tag can have its own template snippet and context which could render the menu for you.
For the template reusing: you should just create a base template for the generic layout, and use detailed templates for the individual pages. This is already covered in detail by the Django documentation.
What I tend to do for those generic parts (say for example, a menu highlighting the current part of the site the use is on), is to create my own render_to_response functions, akin to the following:
from django.shortcuts import render_to_response as django_render_to_response
def render_to_response(template, params, context_instance):
return django_render_to_response(template,
AppendStandardParams(request, params),
context_instance)
The ApplyStandardParams method then configures the menu based on the current path:
def AppendStandardParams(request, params):
if request.META['PATH_INFO'].startswith('/customer'):
params['category'] = 'customer'
params['title'] = 'Customer overview'
# and so on for all different parts
These category and title tags in this example are some values used to highlight the menu, configure titles, and so on. For example:
<!-- Customer menu entry: change class if this is the current category. -->
<li{% if category == "customer" %} class="selected"{% endif %}>Customers</li>
Finally, to use it in a view, instead of the normal render_to_response import, I just do something like from lib.views import *, which makes my custom version available in the view. This way the syntax of all code in the views stays the same, but I don't have to customize the menu every time I create a new view or app.

Database localization in Django

I am using .mo files for localization in Django.
Also, in my database, I store some translated text in different fields, such as:
name_en, name_es, name_de (they are all columns in each row).
What will be the best method to choose the correct field inside a template?
i.e.:
{{ name.some_method }} will generate the correct translation based on the current localization.
Thanks,
Meit
You should look at http://goodcode.io/articles/django-multilanguage/ Here’s a simple solution that may fit your use case and is easy to implement and understand.
You should look at Django Transmeta, it work the same way as what you've done (DB fields with language code) but it's a more complete solution. It already deal with the template stuff, etc.
You can check Model Internationalization and Django Packages for more info and ideas in this domain.
I can see two method for doing this, one in your view and the other one is in the template...
In view:
Probably you keep the user language information somewhere so,
user_lang = 'es'
obj = Somemodel.objects.get(pk=123434)
obj.local_name = getattr(obj, 'name_%s'%user_lang)
So, you keep local translation in a specific variable of the instance and in your template you can use is as:
{{obj.local_name}}
But that might be costly if you wish to pass the template a queryset instead of a single instance. For a such usege you have to evaluate that value for each object in your queryset.
In template:
That is a more complex way of solving the porblem in the template...
Define a template tag and pass object_id, and local language information and get the translated text using a similar getattr function. But in that point, if you wish to use this for more than one model, you probably have to pass a content type information for your template tag too, such as:
{% get_translation <object_id> <content_type_id> <local_language> %}
And in your template tag function, do something like:
from django.contrib.contenttypes.models import ContentType
....
cont_obj = Content_type.objects.get_for_id(<cotent_type_id>) #get the related model
obj = cont_obj.get_object_for_this_type(pk=<object_id>) # get your object
return getattr(obj, 'name_%s'%<local_language>)

How to sort column fields in Django model.object.values()

I am using this
objects = Model.objects.values('var1', 'var2', 'var4')
IN template i use
{% for fieldname in object.keys %}<th>{{ fieldname }}</th>{% endfor %}
But the field names appear in arbitrary order like
var4---var1----var2
I want them to appear like i provided in function
var1---var2----var4
is this possible
The easiest solution is to just use values_list, which returns tuples and change your template accordingly.
https://docs.djangoproject.com/en/1.3/ref/models/querysets/#django.db.models.query.QuerySet.values_list
If for whatever reason, you want to keep using dict-s, and want an "automagical" solution, you'd have to do quite a bit of work:
Subclass Django's ValuesQuerySet, name it for ex. OrderedValuesQueryset and change it's iterator method to use OrderedDict http://docs.python.org/dev/library/collections.html#collections.OrderedDict
Create a Queryset subclass which
in it's .values method returns an instance of
your OrderedValuesQuerySet
Create a custom models.Manager
class which in it's get_query_set
method uses your custom QuerySet
from 2.
Set the custom Manager to be used in your model. See https://docs.djangoproject.com/en/1.3/topics/db/managers/#custom-managers
Now what you are trying to do will work automatically on that model. You can also set the custom manager to a different attribute than objects, to also keep the default manager available.
The question is rather how to sort a Python dictionary, because this is what values() returns. Python dictionaries by definition do not have an ordering.
See this blog post