Add SiteSettings model with currency_symbol field and replace hardcoded currency symbols in templates

This commit is contained in:
2025-11-24 14:00:05 +09:00
parent 9afa37759a
commit 9c6db614d4
8 changed files with 74 additions and 15 deletions

View File

@@ -73,6 +73,7 @@ TEMPLATES = [
'django.contrib.auth.context_processors.auth', 'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages', 'django.contrib.messages.context_processors.messages',
'web.context_processors.footer_settings', # Custom context processor 'web.context_processors.footer_settings', # Custom context processor
'web.context_processors.site_settings', # Site settings (currency, etc.)
], ],
}, },
}, },

View File

@@ -2,7 +2,8 @@ from django.contrib import admin
from .models import ( from .models import (
Service, Project, Client, Order, Review, BlogPost, Service, Project, Client, Order, Review, BlogPost,
Category, ServiceRequest, AboutPage, FooterSettings, TeamMember, Category, ServiceRequest, AboutPage, FooterSettings, TeamMember,
PortfolioItem, PrivacyPolicy, TermsOfUse, NewsArticle, CareerVacancy PortfolioItem, PrivacyPolicy, TermsOfUse, NewsArticle, CareerVacancy,
SiteSettings
) )
from .forms import ProjectForm from .forms import ProjectForm
@@ -218,6 +219,25 @@ class TeamMemberAdmin(admin.ModelAdmin):
def full_name(self, obj): def full_name(self, obj):
return obj.full_name return obj.full_name
full_name.short_description = 'ФИО' full_name.short_description = 'ФИО' # type: ignore
full_name.admin_order_field = 'last_name' full_name.admin_order_field = 'last_name' # type: ignore
@admin.register(SiteSettings)
class SiteSettingsAdmin(admin.ModelAdmin):
list_display = ('currency_symbol',)
fieldsets = (
('Настройки валюты', {
'fields': ('currency_symbol',)
}),
)
def has_add_permission(self, request):
# Запретить создание новых записей (singleton)
return not SiteSettings.objects.exists()
def has_delete_permission(self, request, obj=None):
# Запретить удаление настроек
return False

View File

@@ -1,4 +1,4 @@
from .models import FooterSettings from .models import FooterSettings, SiteSettings
def footer_settings(request): def footer_settings(request):
@@ -11,3 +11,12 @@ def footer_settings(request):
return { return {
'footer_settings': footer 'footer_settings': footer
} }
def site_settings(request):
"""Context processor для глобальных настроек сайта"""
settings = SiteSettings.get_settings()
return {
'site_settings': settings,
'currency_symbol': settings.currency_symbol,
}

View File

@@ -581,4 +581,33 @@ class TeamMember(models.Model):
return f"{self.first_name} {self.last_name}" return f"{self.first_name} {self.last_name}"
class SiteSettings(models.Model):
"""Глобальные настройки сайта"""
currency_symbol = models.CharField(
max_length=10,
default='',
verbose_name='Символ валюты',
help_text='Символ валюты для отображения на сайте (₩, $, ₽, €, ¥ и т.д.)'
)
class Meta:
verbose_name = 'Настройки сайта'
verbose_name_plural = 'Настройки сайта'
def __str__(self):
return f'Настройки сайта (Валюта: {self.currency_symbol})'
def save(self, *args, **kwargs):
# Singleton pattern - только одна запись настроек
self.pk = 1
super().save(*args, **kwargs)
@classmethod
def get_settings(cls):
"""Получить настройки сайта (создать если не существует)"""
settings, created = cls.objects.get_or_create(pk=1)
return settings

View File

@@ -35,11 +35,11 @@
<div class="mb-3"> <div class="mb-3">
<strong class="text-primary h4"> <strong class="text-primary h4">
{% if vacancy.salary_min and vacancy.salary_max %} {% if vacancy.salary_min and vacancy.salary_max %}
${{ vacancy.salary_min|floatformat:0 }} - ${{ vacancy.salary_max|floatformat:0 }} {{ currency_symbol }}{{ vacancy.salary_min|floatformat:0 }} - {{ currency_symbol }}{{ vacancy.salary_max|floatformat:0 }}
{% elif vacancy.salary_min %} {% elif vacancy.salary_min %}
От ${{ vacancy.salary_min|floatformat:0 }} От {{ currency_symbol }}{{ vacancy.salary_min|floatformat:0 }}
{% else %} {% else %}
До ${{ vacancy.salary_max|floatformat:0 }} До {{ currency_symbol }}{{ vacancy.salary_max|floatformat:0 }}
{% endif %} {% endif %}
</strong> </strong>
</div> </div>

View File

@@ -46,11 +46,11 @@
<div class="mb-3"> <div class="mb-3">
<strong class="text-primary"> <strong class="text-primary">
{% if vacancy.salary_min and vacancy.salary_max %} {% if vacancy.salary_min and vacancy.salary_max %}
${{ vacancy.salary_min|floatformat:0 }} - ${{ vacancy.salary_max|floatformat:0 }} {{ currency_symbol }}{{ vacancy.salary_min|floatformat:0 }} - {{ currency_symbol }}{{ vacancy.salary_max|floatformat:0 }}
{% elif vacancy.salary_min %} {% elif vacancy.salary_min %}
От ${{ vacancy.salary_min|floatformat:0 }} От {{ currency_symbol }}{{ vacancy.salary_min|floatformat:0 }}
{% else %} {% else %}
До ${{ vacancy.salary_max|floatformat:0 }} До {{ currency_symbol }}{{ vacancy.salary_max|floatformat:0 }}
{% endif %} {% endif %}
</strong> </strong>
</div> </div>

View File

@@ -42,7 +42,7 @@
<div class="price-badge"> <div class="price-badge">
<span class="price-label">от</span> <span class="price-label">от</span>
<span class="price-value">{{ service.price|floatformat:0 }}</span> <span class="price-value">{{ service.price|floatformat:0 }}</span>
<span class="price-currency"></span> <span class="price-currency">{{ currency_symbol }}</span>
</div> </div>
</div> </div>

View File

@@ -85,7 +85,7 @@
<div class="d-flex justify-content-between align-items-center mb-3"> <div class="d-flex justify-content-between align-items-center mb-3">
<div> <div>
<small class="text-muted">От</small> <small class="text-muted">От</small>
<span class="h5 text-primary mb-0"> {{ service.price|default:"По запросу" }}</span> <span class="h5 text-primary mb-0">{{ currency_symbol }} {{ service.price|default:"По запросу" }}</span>
</div> </div>
<div class="text-end"> <div class="text-end">
<small class="text-muted">Срок</small> <small class="text-muted">Срок</small>
@@ -309,9 +309,9 @@
<label for="budget" class="form-label">Примерный бюджет</label> <label for="budget" class="form-label">Примерный бюджет</label>
<select class="form-select" id="budget" name="budget"> <select class="form-select" id="budget" name="budget">
<option value="">Не определен</option> <option value="">Не определен</option>
<option value="1000-5000"> 1,000,000 - 5,000,000</option> <option value="1000-5000">{{ currency_symbol }} 1,000,000 - 5,000,000</option>
<option value="5000-10000"> 5,000,000 - 10,000,000</option> <option value="5000-10000">{{ currency_symbol }} 5,000,000 - 10,000,000</option>
<option value="10000+"> 10,000,000+</option> <option value="10000+">{{ currency_symbol }} 10,000,000+</option>
</select> </select>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">