Django Language Change Anchors vs. Options - django

I have a dropdown list of languages that looks something like the following:
<ul class="languages hoverSelectorBlock">
{% get_current_language as current_lang %}
{% for lang in LANGUAGES %}
<li><a href="{% url 'set_language' %}" lang-code="{{ lang.0 }}"
class="change_language{% if current_lang == lang.0 %} current_language {% endif %}"
{% if current_lang == lang.0 %}selected="selected"
{% else %}selected=""{% endif %}>{{ lang.1 }}</a></li>
{% endfor %}
</ul>
The documentation says that it needs to be submitted as a POST request. From my understanding that means I need to change the anchor tags into options. But I want the same behavior such that when you click a language it will submit the form and reload the current page in that language.
Will the set_language view work with anchor tags? If I need to change them to a select with options, how can I submit the form when one of the options is clicked without the need for a submit button?

If you use select options and wrap them in a form with an id. You can submit the form on the select element's change event.
<form id="my_form">
<select onchange="submit_my_form()">
...
</select>
</form>
function submit_my_form(){
document.getElementById("my_form").submit();
}

Related

HTMX does not trigger get on load if it's a radio check

I am working on Django and using htmx I have checkbox input, select tag and radio input both work as expected on page load it sends a request to an endpoint to the server to retrieve certain information which is rendered through a partial template. The problem is only radio deosn't trigger it when the appropriate input value is checked.
Here is the radio input.
<input id="option_{{ option.id }}" class="form-check-input" type="radio"
name="radio_{{ question.id }}" value="{{ option.id }}" {% if question.required %} required
{% endif %} {% if question.disable %} disabled {% endif %} {% if option.id == radio_response %}
checked {% endif %} hx-get="{% url 'survey:dynamic_loader' %}" hx-trigger="load, change"
hx-target="#radio-result-{{question.id}}"/>
Is this a normal behaviour for htmx? Or I am doing something wrong.
You should not put the load trigger on radio inputs. If you have 10 radio inputs, then the load trigger creates 10 requests in total from which 9 will not have the value you expect, because HTMX just extracts the actual state of a radio input when the page loads. Instead of that, you should put HTMX attributes on a parent (grouping) element. For example:
<div hx-get="{% url 'survey:dynamic_loader' %}"
hx-trigger="load, change"
hx-target="#radio-result-{{question.id}}">
hx-include="this"
{% for option in options %}
<input id="option_{{ option.id }}"
class="form-check-input" type="radio"
name="radio_{{ question.id }}"
value="{{ option.id }}"
{% if question.required %} required{% endif %}
{% if question.disable %} disabled {% endif %}
{% if option.id == radio_response %}checked {% endif %} />
{% endfor %}
</div>
This creates only one request on page load (and of course when the user clicks on a radio input) and it will have the correct value of the radio input. The hx-include="this" attribute includes all child inputs' value in the request.

I want user can change website language using drop-down without login but if they log in website should translate in their saved language preference

I am using a Django website in which a user can change their language using a drop-down menu. I use Django i18n for the translation of the website. Now problem is that I want a user can visit some pages of the website without login and they can change the language using a drop-down. But when a user logs in, the language of the website should change to the default language of that user's we store in their porifle section. How can I achieve this?
language_form.html
{% load i18n %}
<form action="/i18n/setlang/?next={% url 'homepage' %}" method="post">
{% csrf_token %}
<select name="language" style="padding: 4px 3px;">
{% get_current_language as LANGUAGE_CODE %}
{% get_available_languages as LANGUAGES %}
{% get_current_language_bidi as LANGUAGE_BIDI %}
{% for language in LANGUAGES %}
<option value="{{ language.0 }}"{% if language.0 == LANGUAGE_CODE %} selected {% endif %} ">
{{ language.1 }}
</option>
{% endfor %}
</select>
{% for lang in aLANGUAGES %}
{{lang.list}}
{% endfor %}
<input type="submit" value="Change language" style="padding: 3px 3px; margin-right: 10px;">
</form>
The above code is my drop-down form for the select languages but I want user can select their preferred language in the profile section and that will be enabled automatically when they logged in.

Django admin custom form submission force to select action from dropdown list

