Share This
Связаться со мной
Крути в низ
Categories
//Создаем портфолио разработчика с помощью django

Создаем портфолио разработчика с помощью django

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

sozdaem portfolio razrabotchika s pomoshhju django 04ed415 - Создаем портфолио разработчика с помощью django

← Часть 2 ORM и основы работы с базами данных

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

Приложение состоит из 3 основных разделов – главной страницы, резюме и секции «Контакты». На главной странице выводятся все работы, перечень услуг (со списками используемых инструментов), и отзывы заказчиков:

sozdaem portfolio razrabotchika s pomoshhju django c147cb6 - Создаем портфолио разработчика с помощью django

Главная страница

Раздел «Обо мне», по сути, является резюме владельца портфолио – здесь можно разместить подробные сведения об образовании, опыте работе и уровне профессиональных навыков:

sozdaem portfolio razrabotchika s pomoshhju django 8c50209 - Создаем портфолио разработчика с помощью django

Резюме разработчика

В разделе «Контакты» перечислены всевозможные способы связи с владельцем портфолио, но самое главное – там еще есть форма для отправки сообщения:

sozdaem portfolio razrabotchika s pomoshhju django 19cd45a - Создаем портфолио разработчика с помощью django

Контактная форма

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

sozdaem portfolio razrabotchika s pomoshhju django 151fa47 - Создаем портфолио разработчика с помощью django

А теперь расскажем, как это все сделать.

? Библиотека питониста Больше полезных материалов вы найдете на нашем телеграм-канале «Библиотека питониста» ?? Библиотека собеса по Python Подтянуть свои знания по Python вы можете на нашем телеграм-канале«Библиотека собеса по Python» ?? Библиотека задач по Python» Интересные задачи по Python для практики можно найти на нашем телеграм-канале«Библиотека задач по Python»

Ход работы

Весь код есть в репозитории: просто скопируйте, если что-то не получается.

Установка Django, Pillow и настройки проекта

Для хранения ссылок на изображения (и автоматической загрузки изображений в папку media) нужна библиотека Pillow – установите ее сразу после Django:

         python -m venv myportfoliovenv cd myportfolio venvscriptsactivate pip install django pip install pillow django-admin startproject config . python manage.py startapp portfolio      

Добавьте приложение portfolio в INSTALLED_APPS в config/settings.py:

         INSTALLED_APPS = [     'portfolio.apps.PortfolioConfig',     'django.contrib.admin',     'django.contrib.auth',     'django.contrib.contenttypes',     'django.contrib.sessions',     'django.contrib.messages',     'django.contrib.staticfiles', ]     

Также добавьте в config/settings.py настройки для вывода сообщений:

         MESSAGE_TAGS = {         messages.DEBUG: 'alert-secondary',         messages.INFO: 'alert-info',         messages.SUCCESS: 'alert-success',         messages.WARNING: 'alert-warning',         messages.ERROR: 'alert-danger', }     

И пути к папкам static и media:

         STATIC_URL = '/static/' STATICFILES_DIRS = [BASE_DIR / "static"] MEDIA_URL = '/media/' MEDIA_ROOT = BASE_DIR / "media"      

Для удобства еще можно изменить язык админки на русский, а время – на московское:

         LANGUAGE_CODE = 'ru'  TIME_ZONE = 'Europe/Moscow'     

Чтобы Django мог работать с папками static и media, нужно добавить эти пути в файл config/urls.py:

         from django.contrib import admin from django.urls import path from django.conf import settings from django.conf.urls.static import static  urlpatterns = [     path('admin/', admin.site.urls), ]  urlpatterns += static(settings.MEDIA_URL,      document_root=settings.MEDIA_ROOT) urlpatterns += static(settings.STATIC_URL,      document_root=settings.STATIC_ROOT)     

Создание базы данных и аккаунта админа

Инициализируйте базу и создайте аккаунт суперпользователя:

         python manage.py migrate python manage.py createsuperuser      

