🐍🚀 Создаем рекрутинговый портал на Django: часть 3

В заключительной части: создание мессенджера, реализация поиска по профилям и проектам, отзывы и пагинация.

Пятый этап

Зарегистрированные пользователи сайта ITfinder должны иметь возможность обмениваться сообщениями и оставлять отзывы о проектах. И то, и другое реализовать на Django несложно.

Мессенджер

Начнем работу с создания модели Message – сохраните этот код в users/models.py:

class Message(models.Model):
    sender = models.ForeignKey(
        Profile, on_delete=models.SET_NULL, null=True, blank=True)
    recipient = models.ForeignKey(
        Profile, on_delete=models.SET_NULL, null=True, blank=True, related_name="messages")
    name = models.CharField(max_length=200, null=True, blank=True)
    email = models.EmailField(max_length=200, null=True, blank=True)
    subject = models.CharField(max_length=200, null=True, blank=True)
    body = models.TextField()
    is_read = models.BooleanField(default=False, null=True)
    created = models.DateTimeField(auto_now_add=True)
    id = models.UUIDField(default=uuid.uuid4, unique=True,
                        primary_key=True, editable=False)
 
    def __str__(self):
        return self.subject
 
    class Meta:
        ordering = ['is_read', '-created']

Подготовьте и примените миграции:

python manage.py makemigrations
python manage.py migrate 

После этого добавьте импорт Message и новый класс в users/form.py:

class MessageForm(ModelForm):
    class Meta:
        model = Message
        fields = ['name', 'email', 'subject', 'body']
 
    def __init__(self, *args, **kwargs):
        super(MessageForm, self).__init__(*args, **kwargs)
 
        for name, field in self.fields.items():
            field.widget.attrs.update({'class': 'input'})

Шаблоны, которые понадобятся для мессенджера:

Сохраните эти шаблоны в templates/users. Еще мы добавим ссылку на входящие в шаблоне navbar.html{% url 'inbox' %}.

Мессенджер на Django
Больше полезных материалов вы найдете на нашем телеграм-канале «Библиотека питониста»

Отзывы о проектах

В первой части туториала мы уже частично реализовали функциональность для отзывов о проектах. Теперь нам нужно связать отзывы с пользователями. Для этого мы внесем дополнения в модель Project:

    @property
    def reviewers(self):
        queryset = self.review_set.all().values_list('owner__id', flat=True)
        return queryset
 
    @property
    def getVoteCount(self):
        reviews = self.review_set.all()
        upVotes = reviews.filter(value='up').count()
        totalVotes = reviews.count()
 
        ratio = (upVotes / totalVotes) * 100
        self.vote_total = totalVotes
        self.vote_ratio = ratio
 
        self.save()

Дополним класс Review:

class Review(models.Model):
    VOTE_TYPE = (
        ('up', 'Положительная оценка'),
        ('down', 'Отрицательная оценка'),
    )
    owner = models.ForeignKey(Profile, on_delete=models.CASCADE, null=True)
    project = models.ForeignKey(Project, on_delete=models.CASCADE)
    body = models.TextField(null=True, blank=True)
    value = models.CharField(max_length=200, choices=VOTE_TYPE)
    created = models.DateTimeField(auto_now_add=True)
    id = models.UUIDField(default=uuid.uuid4, unique=True,
                          primary_key=True, editable=False)
 
    class Meta:
        unique_together = [['owner', 'project']]
 
    def __str__(self):
        return self.value

В шаблоне single-projects.html изменим ссылки на авторов отзывов: {% url 'user-profile' review.owner %}, после чего добавим форму отзыва в projects/forms.py:

class ReviewForm(ModelForm):
    class Meta:
        model = Review
        fields = ['value', 'body']
 
        labels = {
            'value': 'Оцените проект',
            'body': 'Добавьте комментарий'
        }
 
    def __init__(self, *args, **kwargs):
        super(ReviewForm, self).__init__(*args, **kwargs)
 
        for name, field in self.fields.items():
            field.widget.attrs.update({'class': 'input'})

