Django multilingual with pages in one language disabling switch - django

I am developing a website using Django Mezzanine.
I have some pages using a model derived from Mezzanine Page model with translatable fields (using i18n) and this works.
However I have some pages relative to some events in given countries, so they are only in one language, and they use a model derived from Mezzanine Displayable model, without translatable fields but a language attribute.
In the list I tried to put links including the language of the page (like /en/events/event/eventslug ).
I tried to add translation.activate(lang_code) to the view.
This way I get the page in the wanted language (I use {% trans %} template tags).
The problem comes when I visit the page from another language (for example if I am on the filter page in Spanish and go to an English event). Then the language switch (mezzanine form sending a POST request to /i18n/) doesn't work any more (I am locked in English)
The switch still work in private navigation for example as long as I don't visit one of this pages from another language.
How can I fix this?
I am out of ideas as of why...
Update: I changed the urlpattern so it is not i18n anymore (I think it makes more sense) but as I still need translation.activate(lang_code) for the {% trans %} tags my problem is still the same.

The problem came from the fact that if you use translation.activate(language) then you need to use translation.deactivate().
So that would have required the use of a middleware to make it work properly.
However I found the i18next module allowing to override the locale in the template, so I defined the context 'lang_code' in my view and used {% overridelocale lang_code %} in my template.

Related

Hyphenation in Jinja template (using Django Wagtail)

