Merge pull request 'Save user language' (#12) from dev into main
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/promote/production Build is passing

Reviewed-on: #12
This commit is contained in:
Jannis Portmann 2023-09-08 11:50:20 +02:00
commit 05ca8ac322
9 changed files with 107 additions and 26 deletions

View file

@ -14,4 +14,4 @@ class WishAdmin(admin.ModelAdmin):
@admin.register(PflaenzliUser)
class UserAdmin(admin.ModelAdmin):
list_display = ['id', 'username', 'email', 'zipcode', 'date_joined']
list_display = ['id', 'username', 'email', 'zipcode', 'language_code', 'date_joined']

View file

@ -0,0 +1,34 @@
# Generated by Django 4.1.10 on 2023-07-22 16:52
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("pflaenzli", "0004_offer_category"),
]
operations = [
migrations.AddField(
model_name="pflaenzliuser",
name="language_code",
field=models.CharField(default="de", max_length=2),
),
migrations.AlterField(
model_name="offer",
name="category",
field=models.CharField(
choices=[
("PLNT", "Plant"),
("SEED", "Seedling"),
("POT", "Pots"),
("TOOL", "Tools"),
("OTHR", "Other"),
],
default="PLNT",
max_length=4,
verbose_name="Category",
),
),
]

View file

@ -11,6 +11,7 @@ from django.utils.translation import gettext_lazy as _
class PflaenzliUser(AbstractUser):
email = models.EmailField(max_length=254)
zipcode = models.PositiveIntegerField(blank=True, null=True, verbose_name=_('ZIP code'))
language_code = models.CharField(max_length=2, default='de')
class Offer(models.Model):

View file

@ -20,8 +20,10 @@
const setTheme = function(theme) {
if (theme === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.documentElement.setAttribute('data-bs-theme', 'dark')
set_captcha_theme('dark', 0)
} else {
document.documentElement.setAttribute('data-bs-theme', theme)
set_captcha_theme(theme, 0)
}
}
@ -59,4 +61,17 @@
})
})
})
})()
})()
function set_captcha_theme(theme, set_try) {
var captchaDiv = document.getElementById("id_captcha");
if (captchaDiv) {
console.log("Set the theme on try" + set_try)
if (theme == 'dark') {
captchaDiv.classList.add("dark");
} else {
captchaDiv.classList.remove("dark");
}
}
};

View file

@ -46,7 +46,6 @@
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"
integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN"
crossorigin="anonymous"></script>
<script src="{% static 'bootstrap-color-toggler.js' %}"></script>
{% block head %}{% endblock %}
</head>
<body class="d-flex flex-column h-100 justify-content-between {% block background %}{% endblock background %}">
@ -93,10 +92,10 @@
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
<li>
<form method="POST" action="{% url 'set_language' %}">
<form method="POST" action="{% url 'save_language' %}">
{% csrf_token %}
<input type="hidden" name="language" value="{{ language.code }}" />
<button class="dropdown-item d-flex align-items-center {% if language.code == LANGUAGE_CODE %} active{% endif %}"
<button class="dropdown-item d-flex align-items-center {% if language.code == LANGUAGE_CODE %}active{% endif %}"
type="submit">
{{ language.name_local }} ({{ language.code }})
</button>
@ -215,5 +214,6 @@
</div>
</div>
</footer>
<script src="{% static 'bootstrap-color-toggler.js' %}"></script>
</body>
</html>

View file