Осталось внести небольшие изменения в представление проекта в файле projects/views.py. Добавим import ReviewForm и код:

def project(request, project_slug):
   project = Project.objects.get(slug=project_slug)
   tags = project.tags.all()
   form = ReviewForm()
   if request.method == 'POST':
       form = ReviewForm(request.POST)
       review = form.save(commit=False)
       review.project = project
       review.owner = request.user.profile
       review.save()
       project.getVoteCount
       messages.success(request, 'Ваш отзыв был добавлен!')
       return redirect('project', project_slug=project.slug)   
   return render(request, 'projects/single-project.html', {'project': project, 'form': form})

Готово, теперь на сайте есть система отзывов:

Система комментариев на Django

Шестой этап

На заключительном этапе мы сделаем пагинацию профилей и проектов, а затем реализуем систему поиска.

Пагинация

Сначала сделаем пагинацию для вывода проектов. Создайте файл projects/utils.py, а в файл projects/views.py добавьте импорт:

from django.core import paginator
from .utils import paginateProjects

В конец шаблона projects.html добавьте:

{% include 'pagination.html' with queryset=projects custom_range=custom_range %}

После этого в папку с глобальными шаблонами положите файл pagination.html.

Запустите сервер и проверьте: проекты теперь выводятся постранично.

Таким же образом сделаем пагинацию для постраничного вывода профилей в приложении Users:

Готово – теперь профили выводятся по 6 штук на странице:

Пагинация

Поиск

Мы реализуем поиск по проектам и профилям с помощью модуля Q. Сначала добавим импорт from django.db.models import Q и эту функцию в projects/utils.py:

 def searchProjects(request):
     search_query = ''
     if request.GET.get('search_query'):
        search_query = request.GET.get('search_query')
     tags = Tag.objects.filter(name__icontains=search_query)
 
    projects = Project.objects.distinct().filter(
        Q(title__icontains=search_query) |
        Q(description__icontains=search_query) |
        Q(owner__name__icontains=search_query) |
        Q(tags__in=tags)
    )
    return projects, search_query

Использование модуля Q значительно изменит представление для вывода проектов:

def projects(request):
    projects, search_query = searchProjects(request)
    custom_range, projects = paginateProjects(request, projects, 6)
 
    context = {'projects': projects,
            'search_query': search_query, 'custom_range': custom_range}
    return render(request, 'projects/projects.html', context)

Вызов Q в шаблоне projects.html производит {{ search_query }}. Все готово – поиск по проектам работает:

Результаты поиска по запросу "магазин"

То же самое сделаем для поиска по профилям. Добавим функцию поиска в users/utils.py:

def searchProfiles(request):
    search_query = ''
    if request.GET.get('search_query'):
        search_query = request.GET.get('search_query')
 
    skills = Skill.objects.filter(name__icontains=search_query)
    profiles = Profile.objects.distinct().filter(
        Q(name__icontains=search_query) |
        Q(short_intro__icontains=search_query) |
        Q(skill__in=skills)
    )
    return profiles, search_query

Изменим представление для вывода профилей в users/views.py:

def profiles(request):
    profiles, search_query = searchProfiles(request)
 
    custom_range, profiles = paginateProfiles(request, profiles, 6)
    context = {'profiles': profiles, 'search_query': search_query,
            'custom_range': custom_range}
    return render(request, 'users/profiles.html', context)

И добавим {{ search_query }} в profiles.html. Готово – поиск по профилям работает:

Результаты поиска по запросу "Python"

На этом разработка сайта завершена. Код готового проекта можно взять в репозитории ITfinder.

***

Материалы по теме


ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ

admin
11 декабря 2018

ООП на Python: концепции, принципы и примеры реализации

Программирование на Python допускает различные методологии, но в его основе...
admin
28 июня 2018

3 самых важных сферы применения Python: возможности языка

Существует множество областей применения Python, но в некоторых он особенно...
admin
13 февраля 2017

Программирование на Python: от новичка до профессионала

Пошаговая инструкция для всех, кто хочет изучить программирование на Python...