Теперь можно приступить к созданию нужных таблиц в БД. Сохраните эти модели в файле portfolio/models.py:

         from django.db import models  class Skill(models.Model):     name = models.CharField(max_length=30)     level = models.CharField(max_length=3)      class Meta:         ordering = ['id']         verbose_name = 'Навык'         verbose_name_plural = 'Навыки'      def __str__(self):         return self.name   class Category(models.Model):     engname = models.CharField(max_length=25)     rusname = models.CharField(max_length=25)       class Meta:         ordering = ['id']         verbose_name = 'Категория'         verbose_name_plural = 'Категории'      def __str__(self):         return self.rusname  class Work(models.Model):     title = models.CharField(max_length=150)     slug = models.SlugField(max_length=150, unique=True)     category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='works')     image = models.ImageField(upload_to='works')     description = models.TextField()     stack = models.TextField()     link = models.URLField(max_length=200)       class Meta:         ordering = ['-id']         verbose_name = 'Работа'         verbose_name_plural = 'Работы'      def __str__(self):         return self.title   class Service(models.Model):     name = models.CharField(max_length=25)     icon = models.CharField(max_length=50)     description = models.CharField(max_length=200)      class Meta:         ordering = ['id']         verbose_name = 'Сервис'         verbose_name_plural = 'Виды сервиса'      def __str__(self):         return self.name      class Item(models.Model):     name = models.CharField(max_length=150)     service = models.ForeignKey(Service, on_delete=models.CASCADE)      class Meta:         ordering = ['-id']         verbose_name = 'Инструмент'         verbose_name_plural = 'Инструменты'      def __str__(self):         return self.name        class Author(models.Model):     name = models.CharField(max_length=15)     lastname = models.CharField(max_length=15)     about = models.TextField()     skills = models.ManyToManyField(Skill, related_name='author')     image = models.ImageField(upload_to='author')      class Meta:         ordering = ['-id']         verbose_name = 'Автор'         verbose_name_plural = 'Авторы'      def __str__(self):         return f'{self.name} {self.lastname}'   class Message(models.Model):     name = models.CharField(max_length=100)     email = models.EmailField()     subject = models.CharField(max_length=100)     message = models.TextField()     created_at = models.DateTimeField(auto_now_add=True)      class Meta:         ordering = ['-created_at']         verbose_name = 'Сообщение'         verbose_name_plural = 'Сообщения'      def __str__(self):         return f'Сообщение от {self.name}: {self.subject}'     class Testimony(models.Model):     name = models.CharField(max_length=15)     lastname = models.CharField(max_length=15)       image = models.ImageField(upload_to='clients')      text = models.TextField()           class Meta:         ordering = ['-id']         verbose_name = 'Заказчик'         verbose_name_plural = 'Заказчики'      def __str__(self):         return f'{self.name} {self.lastname}'      

А затем подготовьте и примените миграции (изменения в структуре БД):

         python manage.py makemigrations python manage.py migrate      

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

         from django.contrib import admin from .models import Skill, Author, Category, Testimony, Work, Item, Service, Message   class ItemInline(admin.TabularInline):     model = Item   class ServiceAdmin(admin.ModelAdmin):     inlines = [ItemInline]    admin.site.register(Category) admin.site.register(Testimony) admin.site.register(Skill)  admin.site.register(Service, ServiceAdmin) admin.site.register(Author) admin.site.register(Work) admin.site.register(Item) admin.site.register(Message)     

Разберемся, что и как определяют эти модели.

Skill – навыки. Название и уровень навыка позволяют рендерить на фронтенде эти данные:

sozdaem portfolio razrabotchika s pomoshhju django 93dc4b7 - Создаем портфолио разработчика с помощью django

Визуализацией навыков занимается Bootstrap

Данные из Category используются не только для указания категории, к которой принадлежит проект, но и для фильтрации работ с помощью плагина Isotope.js:

         <div id="filters" class="filters">  <a href="#" data-filter="*" class="active">Все</a>  {% for category in categories %}  <a href="#" data-filter=".{{ category.engname }}">{{ category.rusname }}</a>  {% endfor %} </div>     

Work, как и модели Author и Testimony, использует ImageField для автоматической загрузки изображений в соответствующие поддиректории media, а также для создания и хранения ссылок на эти изображения. Работу ImageField обеспечивает библиотека Pillow:

         image = models.ImageField(upload_to='works')     

Для хранения ссылок на готовые сайты используется поле URLField.

В модели Service хранятся виды услуг. Поскольку в оформлении портфолио используются иконки BoxIcons, в поле icon нужно сохранять название нужной иконки в этом наборе, например, bx bx-laptop. При использовании другого набора, скажем, Font Awesome, нужно вводить названия иконок в соответствующем этому набору формате.

Item – вид инструмента, относящегося к конкретному виду услуг. С помощью данных из Item стек инструментов можно рендерить в виде списка с иконками:

         {% for item in service.item_set.all %} <li><span class='bx bx-chevron-right'></span>{{ item.name }}</li> {% endfor %}     

Другой способ отрендерить список в нужном стиле – сохранить список с HTML-тегами и Bootstrap стилями в базе, и вывести его в шаблоне с помощью тега |safe:

         <h4 class="h4 mb-3">Технологический стек</h4> {{ work.stack|safe }}      

sozdaem portfolio razrabotchika s pomoshhju django b4e98f6 - Создаем портфолио разработчика с помощью django

Так нужно сохранить список в базе

Message сохраняет и показывает (в админке) все полученные сообщения. Чтобы получать сообщения на почту, нужно подключить собственный (сложнее) или сторонний (гораздо проще) SMTP-сервер. Здесь показано, как получать сообщения с помощью SMTP Яндекса.

Отзывы заказчиков сохраняются в таблице Testimony, а данные о владельце портфолио – в Author.

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

