🔧 FIX: Исправлен URL pattern 'about_view' → 'about' + Динамический фильтр категорий услуг из БД
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
<div id="navcol-5" class="collapse navbar-collapse">
|
||||
<ul class="navbar-nav ms-auto">
|
||||
<li class="nav-item"><a class="nav-link active" href="{% url 'services' %}">Услуги</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="{% url 'about_view' %}">О нас</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="{% url 'about' %}">О нас</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -27,28 +27,21 @@
|
||||
<div class="container-modern">
|
||||
<!-- Service Categories Filter -->
|
||||
<div class="text-center mb-5">
|
||||
<div class="btn-group" role="group" aria-label="Категории услуг">
|
||||
<button type="button" class="btn btn-outline-primary active" data-filter="all">
|
||||
<div class="btn-group flex-wrap justify-content-center" role="group" aria-label="Категории услуг">
|
||||
<a href="?category=all" class="btn btn-outline-primary {% if selected_category == 'all' %}active{% endif %} mb-2">
|
||||
Все услуги
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-primary" data-filter="web">
|
||||
Веб-разработка
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-primary" data-filter="mobile">
|
||||
Мобильные приложения
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-primary" data-filter="design">
|
||||
Дизайн
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-primary" data-filter="other">
|
||||
Другое
|
||||
</button>
|
||||
</a>
|
||||
{% for category in categories %}
|
||||
<a href="?category={{ category.name|lower }}" class="btn btn-outline-primary {% if selected_category == category.name|lower %}active{% endif %} mb-2">
|
||||
{{ category.name }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-4" id="services-container">
|
||||
{% for service in services %}
|
||||
<div class="col-lg-4 col-md-6 service-item" data-category="{{ service.category.name|lower }}">
|
||||
<div class="col-lg-4 col-md-6 service-item">
|
||||
<div class="card-modern h-100">
|
||||
<div class="position-relative overflow-hidden" style="height: 200px;">
|
||||
{% if service.video %}
|
||||
@@ -383,39 +376,6 @@
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script>
|
||||
// Service filtering
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const filterButtons = document.querySelectorAll('[data-filter]');
|
||||
const serviceItems = document.querySelectorAll('.service-item');
|
||||
|
||||
filterButtons.forEach(button => {
|
||||
button.addEventListener('click', function() {
|
||||
const filter = this.getAttribute('data-filter');
|
||||
|
||||
// Update active button
|
||||
filterButtons.forEach(btn => btn.classList.remove('active'));
|
||||
this.classList.add('active');
|
||||
|
||||
// Filter services
|
||||
serviceItems.forEach(item => {
|
||||
if (filter === 'all' || item.getAttribute('data-category').includes(filter)) {
|
||||
item.style.display = 'block';
|
||||
setTimeout(() => {
|
||||
item.style.opacity = '1';
|
||||
item.style.transform = 'translateY(0)';
|
||||
}, 50);
|
||||
} else {
|
||||
item.style.opacity = '0';
|
||||
item.style.transform = 'translateY(20px)';
|
||||
setTimeout(() => {
|
||||
item.style.display = 'none';
|
||||
}, 300);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Service modal
|
||||
function openServiceModal(serviceId, serviceName) {
|
||||
document.getElementById('serviceId').value = serviceId;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from django.shortcuts import render, get_object_or_404, redirect
|
||||
from .models import Service, Project, Client, BlogPost, Review, Order, ServiceRequest, HeroBanner
|
||||
from .models import Service, Project, Client, BlogPost, Review, Order, ServiceRequest, HeroBanner, Category
|
||||
from django.db.models import Avg
|
||||
from comunication.models import TelegramSettings
|
||||
import qrcode
|
||||
@@ -76,8 +76,23 @@ def blog_post_detail(request, pk):
|
||||
return render(request, 'web/blog_post_detail.html', {'blog_post': blog_post})
|
||||
|
||||
def services_view(request):
|
||||
services = Service.objects.all()
|
||||
return render(request, 'web/services_modern.html', {'services': services})
|
||||
# Получаем выбранную категорию из GET параметра
|
||||
selected_category = request.GET.get('category', 'all')
|
||||
|
||||
# Получаем все категории для фильтра
|
||||
categories = Category.objects.all().order_by('name')
|
||||
|
||||
# Фильтруем услуги по категории
|
||||
if selected_category == 'all' or not selected_category:
|
||||
services = Service.objects.all().order_by('name')
|
||||
else:
|
||||
services = Service.objects.filter(category__name__icontains=selected_category).order_by('name')
|
||||
|
||||
return render(request, 'web/services_modern.html', {
|
||||
'services': services,
|
||||
'categories': categories,
|
||||
'selected_category': selected_category
|
||||
})
|
||||
|
||||
def about_view(request):
|
||||
return render(request, 'web/about_modern.html')
|
||||
|
||||
Reference in New Issue
Block a user