from django.shortcuts import render, get_object_or_404, redirect from django.http import HttpResponse, Http404 from django.template import TemplateDoesNotExist from django.template.loader import get_template from django.contrib.auth.views import LoginView, LogoutView, PasswordChangeView from django.contrib.auth.decorators import login_required from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth import logout from django.contrib import messages from django.contrib.messages.views import SuccessMessageMixin from django.views.generic.edit import UpdateView, CreateView, DeleteView from django.views.generic.base import TemplateView from django.urls import reverse_lazy from django.core.signing import BadSignature from django.core.paginator import Paginator from django.db.models import Q from .models import AdvUser, SubRubric, Ad, Comment from .forms import ChangeUserInfoForm, RegisterUserForm, SearchForm, AdForm, AIFormSet, UserCommentForm, GuestCommentForm from .utilities import signer def index(request): # Вывод последних 10 объявлений ads = Ad.objects.filter(is_active=True)[:10] context = {'ads': ads} return render(request, 'main/index.html', context) def other_page(request, page): try: template = get_template('main/' + page + '.html') except TemplateDoesNotExist: raise Http404 return HttpResponse(template.render(request=request)) class BLoginView(LoginView): template_name = 'main/login.html' @login_required def profile(request): ads = Ad.objects.filter(author=request.user.pk) context = {'ads': ads} return render(request, 'main/profile.html', context) class BLogoutView(LoginRequiredMixin, LogoutView): template_name = 'main/logout.html' class ChangeUserInfoView(SuccessMessageMixin, LoginRequiredMixin, UpdateView): model = AdvUser template_name = 'main/change_user_info.html' form_class = ChangeUserInfoForm success_url = reverse_lazy('main:profile') success_message = 'Данные пользователя изменены' def setup(self, request, *args, **kwargs): self.user_id = request.user.pk return super().setup(request, *args, **kwargs) def get_object(self, queryset=None): if not queryset: queryset = self.get_queryset() return get_object_or_404(queryset, pk=self.user_id) class BPasswordChangeView(SuccessMessageMixin, LoginRequiredMixin, PasswordChangeView): template_name = 'main/password_change.html' success_url = reverse_lazy('main:profile') success_message = 'Пароль пользователя изменен' class RegisterUserView(CreateView): model = AdvUser template_name = 'main/register_user.html' form_class = RegisterUserForm success_url = reverse_lazy('main:register_done') class RegisterDoneView(TemplateView): template_name = 'main/register_done.html' def user_activate(request, sign): try: username = signer.unsign(sign) except BadSignature: return render(request, 'main/bad_signature.html') user = get_object_or_404(AdvUser, username=username) if user.is_activated: template = 'main/user_is_activated.html' else: template = 'main/activation_done.html' user.is_active = True user.is_activated = True user.save() return render(request, template) class DeleteUserView(LoginRequiredMixin, DeleteView): model = AdvUser template_name = 'main/delete_user.html' success_url = reverse_lazy('main:index') def setup(self, request, *args, **kwargs): # Сохраняем ключ текущего пользователя self.user_id = request.user.pk return super().setup(request, *args, **kwargs) def post(self, request, *args, **kwargs): # Делаем выход для текущего пользователя и создаем всплывающее сообщение об успешном удалении logout(request) messages.add_message(request, messages.SUCCESS, 'Пользователь удален') return super().post(request, *args, **kwargs) def get_object(self, queryset=None): # Отыскиваем по ключу пользователя, подлежащего удалению if not queryset: queryset = self.get_queryset() return get_object_or_404(queryset, pk=self.user_id) def by_rubric(request, pk): rubric = get_object_or_404(SubRubric, pk=pk) # Название рубрики ads = Ad.objects.filter(is_active=True, rubric=pk) # Объявления, относящиеся к рубрике keyword = request.GET.get('keyword', False) if keyword: q = Q(title__icontains=keyword) | Q(content__icontains=keyword) # Фильтрация уже отобранных объявлений по введенному пользователю искомому слову ads = ads.filter(q) else: keyword = '' form = SearchForm(initial={'keyword': keyword}) # Вывод формы поиска paginator = Paginator(ads, 2) # Пагинатор, выводящий по 2 объявления page = request.GET.get('page', False) if page: page_num = page else: page_num = 1 page = paginator.get_page(page_num) context = {'rubric': rubric, 'page': page, 'ads': page.object_list, 'form': form} return render(request, 'main/by_rubric.html', context) def detail(request, rubric_pk, pk): ad = Ad.objects.get(pk=pk) ais = ad.additionalimage_set.all() comments = Comment.objects.filter(ad=pk, is_active=True) initial = {'ad': ad.pk} # В поле ad создаваемой формы ввода комментария заносим ключ выводящегося на странице объявления. С этим объявлением будет связан комментарий. if request.user.is_authenticated: initial['author'] = request.user.username form_class = UserCommentForm else: form_class = GuestCommentForm form = form_class(initial=initial) if request.method == 'POST': c_form = form_class(request.POST) if c_form.is_valid(): c_form.save() messages.add_message(request, messages.SUCCESS, 'Комментарий добавлен') else: form = c_form # Переносим форму из переменной c_form в переменную form. Эта форма, хранящая некорректные данные и сообщения об ошибках ввода, будет выведена на экран, # и посетитель сразу увидит, что он ввел не так. messages.add_message(request, messages.WARNING, 'Комментарий не добавлен') context = {'ad': ad, 'ais': ais, 'comments': comments, 'form': form} return render(request, 'main/detail.html', context) @login_required def profile_ad_detail(request, pk): ad = get_object_or_404(Ad, pk=pk) ais = ad.additionalimage_set.all() comments = Comment.objects.filter(ad=pk, is_active=True) context = {'ad': ad, 'ais': ais, 'comments': comments} return render(request, 'main/profile_ad_detail.html', context) @login_required def profile_ad_add(request): if request.method == 'POST': form = AdForm(request.POST, request.FILES) if form.is_valid(): ad = form.save() formset = AIFormSet(request.POST, request.FILES, instance=ad) if formset.is_valid(): formset.save() messages.add_message(request, messages.SUCCESS, 'Объявление добавлено') return redirect('main:profile') else: form = AdForm(initial={'author': request.user.pk}) formset = AIFormSet() context = {'form': form, 'formset': formset} return render(request, 'main/profile_ad_add.html', context) @login_required def profile_ad_change(request, pk): ad = get_object_or_404(Ad, pk=pk) if request.method == 'POST': form = AdForm(request.POST, request.FILES, instance=ad) if form.is_valid(): ad = form.save() formset = AIFormSet(request.POST, request.FILES, instance=ad) if formset.is_valid(): formset.save() messages.add_message(request, messages.SUCCESS, 'Объявление исправлено') return redirect('main:profile') else: form = AdForm(instance=ad) formset = AIFormSet(instance=ad) context = {'form': form, 'formset': formset} return render(request, 'main/profile_ad_change.html', context) @login_required def profile_ad_delete(request, pk): ad = get_object_or_404(Ad, pk=pk) if request.method == 'POST': ad.delete() messages.add_message(request, messages.SUCCESS, 'Объявление удалено') return redirect('main:profile') else: context = {'ad': ad} return render(request, 'main/profile_ad_delete.html', context)