I have a Django Wagtail application, which employs the templating machine Jinja (or Jinja2, not entirely sure, but won't make a difference for this issue).
When I e.g. want to use the templating to show the title of a blog post, I can write
{{ post.title }}
This works perfectly fine. But I cannot enforce hyphenation in this title. If the title holds a very long word, this crashes my layout on small devices. Anyone an idea how I can tell Jinja that hyphenation should be enabled?

django cms [aldryn newsblog] replace template for plugin

I need to replace same plugin template on different subpages - e.g. on frontpage I need specific slider template for latest articles, in detail article I need small list, on search result without images etc.
[note: everything about aldryn newsblog app - I don't mean my own plugin!]
*(something like custom template per plugin instance)
How to replace it ? Extending template is not quite what I need - inheritance is from bottom - from lower subtemplate to base.html - but that plugin have hardcoded lower template.
Tons of IF block in template is irrational then we think in MVC.
*( like here Render Django-CMS plugins differently on different splaceholders/templates )
Or maybe just write custom template with using hardcoded including plugins ? But using django cms placeholder editor is very useful and it'll be better to keep working in that way :///
So, I create front.html base template for frontpage,
put some plugins to placeholders - and need to replace subtemplates for this plugins only in this front.html and keep subtemplates for that plugin in other places - this is main goal.
It will be the best, when django cms / aldryn newsblog provide option "custom template" per plugin instance :|
( like this one http://www.ilian.io/django-cms-plugins-with-selectable-template/ )
If I understand your question correctly (it's late here), you need a way to override plugin templates on a plugin instance basis because hacking django templates is not the way to go (I agree).
Django CMS does allow you to override plugin templates on an instance basis.
As shown in http://docs.django-cms.org/en/develop/how_to/custom_plugins.html?highlight=get_render_template#the-simplest-plugin
In your CMSPluginBase subclass add the following:
def get_render_template(self, context, instance, placeholder):
# criteria goes here
return 'sometemplate.html'
As far as how to know which template to render when (criteria), you can do a few things.
Use the page's reverse id:
page = instance.page
templates = {
'homepage': 'plugin_home.html',
'about': 'plugin_about.html',
'contact': 'plugin_contact.html',
}
return templates[plugin.page.reverse_id]
This approach has a few drawbacks:
Relies on plugin being bound to a page. (plugins can live outside of pages)
Can only work with pages that have reverse id set and reverse ids
are unique per page which means you would have to list reverse id
for every page you want to change template for.
Use a page extension to set a category per page:
Checkout http://docs.django-cms.org/en/develop/how_to/extending_page_title.html
With this approach you can then set some sort of category to multiple pages and so you can target multiple pages in one shot like so:
page = instance.page
extension = get_page_extension(page) # Check out docs for this
templates = {
'category_1': 'plugin_category_1.html',
'category_2': 'plugin_category_2.html',
'category_3': 'plugin_category_3.html',
}
return templates[extension.category.name]
Pros:
Can target multiple pages in one shot
Cons:
Relies on plugin being bound to a page.
A bit more complex
Use a template context variable:
In your templates, depending on how you're rendering your plugins, you can
provide a context variable like so:
{% with category='category_1' %}
{% placeholder 'content' %}
{% endwith %}
or
{% with category='category_1' %}
{% render_plugin yourplugin %}
{% endwith %}
Then in your get_render_template method you can access this context variable and do the following:
# Use .get() to provide fallback
category = context['category']
templates = {
'category_1': 'plugin_category_1.html',
'category_2': 'plugin_category_2.html',
'category_3': 'plugin_category_3.html',
}
return templates[category]
Pros:
No extra models.
Can target multiple pages in one shot.
Cons:
The only one I can think of is these random {% with %} in
templates.
I completely missed the newblog part, so in order to override the newsblog plugins or any plugin, just subclass the plugin class you want to override and unregister the original and then register yours, make sure yours has the same class name.
Maybe you can make the whole template logic above into a mixin to use throughout your project.
I've always wanted to give Zinnia a look, but I'm too far into working with NewsBlog on a site right now to do it (and blogs have already been posted and whatnot). You can always just add a few extra placeholders in the template (it's not the most efficient looking thing ever, but it's no load on the framework if you add a placeholder and leave it blank), that way they aren't static, and then you can put whatever plugins you want to inside of them. You can customize each component in NewsBlog pretty easily by just adding whatever you want in the structure mode. Things get trickier when it comes to having multiple blogs that act differently, but even then, as long as you're not adding components into the static placeholders provided by NewsBlog (or as I so elegantly learned it, "don't put the stuff in the blocky-things with the pins next to them), you can create different namespace for the different blogs (either in the admin, under "Configs" in the NewsBlog section, or when creating a new page and hooking it to the NewsBlog app), and you can have different templates on different blogs.
EDIT: This is a really excellent resource for touching up NewBlog without throwing the baby out with the bathwater (after three months of learning DjangoCMS, I'm still finding myself referencing it for fine-tuning pieces of NewsBlog, and to refresh my grasp on templatetags and other things that are overwhelming and have quickly left my brain along the way): https://www.django-cms.org/en/blog/2016/02/16/build-a-website-without-knowing-python-django-part-two/
*I linked to part two, as the first part deals with how to initially setup a project, and I assumed it probably wasn't relevant. Then again, if you're using Aldryn, there are some useful bits in there that can extrapolate if you're having trouble with customizing the boilerplate (or other things you'd like to configure that an Aldryn setup handles for you -- which is super awesome most of the times, but when it's not super awesome, it's usually super frustrating :)

Use Django templates to generate forms

I’m planning to use the Django templating system in a slightly uncommon way. I need an app that will let me easily create simple “fill in the gap”-style forms and I decided to use Django templates with custom tags to design the forms.
Here is a sketch of what I mean:
<p>
This is the <i>form</i>. Two plus two is {% gap four 4 vier %}.<br>
The best programming language is {% case_gap Python Haskell %}.
</p>
{% if all_correct %}
You are smart.
{% else %}
<input type="submit">
{% endif %}
The idea is that the *gap tags render a text input control, look into the context to see if the answer for them was sent, and if the answer is correct, mark the text inputs green.
The question is how to implement the all_correct logic. The simple solution is to add this variable to the context and then make each *gap tag update it based on its correct answer, and, I believe, this should work with my example. But what if I want to move the {% if all_correct %} code to the top of the template, where none of the gaps were rendered, and thus none of them have validated their answers yet?
Looks like I need some way to iterate over all the *gap tags before starting to render the template and [ask them to] validate the answers, but I don’t know the internals of the templating system well enough to implement this. Or there might be a completely different and better way.
I believe I figured how to do this after reading Chapter 9 of The Django Book.
Creating of a custom template tag involves defining of two things: how to compile the tag and how to render it. The compile-function should parse the tag data and return a Node—basically a thing that has a .render(self, context) method and some other data derived from the tag text.
The solution is to create FormNode—a subclass of Node that will also have a .validate(self, context) method. Then our custom tag will be compiled to a subclass of FormNode that implements validation logic.
The next thing to do is to create FormTemplate—a subclass of Template with a super-power: before starting to render individual nodes it will validate all the nodes by iterating over them and calling validate(context) on all the subclasses of FormNode and it will set the all_valid variable in the context.
Here is my proof-of-concept implementation: https://github.com/kirelagin/django-template-forms. I believe it works pretty well.
I used the ability to instantiate a custom template engine, which was added in Django 1.8. Overall, I had to dig a little deeper than one might expect and I always had this feeling that splitting of the templating API and the django engine (which is now just one of the available backends) wasn’t complete yet. I hope that Django 2.0 will bring us new cool stuff and all the hacks I had to add will vanish.

Isn't it rough to retrieve flatpages via get_flatpages template tag from its url instead of a page identifier?

As you can read on the django reference or hacking a bit, get_flatpages can be used as follow:
{% get_flatpages as flatpages %}
{% get_flatpages for someuser as flatpages %}
{% get_flatpages '/about/' as about_pages %}
{% get_flatpages prefix as about_pages %}
{% get_flatpages '/about/' for someuser as about_pages %}
So, if I want to get a specific page I need to do it via its url or a prefix, which is somewhat rough, because my template code become data dependant, I meant, if I change the url of certain flat page then it is necessary to change my template code too.
A more flexible idea would be including an identifier to each page, addable through e.g. the 'Advanced options' section, so that the page can be refered via its identifier, thus we could do something like this:
{% get_flatpages 'about' as about_pages %}
Which is more flexible and less data dependant, no matter what url the page has, note we could change the page's url without changing the template code.
Is there something like that in the framework?, of course I could customize this app or to use a third-party app, but this isn't the point ;-)
Have you any other idea to deal with?
No, I don't believe there's any support for what you're asking for in Django at present. The docs you linked to for flatpages say:
A flatpage is a simple object with a URL, title and content. Use it for one-off, special-case pages, such as “About” or “Privacy Policy” pages, that you want to store in a database but for which you don’t want to develop a custom Django application.
My reading of this is "this is the bare minimum we're providing, and if you want any more you'll have to code it yourself". I agree that your proposal of allowing pages to be referred to by a symbolic name (which perhaps defaults to their URL) is more flexible, but you're probably better off raising an issue for it or discussing on the mailing list than hoping a dev happens upon your question on StackOverflow.
In the short term, you could look at some of the pre-built CMS-like Django apps. Django-page-cms is relatively lightweight (it's a relatively small app itself but does have a bunch of dependencies) and you could accomplish what you're after: each page is referred to by its slug (aka url / name), but you can define aliases / redirects to given pages for arbitrary URLs.

Is it possible, in a django template, to check if an object is contained in a list

I'm very new to django, about a week into it.
I'm making a site where users enter stuff, then other users can vote on whether they like the stuff or not. I know it's not so novel, but it's a good project to learn a bunch of tools.
I have a many-to-many table for storing who likes or dislikes what. Before I render the page, I pull out all the likes and dislikes for the current user, along with the stuff I'm going to show on the page.
When I render the page, I go through the list of stuff I'm going to show and print them out one at a time. I want to show the user which stuff they liked, and which they didn't.
So in my django template, I have an object called entry. I also have two lists of objects called likes and dislikes. Is there any way to determine if entry is a member of either list, inside my django template.
I think what I'm looking for is a filter where I can say something like
{% if entry|in:likes %}
or
{% if likes|contains:entry %}
I know I could add a method to my model and check for each entry individually, but that seems like it would be database intensive.
Is there a better way to think about this problem?
If you're using latest django version, then it's just
{% if entry in likes %}
Refer django docs
Go here. Very similar to what they're using on trunk. "Save this as smart_if.py in the templatetags folder of one of your apps. Then a simple {% load smart_if %} replaces the boring built-in Django {% if %} template with the new smart one."
If you're not running trunk one of the following should work:
Filter:
Replacement "if" tag, largely the basis for the new functionality in the upcoming 1.2 release: