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

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

Хочешь уверенно проходить IT-интервью?

Готовься к IT-собеседованиям уверенно с AI-тренажёром T1!

Мы понимаем, как сложно подготовиться: стресс, алгоритмы, вопросы, от которых голова идёт кругом. Но с AI тренажёром всё гораздо проще.

💡 Почему Т1 тренажёр — это мастхэв?

  • Получишь настоящую обратную связь: где затык, что подтянуть и как стать лучше
  • Научишься не только решать задачи, но и объяснять своё решение так, чтобы интервьюер сказал: "Вау!".
  • Освоишь все этапы собеседования, от вопросов по алгоритмам до диалога о твоих целях.

Зачем листать миллион туториалов? Просто зайди в Т1 тренажёр, потренируйся и уверенно удиви интервьюеров. Мы не обещаем лёгкой прогулки, но обещаем, что будешь готов!

Реклама. ООО «Смарт Гико», ИНН 7743264341. Erid 2VtzqwP8vqy


Пятый этап

Зарегистрированные пользователи сайта 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
Мессенджер на 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
Система комментариев на 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"
Результаты поиска по запросу "Python"

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

***

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


МЕРОПРИЯТИЯ

Комментарии

ВАКАНСИИ

Добавить вакансию

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