Share This
Связаться со мной
Крути в низ
Categories
//Пишем рекрутинговый портал на Django: часть 1. Веб-приложение на Django

Пишем рекрутинговый портал на Django: часть 1. Веб-приложение на Django

Разрабатываем портал, на котором каждый рекрутер сможет найти своего разработчика :). Система поиска позволяет подобрать нужного специалиста по резюме, портфолио или описанию проектов; рейтинг проекта поможет оценить квалификацию, а мессенджер – послать оффер.

pishem rekrutingovyj portal na django chast 1 veb prilozhenie na django 7dd5d6c - Пишем рекрутинговый портал на Django: часть 1. Веб-приложение на Django

Это достаточно сложный проект, состоящий из двух взаимосвязанных приложений – Projects и Users. Разработчики могут создавать профили и добавлять в портфолио проекты. Предусмотрены поиск, оценка проектов и обмен сообщениями. Реализована фильтрация по тегам (для проектов) и по скиллам (для профилей). Весь код проекта ITfinder находится здесь.

Обзор проекта

Сайт включает:

  1. Систему аутентификации и авторизации.
  2. Поиск по профилям, навыкам, тегам, описаниям проектов.
  3. Фильтрацию по тегам и скиллам.
  4. CRUD операции для создания, редактирования, удаления профилей, проектов, тегов и скиллов.
  5. Мессенджер.
  6. Систему оценок и отзывов о проектах.

pishem rekrutingovyj portal na django chast 1 veb prilozhenie na django 873e36c - Пишем рекрутинговый портал на Django: часть 1. Веб-приложение на Django

Главная страница – профили разработчиков

pishem rekrutingovyj portal na django chast 1 veb prilozhenie na django d22c8f5 - Пишем рекрутинговый портал на Django: часть 1. Веб-приложение на Django

Раздел «Проекты»

pishem rekrutingovyj portal na django chast 1 veb prilozhenie na django 6fcc56d - Пишем рекрутинговый портал на Django: часть 1. Веб-приложение на Django

Профиль разработчика

pishem rekrutingovyj portal na django chast 1 veb prilozhenie na django 753af32 - Пишем рекрутинговый портал на Django: часть 1. Веб-приложение на Django

Страница проекта с отзывами Больше полезных материалов вы найдете на нашем телеграм-канале «Библиотека питониста» Интересно, перейти к каналу

Первый этап

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

Установка Django и создание структуры проекта

Выполним установку фреймворка и зависимостей с помощью встроенного менеджера виртуального окружения venv:

         python -m venv itfindervenv cd itfinder venvscriptsactivate pip install -r requirements.txt      

Создадим новый проект под названием itfinder:

         django-admin startproject itfinder     

Проект состоит из двух приложений – «Проекты» и «Пользователи». Начнем работу с создания скелета проекта projects:

         cd itfinder python manage.py startapp projects      

Django автоматически создает базовую структуру приложения, но зарегистрировать projects в конфигурационном файле проекта придется вручную. Откройте файл itfindersettings.py, и добавьте в список INSTALLED_APPS строку 'projects.apps.ProjectsConfig'.

Теперь нужно создать основные маршруты приложения «Проекты». Создайте файл projects/urls.py и сохраните в нем нужные маршруты:

         from django.urls import path from . import views urlpatterns = [     path('', views.projects, name="projects"),     path('project-object/<str:pk>/', views.project, name="project"), ]      

Чтобы маршруты projects были доступны на уровне проекта, нужно включить их в глобальные URL – в файле itfinderurls.py:

         from django.contrib import admin from django.urls import path, include   urlpatterns = [      path('admin/', admin.site.urls),      path('', include('projects.urls')), ]      

Шаблоны приложения Projects

Создайте папку templates внутри projects, и в ней два файла – projects.html и single-project.html. Тестовый код для шаблона projects.html:

         <!DOCTYPE html> <html> <head>    <title>Шаблон для вывода проектов</title> </head> <body> <h2>Здесь будут все проекты</h2> {% for project in projects %} <p>Номер проекта: #{{ project.id }}</p> <h3>Название проекта: <a href="{% url 'project' project.id %}">{{ project.title }}</a></h3> <em>{{ project.description }}</em> {% endfor %} </body> </html>      

