Dynamic name variable on django template - django

I'm having a problem with django. I have a dict with all my site texts for translations. For example:
term = {"level_1": "Noob",
"level_2": "Noob 2"}
The problem is, how can I access this key on django template?
I have
img src="/images/level_{{player.level.id}}.jpg"
title="{{term.level??????? }}"
I tried:
title="{{term.level{{player.level.id}}}}
but of course this didn't work.

Django's template language is (by design) pretty dumb/restricted. In his comment, Davind Wolever points at Accessing a dict by variable in Django templates?, where an answer suggests to make a custom template tag.
I think that in your case, it is best to handle it in your view code. Instead of only passing along a player into your context, pass both the level ID and the level name.
Possibly you can even directly pass the image url and the level name? Not constructing the URL in your template makes it more readable.

Related

How can I pass a variable to all the HttpResponse?

I am learning Django and I want to list in all my pages the categories, that are for example categories = Category.objects.all(), but I think it's very redundant to declare that variable in all my views and pass it in every HttpResponse. Is there any way to do it for all?
If you want to add categories to all the pages it may be useful to write a custom template tag, https://docs.djangoproject.com/en/dev/howto/custom-template-tags/#writing-custom-template-tags

How to create a WordPress like URL naming convention in Django?

I'm a newbie in Django and in WordPress if you create a Post called "hello world" then the URL by default will be like
wordpress.com/2012/07/05/hello-world/
and if you create another post with the same name it will be
wordpress.com/2012/07/05/hello-world-2/
I want to achieve the same in Django and I was thinking to create a sample urlconf like this
(r'^articles/(\d{4})/(\d{2})/(?P<name>\w+)', 'article.views.article_detail')
and in the views break down the name and iterate through all the items and match the name.
But the problem with will be that I won't be able to reference posts dynamically. For e.g. if I was to link the a hello world post I would need to find out how many posts with the same name exist already and then append the additional number to it which is inefficient.
So what's the best way to do this in Django?
See the documentation for Django's {{ url }} template tag. It lets you pass it a view name and parameters, and automatically generates the correct URL for you.
You can take care of appending numbers to each post's name in the function that generates its slug - you could have a look at django-autoslug

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 can you use Django template tags in a Jinja2 template?

There are a number of off-the-shelf Django packages that offer template tags, and I'd like to use them in my project despite the fact that it uses Jinja2.
I've seen some workarounds that allow other template engines to use Django tags. These involve creating a mini-template in a string, and passing it to the Django template processor along with the current context. Here are two example of what I'm talking about: Mako templates using Django template tags and Jinja2 templates using Django template tags.
I'm wondering if there's a less hackish solution.
what about moving problem to python's scope
and importing one python's function into another, this way:
in your_jinja_templatetags.py
from some_django_templatetags import somefilter as base_somefilter
#library.filter
def somefilter(value):
return base_somefilter(value)
Unfortunately Django template tags are not directly translatable to Jinja.
Django Template tags can do many different things, and are usually implemented as functions. Fortunately, Jinja can register these functions as globals and call them. This works for "simple" template tags out of the box.
If you are using the official Django Jinja2 backend, see https://docs.djangoproject.com/en/4.1/topics/templates/#django.template.backends.jinja2.Jinja2 to find out how to register a function (in this case your template tag) as a global. Once this is done, you can call the function from within your template as {{ your_tag_function() }}. Remember to pass whatever arguments the template tag function needs!
I like to use the https://github.com/niwinz/django-jinja backend, myself- if you are using this backend, see https://niwi.nz/django-jinja/latest/#_custom_filters_globals_constants_and_tests for how to register a function as a global.
Unfortunately, this only works for "simple" tags out of the box. Some tags are "inclusion tags" or otherwise depend on the Django Template Engine. Since Django Templates can't be rendered within the Jinja engine, you have to do a bit more work to translate these types of tags. You will need to look at the source code to tell the difference and see what they are doing.
What I usually do for the more complicated tags is create a "jinja_functions.py" script in my Django app, then in that script I import the original template tag. Then I write a function that wraps it- calling the original function, getting back usually a dictionary, and then using that dict to render a string which is returned... most tags are simple enough I just use an f string or .format to format them with the results of the dict.
Then I register my new wrapper function as a jinja global and use it in my jinja templates!
The following is an example of where I re-implemented the template tags provided by https://github.com/timonweb/django-tailwind for use with jinja. I combined both the tailwind_css and tailwinf_preload_css tags into a single function, tailwind_css, which I register with Jinja as a global as per the instructions above, then I can call that function as {{ tailwind_css(prefetch=True) }} or {{ tailwind_css() }} within my templates.
from django.templatetags.static import static
from tailwind import get_config
from tailwind.utils import is_path_absolute
def tailwind_css(v=None, prefetch=False):
tailwind_css_path = get_config("TAILWIND_CSS_PATH")
if not is_path_absolute(tailwind_css_path):
tailwind_css_path = static(tailwind_css_path)
if v:
tailwind_css_path = f"{tailwind_css_path}?v={v}"
if prefetch:
rel = 'rel="preload"'
as_str = ' as="style"'
else:
rel = 'rel="stylesheet"'
as_str = ""
return f'<link {rel} href="{tailwind_css_path}"{as_str}>'
In conclusion it works well out of the box for "simple" tags because you can just register them as global functions in Jinja... but for "include" tags or other tags that rely on the Django Template engine, you will have to write your own function :( But usually its not too much work!

Use url args in views, is it possible?

I'd like to use url arguments in views (not templates, I know how to do that).
So is it possible to use them like:
def item_link(self, item):
return mainpage_url_name + "%s/%i" % (item.slug, item.cid)
mainpage_url_name - is of course defined in url patterns (as name variable)
I'm a total newb in Django...
Thanks
First you should use names for your url patterns as documented here.
Then you can use reverse() to use these names in your views or methods.
Following your comments you are using the syndication framework.
Therefore you should make sure that you define get_absolute_url() for you models, ideally using the permalink decorator (for a clean reversing of your urls).
Looking at the example from Django's docs that should be all that's necessary.
To specify the contents of <link>, you
have two options. For each item in
items(), Django first tries calling
the item_link() method on the Feed
class. In a similar way to the title
and description, it is passed it a
single parameter, item. If that method
doesn't exist, Django tries executing
a get_absolute_url() method on that
object.