Database localization in Django - 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>)

Related

Conditional tags in templates

I'm using Django on top of an existing database/user framework so unfortunately it is not possible to me for use the django auth framework.
I have my custom auth library built, now I just need to figure out how to use it in templates. Certain links should only appear for users who have access to it.
In PHP I could do soemthing like this
<?php if auth('RestrictedLinkName') {?> <?php } ?>
What is the Django way? I have been playing with custom tags but haven't been able to get it working yet. I was thinking something like:
{% if check_permission('Restrictedarea') %} hjkfgdkhfg {% endif %}
If you need to evaluate check_permission('Restrictedarea') then do it in the view function and pass the evaluated result in the template.
The djangobook says (in Chapter 4: Templates, in Philosophies and Limitations section) -
Business logic should be separated from presentation logic. Django’s
developers see a template system as a tool that controls presentation
and presentation-related logic – and that’s it. The template system
shouldn’t support functionality that goes beyond this basic goal.
For that reason, it’s impossible to call Python code directly within
Django templates. All “programming” is fundamentally limited to the
scope of what template tags can do. It is possible to write custom
template tags that do arbitrary things, but the out-of-the-box Django
template tags intentionally do not allow for arbitrary Python code
execution.
And if need to write custom tags check these links:
Writing a Template Tag in Django
Custom template tags and filters
You can write your custom template tags and filters. But this may help you up to a point, for further, you must write your custom context_processors (and custom middlewares if needed.)
But doing authentication and permission check through custom function is quite hard, but possible. I have a system fully runs on custom authentication/authorization.
First of all, you can examine django context_processors to understand how they work. then you can write your custom context_processor. After you add your context processor in your settings, you can use those methods, and do your authentication/authorization as you wish.
One of my custom contect_processor function is like:
from django.utils.functional import lazy
def CustomProcessor(request):
cust_perms = {
'admin_perm_check': lazy(lambda: myCustomPermChecker(request), myCustomPermChecker)(),
'system_admin': aFunctionToReturnBoolValue(),
}
return custom_perms
class myCustomPermChecker(object):
def __init__(self, request):
self.request = request
def __getitem__(self, perm_name):
return True if (perm_name in user_perm_list()) else False
In your template
{%if admin_perm_check.perm_name%}...{%endif%}
{%if system_admin %} this is a bool check{%endif%}
You must define your permchecker as a class, which have __getitem__ method so, your template tag admin_perm_check.perm_name could work. This perm checker accepts only one additional paramater (perm_name), If you want to use django-style two parameter check then you must do:
class myCustomPermChecker(object):
def __init__(self):
pass
def __getitem__(self, module_name):
return SecondPermCheckerStep(module_name)
class SecondPermCheckerStep(object):
def __init__(self, module_name):
self.module_name = module_name
def __getitem__(self, perm_name)
return True if ('%s.%s' % (self.module_name,perm_name) in user_perm_list()) else False
{%if admin_perm_check.module_name.perm_name%}
You can use another class.__getitem__ to add one more key to tour tag chain in your template etc.
Since your context_processor CustomProcessor(request): accept http.request object as a parameter, you can pass your methods or functions any value (session id or user id etc.) that will be required in authenticaon or authorization. You can write a middleware to set custom values to your request object to use (like django set user instance and let you use request.user in your views.). You can also set your custom user model instance so you can use it in you template (if you set it in your request_context) and in your views (if you set it in your middleware)
Reading docs could not help here much, better is checking django code to see how django handle this.

Django's equivalence of ASP.NET UserControl