Для single-projects.html:

         <!DOCTYPE html> <html> <head>     <title>Шаблон для отдельного проекта</title> </head> <body> <h1>Подробная информация о проекте</h1> <h3>Проект #{{ project.id }}</h3> <p>{{ project.title }}</p> <br> <em>{{ project.description }}</em> </body> </html>      

Добавим import os и ссылку на шаблоны в файл настроек itfinder/settings.py:

          'DIRS': [os.path.join(BASE_DIR, 'templates')],     

Принцип работы Django основан на схеме MVT – (Модель, Представление, Шаблон). Если вам не приходилось раньше работать с Джанго, схему работы фреймворка может прояснить приведенный ниже пример того, как функция представления передает данные в шаблон, который мы только что создали. Напишем тестовые функции представления в файле projects/views.py:

         from django.shortcuts import render def projects(request):     projectsList = [{'id':'1',     'title':'Онлайн-кинотеатр',     'description':'Кинотеатр с самой полной библиотекой фильмов.'},     {'id':'2',     'title':'Платформа с ИТ-курсами',     'description':'Курсы по фронтенду, бэкенду и мобильной разработке.'},     {'id':'3',     'title':'Рекрутинговый портал',      'description':'Вакансии для специалистов экстра-класса.'},       ]     return render(request, 'projects/projects.html', {'projects':projectsList}) def project(request):     return render(request, 'projects/single-project.html')      

Запустите сервер python manage.py runserver и откройте адреса http://localhost:8000/ и http://localhost:8000/project/ – все работает, функция передает в шаблон тестовые данные:

pishem rekrutingovyj portal na django chast 1 veb prilozhenie na django 2b43ad7 - Пишем рекрутинговый портал на Django: часть 1. Веб-приложение на Django

Тестовое представление проектов

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

База данных

Джанго по умолчанию работает с базой типа SQLite3 – настройки для подключения указаны в файле itfinder/settings.py. Для инициализации базы данных выполним команду python manage.py migrate. Эта же команда используется для применения изменений, в дальнейшем мы будем ею пользоваться неоднократно, но уже в другом формате – после команды python manage.py makemigrations, которая отслеживает все изменения в моделях.

После инициализации базы Джанго открывает доступ к панели администрирования – http://localhost:8000/admin. Однако для создания учетной записи администратора (суперпользователя) нужно выполнить еще одну команду:

         python manage.py createsuperuser     

В ходе создания аккаунта можно пропустить введение имени – тогда по умолчанию будет назначен юзернейм user, и емейла (поле останется пустым). Если сейчас войти в панель администрирования, можно отметить, что пока там можно создавать, изменять и удалять только новых пользователей и группы.

pishem rekrutingovyj portal na django chast 1 veb prilozhenie na django 2f76178 - Пишем рекрутинговый портал на Django: часть 1. Веб-приложение на Django

Админ-панель

Для создания, редактирования и удаления других типов записей (профилей, проектов, комментариев) нужно сначала определить, а затем зарегистрировать в админ-панели нужные модели. Все атрибуты таблиц базы данных и взаимоотношения между ними определяются в файлах типа models.py. Модели представляют собой классы, все атрибуты которых ORM слой Django связывает с соответствующими полями таблиц. Благодаря этому отпадает необходимость использовать язык SQL.