@ -24,7 +24,7 @@ urlpatterns = [
path("accounts/<int:user_id>", views.user_detail, name="user_detail"),
path("accounts/<int:user_id>/wishlist/", views.wishlist, name="wishlist"),
path('accounts/login/', auth_views.LoginView.as_view(template_name='registration/login.html')),
path('accounts/profile/', auth_views.LoginView.as_view(template_name='user/detail.html'), name='user_profile'),
path('accounts/profile/', TemplateView.as_view(template_name='user/detail.html'), name='user_profile'),
path('accounts/profile/edit', views.user_edit, name='user_edit'),
path('accounts/register/', views.register_user, name='register_user'),
path('accounts/password_reset/', auth_views.PasswordResetView.as_view(template_name='registration/verify_email.html',
@ -39,6 +39,8 @@ urlpatterns = [
path("faq/", TemplateView.as_view(template_name='app/faq.html'), name="faq"),
path("imprint/", TemplateView.as_view(template_name='app/imprint.html'), name="imprint"),
path("wish/delete/<str:wish_id>", views.delete_wish, name='delete_wish'),
path("save_language/", views.save_language, name="save_language"),
path("load_language/", views.load_language, name="load_language"),
path("i18n/", include("django.conf.urls.i18n")),
path('sitemap.xml', sitemap, {'sitemaps': sitemaps},
name='django.contrib.sitemaps.views.sitemap'),

View file

@ -1,21 +1,20 @@
from django.shortcuts import render, get_object_or_404, redirect, reverse
from django.utils import timezone
from django.conf import settings
from django.contrib import messages
from django.contrib.auth import login
from django.contrib.auth.decorators import login_required
from django.http import HttpResponseForbidden
from django.shortcuts import get_object_or_404, redirect, render
from django.utils.translation import gettext_lazy as _
from django.utils.translation import activate, get_language
from django.views.decorators.csrf import csrf_protect
from django.views.decorators.http import require_POST
from django.http import HttpResponseForbidden
from django.utils.translation import gettext_lazy as _
from .forms import CreateOfferForm, RegistrationForm, FilterForm, WishForm
from .models import PflaenzliUser, Offer, Wish
from .forms import CreateOfferForm, FilterForm, RegistrationForm, WishForm
from .mail import send_offer_email
from .models import Offer, PflaenzliUser, Wish
from .upload import generate_unique_filename
from .utils.distance import calculate_distance, filter_by_distance
from .utils.compress_image import compress_image
from .utils.distance import calculate_distance, filter_by_distance
def list_offers(request, filters=None):
@ -184,6 +183,7 @@ def register_user(request):
form = RegistrationForm(request.POST)
if form.is_valid():
user = form.save()
user.language_code = get_language()
login(request, user)
return redirect("index")
else:
@ -192,6 +192,34 @@ def register_user(request):
return render(request, "basic_form.html", {"form": form, "button_label": _("Register"), "title": _("Registeration"), "umami_event": "User registration"})
def save_language(request):
referer_url = request.META.get('HTTP_REFERER')
response = redirect(referer_url)
if request.method == 'POST':
if language_code := request.POST.get('language'):
if request.user.is_authenticated:
user = request.user
user.language_code = language_code
user.save()
activate(language_code)
response.set_cookie(settings.LANGUAGE_COOKIE_NAME, language_code)
return response
@login_required
def load_language(request):
response = redirect('user_profile')
language_code = request.user.language_code
activate(language_code)
response.set_cookie(settings.LANGUAGE_COOKIE_NAME, language_code)
return response
def error_404(request, exception):
return render(request, '404.html')

View file

@ -56,12 +56,12 @@ INSTALLED_APPS = [
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
'django.middleware.locale.LocaleMiddleware',
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
'django.middleware.locale.LocaleMiddleware',
"django.middleware.common.CommonMiddleware",
]
ROOT_URLCONF = "pflaenzli_django.urls"
@ -126,6 +126,7 @@ AUTH_PASSWORD_VALIDATORS = [
]
AUTH_USER_MODEL = 'pflaenzli.PflaenzliUser'
LOGIN_REDIRECT_URL = "/load_language"
LOGOUT_REDIRECT_URL = "/"
# Internationalization

View file

@ -1,14 +1,14 @@
crispy-bootstrap5==0.7
Django==4.1.10
Django==4.1.11
djangoloco==1.0
django-bootstrap5==22.2
django-bootstrap5==23.3
django-crispy-forms==2.0
django-jquery==3.1.0
django-friendly-captcha==0.1.7
geopy==2.3.0
gunicorn==20.1.0
fontawesomefree==6.3.0
pandas==2.0.0
Pillow==9.4.0
psycopg2-binary==2.9.5
django-friendly-captcha==0.1.8
geopy==2.4.0
gunicorn==21.2.0
fontawesomefree==6.4.2
pandas==2.1.0
Pillow==10.0.0
psycopg2-binary==2.9.7
python-dotenv==1.0.0