Здравствуйте. Пару раз вы мне помогли и сейчас в очередной раз я прошу у вас помощи... Я учусь...
Я нашел на просторах интернета один способ в котором описывалось как подкрутить слаг для статей на сайте. Всё получилось на ура и я хотел этот способ прикрутить к категориям статей. Слаг прикрутился к категориям, но вот вывод статей по категориям теперь никак работать не хочет почему-то...
models.py
views.py
urls.py
Шаблон в котором должны отображаться и фильтроваться статьи по категориям news_list.html
Подскажите пожалуйста, как мне сделать так, чтобы при переходе по ссылке категории меня перекидывало на страницу где размещены как раз те статьи на которую категорию я перешел.
Когда навожу на ссылку, то слаг работает, но когда перехожу на ссылку, то статьи пропадают:
Не закидывайте пожалуйста яйцами и помидорами. Уже 2 дня пытаюсь работаться, много вариантов перепробовал, гугл перерыл, ничего не получается((
Я нашел на просторах интернета один способ в котором описывалось как подкрутить слаг для статей на сайте. Всё получилось на ура и я хотел этот способ прикрутить к категориям статей. Слаг прикрутился к категориям, но вот вывод статей по категориям теперь никак работать не хочет почему-то...
models.py
Python:
from django.db import models
from django.urls import reverse
from django.utils.text import slugify
class News(models.Model):
title = models.CharField(max_length=250, verbose_name='Наименование')
content = models.TextField(blank=True, verbose_name='Контент')
created_ad = models.DateTimeField(auto_now_add=True, verbose_name='Дата публикации')
updated_at = models.DateTimeField(auto_now=True, verbose_name='Обновлено')
photo = models.ImageField(upload_to='photos/%Y/%m/%d/', verbose_name='Картинка', blank=True)
is_published = models.BooleanField(default=True, verbose_name='Опубликовано')
category = models.ForeignKey('Category', verbose_name='Категория', on_delete=models.PROTECT) # on_delete=models.PROTECT - защита от удаления статей привязанных к категории.
views = models.IntegerField(default=0, verbose_name='Просмотры')
slug = models.SlugField(max_length=250, unique=True, verbose_name='Слаг статей')
def get_absolute_url(self):
return reverse('view_news', kwargs={"slug": self.slug})
# Строковое представление объекта
def __str__(self):
return self.title
def save(self, *args, **kwargs):
value = self.title
self.slug = slugify(value, allow_unicode=True)
super().save(*args, **kwargs)
class Meta:
verbose_name = 'Новость'
verbose_name_plural = 'Новости'
ordering = ['-created_ad'] # '-created_ad' - посты в обратном порядке. Свежие первые.
class Category(models.Model):
title = models.CharField(max_length=150, db_index=True, verbose_name='Наименование каегории')
slug = models.SlugField(max_length=150, unique=True, verbose_name='Слаг категорий')
def get_absolute_url(self):
return reverse('category', kwargs={"slug": self.slug})
def __str__(self):
return self.title
def save(self, *args, **kwargs):
value = self.title
self.slug = slugify(value, allow_unicode=True)
super().save(*args, **kwargs)
class Meta:
verbose_name = 'Категория'
verbose_name_plural = 'Категории'
ordering = ['title']
views.py
Python:
from django.db.models import F
from django.shortcuts import render, get_object_or_404, redirect
from django.views.generic import ListView, DetailView, CreateView
from django.urls import reverse_lazy
from django.contrib.auth.mixins import LoginRequiredMixin
from .models import News, Category
from .forms import NewsForm, UserRegisterForm, UserLoginForm, ContactForm
from django.contrib import messages
from django.contrib.auth import login, logout
from django.core.mail import send_mail
def register(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
if form.is_valid():
user = form.save()
login(request, user)
messages.success(request, 'Вы успешно зарегистрировались!')
return redirect('home')
else:
messages.error(request, 'Ошибка регистрации')
else:
form = UserRegisterForm()
return render(request, 'news/register.html', {"form": form})
def user_login(request):
if request.method == 'POST':
form = UserLoginForm(data=request.POST)
if form.is_valid():
user = form.get_user()
login(request, user)
return redirect('home')
else:
form = UserLoginForm()
return render(request, 'news/login.html', {"form": form})
def user_logout(request):
logout(request)
return redirect('login')
def contact(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
mail = send_mail(form.cleaned_data['subject'], form.cleaned_data['content'], 'web-supsu@yandex.ru', ['kornyukhov94@mail.ru'], fail_silently=True)
if mail:
messages.success(request, 'Письмо отправлено!')
return redirect('contact')
else:
messages.error(request, 'Ошибка отправки')
else:
messages.error(request, 'Не верно заполнено одно из полей')
else:
form = ContactForm()
return render(request, 'news/test.html', {"form": form})
def search(request):
search_query = request.GET.get('search', '')
if search_query:
ser = News.objects.filter(title__icontains=search_query)
else:
ser = News.objects.all()
return render(request, 'news/search.html', {"ser": ser})
class HomeNews(ListView):
model = News
template_name = 'news/home_news_list.html'
context_object_name = 'news'
extra_context = {'title': 'Статьи'}
paginate_by = 5
def get_queryset(self):
return News.objects.filter(is_published=True).select_related('category') # .select_related('category') Убирает дублирование SQL запросов.
class ArticleListView(ListView):
template_name = 'news/home_page.html'
context_object_name = 'news'
extra_context = {'title': 'Главная'}
paginate_by = 5
def get_queryset(self):
return News.objects.filter(is_published=True).select_related('category')
class NewsByCategory(ListView):
model = News
context_object_name = 'news'
paginate_by = 5
def get_queryset(self):
return News.objects.filter(slug=self.kwargs['slug'], is_published=True).select_related('category')
class ArticleDetailView(DetailView):
model = News
context_object_name = 'news_item'
def get(self, request, *args, **kwargs):
self.object = self.get_object()
self.object.views += 1
self.object.save()
context = self.get_context_data(object=self.object)
return self.render_to_response(context)
class CreateNews(LoginRequiredMixin, CreateView):
login_url = '/admin/login/' # Перенаправление в админку для авторизации
form_class = NewsForm
template_name = 'news/add_news.html'
urls.py
Python:
from django.urls import path
from django.views.decorators.cache import cache_page
from .views import *
from news.views import ArticleListView, ArticleDetailView
urlpatterns = [
path('register/', register, name='register'),
path('login/', user_login, name='login'),
path('logout/', user_logout, name='logout'),
path('contact/', contact, name='contact'),
path('search/', search, name='search'),
# Страница с кэшем path('', cache_page(60)(HomeNews.as_view()), name='home'),
path('articles/', HomeNews.as_view(), name='articles'),
path('', ArticleListView.as_view(), name='home'),
path('news/<slug>/', ArticleDetailView.as_view(), name='view_news'),
path('category/<slug>/', NewsByCategory.as_view(), name='category'),
path('add-news/', CreateNews.as_view(), name='add_news'),
]
Шаблон в котором должны отображаться и фильтроваться статьи по категориям news_list.html
HTML:
{% extends 'base.html' %}
{% block title %}
{{ title }}
{% endblock %}
{% block sidebar %}
{% include 'inc/_sidebar.html' %}
{% endblock %}
{% block content %}
{% for item in object_list %}
<div class="card mb-3">
<div class="card-header">
Категория: <a href="{% url 'category' item.category.slug %}">{{ item.category }}</a>
</div>
<div class="card-body">
<div class="media">
{% if item.photo %}
<img src="{{ item.photo.url }}" alt="" width="350" class="mr-3">
{% else %}
<img src="" alt="" class="mr-3">
{% endif %}
<div class="media-body">
<h5 class="card-title text-center">{{ item.title }}</h5>
<p class="card-text">{{ item.content | safe | linebreaks | truncatewords:50 }}</p>
<a href="{{ item.get_absolute_url }}" class="btn btn-primary">Читать далее...</a>
</div>
</div>
</div>
<div class="card-footer text-muted">
{{ item.created_ad|date:"Y-m-d:i:s" }}
</div>
</div>
{% endfor %}
{% endblock %}
Подскажите пожалуйста, как мне сделать так, чтобы при переходе по ссылке категории меня перекидывало на страницу где размещены как раз те статьи на которую категорию я перешел.
Когда навожу на ссылку, то слаг работает, но когда перехожу на ссылку, то статьи пропадают:
Не закидывайте пожалуйста яйцами и помидорами. Уже 2 дня пытаюсь работаться, много вариантов перепробовал, гугл перерыл, ничего не получается((