Создадим нашу первую модель, которая будет хранить данные обо всех проектах, добавленных в раздел «Проекты». Это первый вариант модели, в дальнейшем мы ее расширим и дополним:

         from django.db import models import uuid class Project(models.Model):     title = models.CharField(max_length=100)     slug = models.SlugField()     description = models.TextField(null=True, blank=True)     demo_link = models.CharField(max_length=500, null=True, blank=True)     source_link = models.CharField(max_length=500, null=True, blank=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.title      

После создания модели нужно подготовить миграции:

         python manage.py makemigrations     

И применить их к базе:

         python manage.py migrate     

Чтобы модель была доступна в панели администрирования, ее нужно зарегистрировать в файле itfinder/admin.py:

         from django.contrib import admin from .models import Project   admin.site.register(Project)      

После регистрации форма добавления проектов становится доступной в панели администрирования:

pishem rekrutingovyj portal na django chast 1 veb prilozhenie na django 285562d - Пишем рекрутинговый портал на Django: часть 1. Веб-приложение на Django

Теперь можно добавлять проекты

В нашем приложении будет несколько моделей, связанных друг с другом различными способами:

  1. Один к одному – у одного пользователя может быть только один профиль.
  2. Один ко многим – один пользователь (профиль) может быть автором множества проектов; один проект может получить множество отзывов / комментариев / оценок. Для реализации такой связи служит ForeignKey. Установление связи между таблицами с помощью ForeignKey нуждается в дополнительных параметрах на случай удаления одной из таблиц. В случае с проектом и отзывами к нему это CASCADE – он удаляет отзыв в случае удаления проекта, к которому отзыв относился.
  3. Многие ко многим – у одного проекта может быть множество тегов, а у пользователя – несколько навыков. Один и тот же тег (навык) может использоваться во множестве проектов (или профилей).

Связь проекта с тегами и отзывами

Расширим модель Project, добавив в нее связь с таблицами тегов и отзывов:

         from django.db import models import uuid  class Tag(models.Model):     name = models.CharField(max_length=100)     slug = models.SlugField()     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.name	    class Project(models.Model):      title = models.CharField(max_length=100)      slug = models.SlugField()      description = models.TextField(null=True, blank=True)      tags = models.ManyToManyField(Tag, blank=True)      total_votes = models.IntegerField(default=0, null=True, blank=True)      votes_ratio = models.IntegerField(default=0, null=True, blank=True)      demo_link = models.CharField(max_length=500, null=True, blank=True)      source_link = models.CharField(max_length=500, null=True, blank=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.title   class Review(models.Model):      project = models.ForeignKey(Project, on_delete=models.CASCADE)      VOTE_TYPE = (      ('up', 'Up Vote'),      ('down', 'Down Vote'),      )      review_text = 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)	        def __str__(self):          return self.value      

Зарегистрируем новые модели в admin.py:

         from django.contrib import admin from .models import Project, Review, Tag   admin.site.register(Project) admin.site.register(Review) admin.site.register(Tag)      

Выполним миграции и откроем админ-панель – теперь к проектам можно добавлять теги, рейтинг и отзывы:

pishem rekrutingovyj portal na django chast 1 veb prilozhenie na django e93da7c - Пишем рекрутинговый портал на Django: часть 1. Веб-приложение на Django

Теги, рейтинг и отзывы о проектах

Создайте несколько проектов или воспользуйтесь готовой базой данных. Эта информация нам понадобится для реализации следующего шага – запросов.

Запросы к базе данных

Структура запроса к базе данных в Джанго выглядит так:

         Queryset = ModelName.objects.all()     
  • где Queryset – переменная, которой передаются результаты запроса;
  • ModelName – название модели;
  • objects – атрибут объекта модели;
  • all() – метод.

Кроме all(), который возвращает все объекты модели, есть множество других методов, например:

  • filter, filter_by – фильтруют по значениям атрибутов. При этом значение может быть равно запросу, содержать ключевое слово или начинаться с определенного критерия. Фильтры могут учитывать или игнорировать регистр.
  • icontains – проверяет, содержит ли поле определенный запрос.
  • get – возвращает единичный объект;
  • exclude – исключает определенные значения.

Тестировать запросы удобно в интерактивной консоли, которую запускают командой python manage.py shell:

         python manage.py shell >>> from projects.models import Project >>> projects = Project.objects.all() >>> print(projects) <QuerySet [<Project: EverGreen - магазин люксовой эко-косметики>, <Project: ITGi gs - платформа для поиска ИТ-фрилансеров>, <Project: BlahBlahChat - социальная с еть нового поколения>, <Project: RoboShop - магазин электронных игрушек>, <Proje ct: SuperCook - сайт для кулинарного блогера>]> >>> singleproject = Project.objects.get(title='RoboShop - магазин электронных иг рушек') >>> print(singleproject) RoboShop - магазин электронных игрушек >>> print(singleproject.created) 2022-07-05 15:40:34.240616+00:00 >>> print(singleproject.slug) roboshop-magazin-igrushek >>> exit()      

Передача данных из базы в шаблон

Откройте файл itfinder/views.py, добавьте в него импорт моделей:

         from .models import Project     

И измените функцию представления projects на эту:

         def projects(request):     projects = Project.objects.all()     context = {'projects': projects}     return render(request, 'projects/projects.html', context)     

Функция представления отдельного проекта теперь должна выглядеть так:

         def project(request, pk):     projectObj = Project.objects.get(id=pk)     tags = projectObj.tags.all()     return render(request, 'projects/single-project.html', {'project': projectObj})     

В шаблон для вывода отдельных проектов нужно добавить отображение тегов:

         <!DOCTYPE html> <html> <head>             	<title>Шаблон для отдельного проекта</title>             	<meta charset="UTF-8"> </head> <body> <h1>Подробная информация о проекте</h1> <h3>Проект {{ project.id }}</h3> <p>{{ project.title }}</p> <br> <ul> {% for tag in project.tags.all %} <li>{{ tag }}</li> {% endfor %} </ul> <em>{{ project.description }}</em> </body> </html>      

Запустите сервер – на главной странице сайта появилось описание проектов из базы данных:

pishem rekrutingovyj portal na django chast 1 veb prilozhenie na django 2ccd4e3 - Пишем рекрутинговый портал на Django: часть 1. Веб-приложение на Django

Вывод всех проектов

И описание отдельного проекта тоже выводится – с тегами:

pishem rekrutingovyj portal na django chast 1 veb prilozhenie na django 98d68e5 - Пишем рекрутинговый портал на Django: часть 1. Веб-приложение на Django

Вывод отдельного проекта

Код и база данных для первого этапа – здесь.

Второй этап

Начнем с разработки CRUD – функциональности для создания, редактирования и удаления проектов.

Сначала сделаем шаблон для формы, которая будет использоваться как для создания, так и для редактирования проектов. Сохраните этот код в project_form.html:

         {% block content %} <h1>Информация о проекте</h1> <form method="POST">     {% csrf_token %}     {{ form.as_p }}     <input type="submit" name="" value="Добавить проект"> </form> {% endblock content %}     

Токен csrf_token обеспечивает защиту сайта от атак; кроме того, без него форма просто не будет обрабатываться. Параметр .as_p создает теги <p></p> вокруг элементов формы.

Создайте файл itfinderforms.py:

         from django.forms import ModelForm from .models import Project   class ProjectForm(ModelForm):     class Meta:         model = Project         fields = ['title', 'slug', 'tags', 'description', 'demo_link', 'source_link']      

Во многих случаях вместо строки с перечислением полей можно указать fields = '__all__' – тогда модуль ModelForm автоматически сгенерирует форму на основе модели проекта, и перечислять поля по отдельности не придется. При этом модуль проигнорирует поля, которые не подлежат редактированию (как уникальный UUID), и пропустит поля, создаваемые во время сохранения записи (как created). Однако в нашей модели Project есть поля, которые обновляются при подсчете рейтинга, и пользователи не должны иметь доступа к ним, поэтому в форме мы перечисляем только редактируемые поля.

Добавьте ссылку на создание проекта в шаблон projects.html:

         <strong><a href="{% url 'create-project' %}">Добавить проект</a></strong>     

Перезагрузите страницу – форма создания нового проекта благополучно загружается, хотя пока что не имеет никакого дизайна (и ничего не сохраняет):

pishem rekrutingovyj portal na django chast 1 veb prilozhenie na django cd03471 - Пишем рекрутинговый портал на Django: часть 1. Веб-приложение на Django

Форма без дизайна

Чтобы форма сохраняла данные, внесем дополнения в itfinder/views.py добавим импорт redirect и обработку POST:

         def createProject(request):     form = ProjectForm()     if request.method == 'POST':         form = ProjectForm(request.POST)         if form.is_valid():             form.save()     return redirect('projects')      

Теперь данные сохраняются – запись добавлена в список проектов. Реализовать редактирование проектов несложно. Сначала добавим новую функцию в views.py:

         def updateProject(request, pk):     project = Project.objects.get(id=pk)     form = ProjectForm(instance=project)     if request.method == 'POST':         form = ProjectForm(request.POST, instance=project)         if form.is_valid():             form.save()             return redirect('projects')     context = {'form': form}     return render(request, 'projects/project_form.html', context)      

Параметр instance=project здесь обеспечивает предзаполнение формы существующими в базе данными:

pishem rekrutingovyj portal na django chast 1 veb prilozhenie na django f0c391d - Пишем рекрутинговый портал на Django: часть 1. Веб-приложение на Django

Автоматическое заполнение существующими данными

Теперь сделаем нужный маршрут в urls.py:

         path('update-project/<str:pk>', views.updateProject, name="update-project"),     

И добавим ссылку на редактирование в шаблон projects.html:

         <h4><a href="{% url 'update-project' project.id %}">Редактировать проект</a></h4>     

Для удаления проектов (а в дальнейшем – и других объектов) нужно сделать шаблон, запрашивающий подтверждение действий пользователя. Создайте файл delete.html и сохраните в нем код:

         {% block content %} <form action="" method="POST">      {% csrf_token %}      <p>Вы действительно хотите удалить "{{ object }}"?</p>      <a href="{% url 'projects' %}">Отмена</a>      <input type="submit" name="" value="Подтвердить удаление" /> </form> {% endblock %}      

В файл views.py добавьте функцию удаления:

         def deleteProject(request, pk):     project = Project.objects.get(id=pk)     if request.method == 'POST':         project.delete()         return redirect('projects')     context = {'object': project}     return render(request, 'projects/delete.html', context)     

На этом работа по созданию CRUD закончена, перейдем к дизайну и статическим файлам.

Статические файлы

Создайте папку static в корневой директории проекта. Внутри static создайте 3 папки:

  • styles – в ней будут находиться css файлы. Поместите туда main.css.
  • js – для скриптов. Положите туда этот скрипт.
  • uikit – для стилей фронтенда. Там должны быть все эти файлы.

Чтобы Джанго знал, откуда загружать стили, нужно внести дополнения в файл настроек settings.py:

         STATICFILES_DIRS = [ 	BASE_DIR / 'static' ]      

Помимо шаблонов, находящихся в папке projects, нам понадобится набор шаблонов, определяющих внешний вид проекта на, так сказать, глобальном уровне. Для этих шаблонов нужно создать папку templates в корневой директории проекта itfinder. Сейчас в эту папку нужно поместить эти два файла – base.html и navbar.html, позже мы добавим туда еще несколько шаблонов.

Шаблоны в папке templates/projects нужно заменить на эти – они соответствуют готовой версии приложения и содержат ссылки на атрибуты моделей, которые мы разработаем на последующих этапах.

Последнее, что мы сделаем на этом этапе – добавим фильтр проектов по тегам. Для этого в views.py нужно добавить эту функцию:

         def projects_by_tag(request, tag_slug):     tag = get_object_or_404(Tag, slug=tag_slug)     projects = Project.objects.filter(tags__in=[tag])     context = {     	"projects": projects 	}       return render(request, "projects/projects.html", context)      

В файл urls.py надо вставить маршрут:

         path('tag/<slug:tag_slug>', views.projects_by_tag, name="tag"),     

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

         <div class="project__tags">    {% for tag in project.tags.all %}       <a href="{% url 'tag' tag.slug %}" class="tag tag--pill tag--main">{{tag}}</a>    {% endfor %} </div>      

А в шаблон single-project.html этот:

         <div class="singleProject__toolStack">   {% for tag in project.tags.all %}       <a href="{% url 'tag' tag.slug %}" class="tag tag--pill tag--sub tag--lg">{{tag}}</a>   {% endfor %}           	 </div>     

Запустим сервер – наш проект получил дизайн и обзавелся фильтрацией по тегам, причем фильтр работает как на главной странице, так и на странице отдельного проекта:

pishem rekrutingovyj portal na django chast 1 veb prilozhenie na django 5b0a805 - Пишем рекрутинговый портал на Django: часть 1. Веб-приложение на Django

Фильтр по тегу Angular

Весь код для этого этапа можно взять здесь.

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

***

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

  • 🐍🚀 Django с нуля. Часть 1: пишем многопользовательский блог для клуба любителей задач Python
  • 🐍🚀 Django с нуля. Часть 2: регистрация, авторизация, ограничение доступа
  • 🐍🚀 Django с нуля. Часть 3: создание профилей, сжатие изображений, CRUD и пагинация

  • 5 views
  • 0 Comment

Leave a Reply

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.

Связаться со мной
Close