🐍🚀 Создаем рекрутинговый портал на 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 .
***
Материалы по теме