If anyone here is ASP.NET pro, you might know what I mean by user control. I wish to create a similar one in django instead.
So, my problem is that I have several pages in my website, but I need a search bar to appear in every pages. Since I require the views.py to operate this search bar, I cannot do a simple method of
{% include 'something.html' %}
Therefore, can anyone suggest how can I do it?
There are a couple of ways to accomplish what you're wanting to do:
Context Processors
Template Tags
Context Processors can augment the template context with values, regardless of which template is loaded. They are akin to filters in Rails.
Template Tags, like Context Processors, can accomplish anything you can do in Python, but are implemented at the template level.
If you need something to be present on every template, one of the simplest ways to accomplish this is with an inclusion tag, which can also accept values passed to it. An inclusion tag could be implemented at your highest level template, a.k.a your MasterPage, and as long as you don't put it in a block and override it, it would appear on every page that includes that template in its inheritance chain.
If it's just something you want to include on every page, and it doesn't need to do any processing, you should just be able to place the code you want in the top-most template and have subsequent templates inherit that.
I typically have a "base.html" template that all of my templates inherit from. If I need something to be in every page, I put it there. If it's something I want there by default, but want to be able to augment it in subsequent templates, I will place it into a block. That block will let you include or override its default content.
I know this post is kind of old but I just came across it and found a kind-of-solution that works. I call it kind-of-solution because it is a workaround.
I have a few different sites on which I want to display logging information. This display always looks the same (it has the same html) and has the same database table and model class behind it.
My solution/workaround uses the django filters:
in views.py I put the list of log-entries in the context
context = {'list_log': Log.objects.filter(condition = True) }
template = loader.get_template('my_html_file.html')
return HttpResponse(template.render(context, request))
in my_html_file.html I use a custom filter
{{ list_log|get_log_uc|safe }}
in the filters.py I load another html file with this custom filter
#register.filter
def get_log_uc(list_log):
template = loader.get_template('user_control_log.html')
context = { 'list_log' : log }
return template.render(context)
in user_control_log.html I have the user control equivalent html
{% for log in list_log %}
<p>log.something</p>
{% endfor %

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

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
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.

Filtering models with inheritance in Django

I have two Django model classes that are structured similar to the following:
class Build(models.Model):
project = models.CharField(max_length=100)
...
class CustomBuild(Build):
custom_type = ...
...
I want to select all Builds and CustomBuilds (each CustomBuild has a one-to-one relationship with a Build) from the database with a specific project attribute.
I believe Build.objects.filter(project="myproject") will select the correct objects but many of them will be missing the additional data (such as custom_type) that would be provided by a CustomBuild object. On the other hand, filtering CustomBuild.objects will exclude those objects that are not CustomBuilds.
How can I accomplish this? Thanks.
There are a couple approaches you can take to handling the QuerySets of "mixed models" that you obtain when you perform this kind of query. A lot of it depends on your ultimate goal.
The "simple and dumb" way, which I use a lot, is to manage the results with utility functions. If you plan to process the result of Build.objects.filter(project="myproject") in a template, for example, you could use custom template tags or filters to take special action. Assume in the below code build_objects contains the result of your filter():
{% for build in build_objects %}
{% if build|is_custom_build %}
<p>This is a custom build of custom type {{ build.custom_build.custom_type }}!</p>
{% endif %}
<p>This is a custom build OR a standard build</p>
{% endfor %}
The obvious problem here is if you have numerous subclasses, writing template filters may be impractical or grow tedious. However, in my experience I usually have a half-dozen subclasses at most so this is not always a problem.
You could also write a parameterized filter like so:
{% if build|is_of_buildtype:"custom_build" %}
With the filter code as follows:
def is_of_buildtype_filter(value, arg):
if hasattr(value, arg): return True
else: return False
This filter simply checks for the presence of the argument as an attribute on the build object (passed in as value). The argument string should be the name of the automatically generated OneToOneField that you want to detect, in this case custom_build.
For view code, similar sorts of helper functions would work the same way but are even easier because you don't need to write custom filters or tags.
This approach works in many cases, but there are more complicated scenarios where it might not be practical. Unfortunately, Django cannot natively provide you with a QuerySet that contains subclass instances when you perform operations on the base class (ie. a QuerySet that truly contains "mixed models"). You may require this in situations where processing the results with helper functions is not possible.
I personally avoid these situations entirely, usually by rethinking my model design. But if that's not possible, there are many interesting attempts at solutions, like this Inheritance MixIn. There are also several Django snippets on the subject. Be aware, though, that almost any solution like this will be performance-limited.
You can fetch Build objects with Build.objects.filter() and access the subclass when you need to:
qs = Build.objects.all()
build_obj = qs[4]
custom_build_obj = build_obj.custom_build
custom_build_obj.custom_type = ...