I want to add a custom form to a django admin-site change list view. As soon as I add a submit button it asking to select the custom action from the drop-down list. I created a separate form with a unique id. Still it look for a action be select. How can I overcome this?
Here is my template code.
{% extends "admin/change_list.html" %}
{% load staticfiles %}
{% block content %}
<div align="right">
<form id="generate-form" method="POST">
{% csrf_token %}
<select>
<option value="">-- section name --</option>
{% for section in sections %}
<option value="{{ section.short_name }}">{{ section.name }}</option>
{% endfor %}
</select>
<input type="text" name="from_date" class="vTextField" placeholder="from">
<input type="text" name="to_date" class="vTextField" placeholder="to">
<input type="submit" value="Generate" class="default" id="gen-schedules"
style="margin:0; height: 30px; padding-top: 5px;">
<form>
</div>
{{ block.super }}
{% endblock %}
Assuming you copy/pasted without changing it, you have this because the form tag isn't properly closed: <form> should be replaced by </form>:
...
</form>
</div>
{{ block.super }}
{% endblock %}
Because it's not closed, the browser thinks it's the same form as the the next form, the actions one.
To avoid this kind of problems, I'd recommend relying on Django's forms to generate the right HTML for you, when possible. To help with complex layouts, django-crispy-forms is a great library that is very helpful.

How to hide an untranslated page from language chooser in django cms?

I want to hide an untranslated page from the language chooser in django cms so that the language chooser shows only the languages that have translations for that page. How can I do that?
One idea is to extend the language chooser template and check there if the language has a translated page but I couldn't find out how to do that.
Actually there is a beautiful solution, first posted here: https://groups.google.com/forum/#!topic/django-cms/z1rdf4C-ltQ
current_page.get_languages is the solution. Works with djangocms 3 in my Aldryn project.
includes/menu/langnav.html:
{% load i18n menu_tags %}
{% if languages|length > 1 %}
{% comment %}
This is awesome: https://groups.google.com/forum/#!topic/django-cms/z1rdf4C-ltQ
{% endcomment %}
<li class="lang">
{% for language in current_page.get_languages %}
<a class="{{ language }}{% ifequal current_language language %} selected{% endifequal %}"
href="{% page_language_url language %}">{{ language }}</a>
{% endfor %}
</li>
{% endif %}
in django cms 3.0:
{% if page and language in page.languages %}
for 2.4:
you probably will a custom filter or templatetag that runs::
if page.title_set.filter(language=lang).count():
return True
else:
return False

Filter by many2many (or foreignkey) that has a LOT of values, in django admin (grappelli or not)

I have two models:
class TheMainThing(models.Model):
... some fields ...
type = ManyToManyField('Type')
class Type(models.Model):
...more fields...
I would like to enable filtering TheMainThings in the admin by Types. The only Issue is that there are like 100k or more of the Type objects, so it isn't practical doing it with standard built-in filters. That's because all the Types get loaded in browser as an available option. (Actually, I'm using Grappelli, but I believe it's the same with standard Django admin).
It there a *don't_reinvent_the_wheel* approach to this problem?
I like Grappelli's autocomplete widget on raw_id fields, I imagine something like that would be ideal for this problem... It there such a thing?
edit:
To clarify - the main problem is load time and memory consumption in browser, not the presentation.
The admin outputs those filters as links with query strings inside <ul>s. You could change those out for selects instead.
The template used there is admin/filter.html and it looks like this:
{% load i18n %}
<h3>{% blocktrans with filter_title=title %} By {{ filter_title }} {% endblocktrans %}</h3>
<ul>
{% for choice in choices %}
<li{% if choice.selected %} class="selected"{% endif %}>
{{ choice.display }}</li>
{% endfor %}
</ul>
You can provide your own by the same name to override theirs, so redo it maybe like this:
{% load i18n %}
<h3>{% blocktrans with filter_title=title %} By {{ filter_title }} {% endblocktrans %}</h3>
<select>
{% for choice in choices %}
<option data-href="{{ choice.query_string|iriencode }}"
{% if choice.selected %} selected="selected"{% endif %}>
{{ choice.display }}
</option>
{% endfor %}
</select>
Then follow the filter link on change:
$(function() {
$('select', '#changelist-filter').on('change', function(e) {
window.location = window.location.href + $(e.target).attr('data-href');
});
});
To take it a step further, you could treat those with something like Select2 afterward.