Представления и маршруты

Все представления в этом проекте – функциональные. Написание представлений на основе классов мы рассмотрим в одной из последующих статей. Эти представления нужно сохранить в файле portfolio/views.py:

         from django.shortcuts import render, redirect, get_object_or_404 from django.contrib import messages from .models import Author, Category, Work, Service, Testimony, Item, Message  def index(request):     categories = Category.objects.all()     works = Work.objects.all()     services = Service.objects.all()     testimonies = Testimony.objects.all()      context = {        'categories': categories,        'works': works,        'services': services,        'testimonies': testimonies,    }      return render(request, 'index.html', context)  def about(request):     author = Author.objects.get()     return render(request, 'about.html', {'author': author})   def work_detail(request, slug):     work = get_object_or_404(Work, slug=slug)     testimonies = Testimony.objects.all()     context = {         'work': work,         'testimonies': testimonies,     }     return render(request, 'work_detail.html', context)   def contact(request):     if request.method == 'POST':         msg = Message(             name=request.POST['name'],               email=request.POST['email'],             subject=request.POST['subject'],               message=request.POST['message']          )         msg.save()         messages.success(request, 'Сообщение отправлено!')         return redirect('contact')         return render(request, 'contact.html')     

Представление index передает в шаблон index.html все записи, сохраненные в таблицах Work, Category, Service и Testimony, потому что на главной странице выводятся все данные, без сокращений. Если портфолио объемное, имеет смысл ограничить количество работ с помощью среза works = Work.objects.all()[:3], а все работы вывести на отдельной странице с пагинацией. В следующем проекте, посвященном разработке блога, мы разберем процесс создания пагинации.

В таблице Author хранится всего одна запись, поэтому для ее извлечения используется запрос author = Author.objects.get(). В случае создания некой платформы для размещения портфолио, где авторов множество, в эту функцию нужно передавать id или username конкретного владельца.

Представление work_detail выводит информацию о каждом проекте в отдельности, причем для извлечения данных используется не id работы, а слаг:

         work = get_object_or_404(Work, slug=slug)     

Благодаря использованию слага, ссылка выглядит как http://site.com/work/design-studio/, а при использовании id она бы выглядела как http://site.com/work/5/.

Представление contact обеспечивает обработку данных из контактной формы. В проекте используется обычная HTML-форма, которая самостоятельно отслеживает заполнение полей при помощи тега required. В Django есть отличный модуль для работы с формами, который предоставляет всю возможную функциональность для валидации данных (однако оформление формы разработчику все равно придется делать самостоятельно). В одном из последующих проектов мы разберем использование Django-форм и все способы придания им привлекательного внешнего вида.

Чтобы Django мог обработать конкретную форму (в случае, если их на странице несколько), нужно добавить ссылку на нужное представление в form action:

         <form action="{% url 'contact' %}"     

Кроме того, Django обязательно нужен токен внутри формы:

         {% csrf_token %}     

Все представления приводятся в действие маршрутами. Сохраните эти маршруты в portfolio/urls.py:

         from django.urls import path from .views import index, contact, about, work_detail  urlpatterns = [     path('', index, name='index'),     path('about/', about, name='about'),     path('work/<slug:slug>/', work_detail, name='work_detail'),     path('contact/', contact, name='contact'),     

И не забудьте включить маршруты portfolio в config/urls.py:

         urlpatterns = [     path('admin/', admin.site.urls),     path('', include('portfolio.urls')),     

Шаблоны

Для вывода данных на фронтенде портфолио использует несколько шаблонов:

  • base.html – основной шаблон проекта. Здесь определены навигация и футер (поскольку они выглядят одинаково на всех страницах сайта), а также подключены все нужные скрипты на JavaScript, HTML/CSS-стили Bootstrap, шрифт Google, favicon и т. д.
  • index.html – как и все последующие шаблоны, наследует все стили base.html с помощью тега {% extends 'base.html' %}. Выводит данные обо всех проектах, услугах, категориях и отзывах.
  • work_detail.html – показывает подробности реализации каждого проекта.
  • about.html – резюме владельца.
  • contact.html – все контакты разработчика и форма для отправки сообщений.

Подведем итоги

При желании готовое портфолио можно экспортировать в статические HTML/CSS/JS-файлы с помощью django-distill, а для обработки контактной формы подключить сервис вроде Formspree. В таком виде портфолио можно будет разместить на GitHub Pages. В одном из последующих проектов мы рассмотрим процесс преобразования динамического Django-сайта в статический.

***

Содержание курса

  • Часть 1: Django — что это? Обзор и установка фреймворка, структура проекта
  • Проект 1: Веб-приложение на основе XLSX вместо базы данных
  • Часть 2: ORM и основы работы с базами данных
  • Проект 2: Портфолио разработчика

  • 2 views
  • 0 Comment

Leave a Reply

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

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

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