Python – популярный язык программирования общего назначения. Он позволяет создавать контент разного направления. Используется и для веб-разработки. Активно применяется при написании собственных веб-страничек.
В данной статье будет рассказано о том, как написать элементарный сайт на Python. Это небольшой туториал, помогающий новичкам освоиться в выбранном направлении. Также предстоит узнать, какие популярные проекты уже были написаны на Питоне. Соответствующие данные помогут понять, насколько на самом деле язык программирования является востребованным и перспективным в 21 веке.
Питон и веб
В Google полно информации о том, как можно сделать собственный сайт. И не только на Питоне, а совершенно на любом языке. Соответствующие сведения позволяют с нуля писать как элементарные, так и весьма сложные странички.
При использовании Python в web development, нужно учитывать следующие особенности:
- инструменты применяются преимущественно для бэкенда и маршрутизации;
- в качестве конкурентов Питона выделяют Ruby и PHP;
- для того, чтобы сделать сайт или веб-утилиту на выбранном ЯП, предстоит выучить CSS и HTML.
Функциональную часть фронтенда можно создать, согласно данным из Google, на JavaScript. Но можно через специальные средства заняться фулл-стек разработкой на Python.
Full Stack Development на Питоне
Для того, чтобы полноценно использовать Питон при написании собственной веб-странички, придется изучить некоторые фреймворки. Они носят название Full Stack Frameworks. Самым распространенным вариантом является Django. С ним всего за 5 минут удастся создать элементарный сайт.
Джанго выделяется:
- простотой изучения;
- наличием шаблонов для специальных HTML-документов;
- возможностью вставки получившегося кода в Python для взаимодействия с информацией из backend.
Фулл-стек позволяет работать с HTTP-запросами, хранилищами БД, а также готовыми шаблонами веб-страниц, запросами маршрутизации. На помощь иногда приходят микрофреймворки, но они применяются более опытными разработчиками. Обладают меньшей гибкостью, из-за чего программный код в конечном итоге усложняется.
Ключевые фреймворки
Если делает website, нужно тщательно составлять запросы для Google. С их помощью удастся найти ответ на любой вопрос, связанный с разработкой программного обеспечения. Но в Google и других поисковых системах легко запутаться. Они редко выдают на первых страницах поэтапные уроки для новичков. Поэтому инструкции, приведенные ниже, подойдут «чайникам» и еще не слишком уверенным в себе пользователям.
Создание новой страницы в интернете на Python лучше проводить при помощи фреймворков. В Google наиболее распространенными «библиотеками» для рассматриваемого направления выступают следующие варианты:
- Django. Самый распространенный фреймворк для веб-разработки. Google указывает на то, что он предусматривает множество встроенных модулей, которые прекрасно совмещаются друг с другом. Сначала нужно вникнуть в алгоритмы создания веб-софта и внутренние структуры Джанго. После этого сделать собственный контент «для интернета» не составит никакого труда. Django отлично масштабируется. Google указывает на то, что поддержка ПО, написанного с этим фреймворком, не отнимет много времени и сил.
- Flask. Второй framework, который поможет при написании веб-страничек. Это, если верить Google, противоположность Django. Понятен новичкам. При разработке предоставляет лишь «базовый функционал». Крупные и оригинальные проекты на Flask сделать никак не получится.
- Pyramid. Что-то среднее между предыдущими двумя фреймворками. Он не такой функциональный, как Джанго, но и не «упрям», как Flask. Google ссылается на то, что Pyramid можно задействовать для большинства веб-софта.
Окончательный выбор фреймворка зависит от того, какой результат хотим получить на выходе. Далее создаем страничку на Python при помощи Django. Это – самое быстрое и рациональное решение.
Написание веб-страницы
Теперь создаем страницу на Python при помощи Django. Такое решение подойдет тем, кто уже знаком в общих чертах с выбранным языком программирования. Он не потребует особых навыков и знаний.
Для того, чтобы сделать веб-проект, предстоит использовать виртуальную машину и Убунту Сервер 18.04. А еще нужно обеспечить на устройстве веб-сервер под названием Apache.
Инициализация компонентов
Делаем всю процедуру поэтапно. Сначала нужно установить необходимые компоненты:
- Инициализировать пакетный менеджер под названием pip.
- Подключить пакет виртуального окружения.
- Перейти в домашнюю директорию. Там делаем виртуальное окружение. Оно будет находиться в ~/venv/.
- Установить Apache. Этот шаг пропускается, если соответствующее ПО уже стоит на задействованном устройстве.
- Активировать виртуальное окружение при помощи source ~/venv/bin/activate.
- Установить на устройство Джанго. Сделать это нужно в Virtual Environment.
Далее предстоит создать проект с сайтом. Для этого лучше сделать отдельную папку. Перейдя туда, остается обеспечить наличие Джанго-проекта. Сделать это помогает команда Django-admin startproject MySite.
Работа в проекте
Теперь создаем основной функционал. Для этого потребуется:
- Перейти в полученный проект.
- Добавить приложение, которое будет называться app. Оно предусматривает основную логику сайта.
- Разрешить все адреса для хостов.
- Запустить получившийся проект. В папке с ним должен появиться управляющий файл manage.py.
- Запустить команду отладочного сервера: python3 manage.py runserver. Сервер заработает. Сайт – тоже. Он обнаружен по адресу 127.0.0.1 на порте 8000.
- В файле models нужно указать классы моделей, которые будут сущностями в базе данных. В Views – прописать концепции MVC в Джанго.
- Создать каталог, в котором хранятся html-странички. В папке проекта нужно сделать папку templates.
- Сделать в каталоге с шаблонами файл index.html.
- Отредактировать файл контроллера. Приведенный пример передает данные на сайт Python. Пусть созданная функция отображает на страничке «Hello, World!».
- Задать адресацию. Для этого нужно перейти в urls и написать желаемый маршрут, по которому отображается страничка.
- Скопировать файл urls в директорию с получившимся приложением.
Google говорит о том, что теперь остается запустить сайт через сервер Apache. Здесь можно посмотреть итоговый исходный код. А тут без помощи Google удастся обнаружить краткий видео обзор относительно программирования страничек на Python.
Проще всего создать динамические страницы на Python при помощи CGI-скриптов. CGI-скрипты — это исполняемые файлы, которые выполняются веб-сервером, когда в URL запрашивается соответствующий скрипт.
Сегодня я расскажу про то, как написать Hello world, как CGI-скрипт.
Настройка локального сервера
В Python уже есть встроенный CGI сервер, поэтому его настройка элементарна.
Для запуска из консоли (для любителей linux-систем). Запускать нужно из той папки, где мы хотим работать:
python3 -m http.server --cgi
Для сидящих на Windows чуть проще будет запуск Python файла (заметьте, что он должен находиться в той же папке, в которой мы планируем работать!):
from http.server import HTTPServer, CGIHTTPRequestHandler server_address = ("", 8000) httpd = HTTPServer(server_address, CGIHTTPRequestHandler) httpd.serve_forever()
Теперь откройте браузер и в адресной строке наберите localhost:8000
Если у вас примерно такая же картина, значит, у вас все заработало!
Теперь в той папке, где мы запустили сервер, создаём папку cgi-bin (у меня она уже создана).
В этой папке создаём скрипт hello.py со следующим содержимым:
#!/usr/bin/env python3 print("Content-type: text/html") print() print("<h1>Hello world!</h1>")
Первая строка говорит о том, что это Python скрипт (CGI-скрипты можно не только на Python писать).
Вторая строка печатает заголовок. Он обозначает, что это будет html файл (бывает ещё css, javascript, pdf и куча других, и браузер различает их по заголовкам).
Третья строка (просто символ новой строки) отделяет заголовки от тела ответа.
Четвёртая печатает Hello world.
Теперь переходим на localhost:8000/cgi-bin/hello.py
И радуемся!
Если у вас не работает, проверьте, установлены ли права на выполнение.
Также в консоли запущенного сервера появляются сообщения об ошибках. Например, убрал скобочку и обновил страницу:
В следующей части мы рассмотрим обработку данных форм и cookies.
Для вставки кода на Python в комментарий заключайте его в теги <pre><code class=»python3″>Ваш код</code></pre>
Я решила создать собственный сайт, который позволял бы вести блог, отображать информационные панели и запускать блокноты Jupyter.
Разобралась, как создать само приложение Dash. Однако мне не удалось найти способ, который описывал бы все 3 нужные функциональности. И в данной статье мы займемся его разработкой.
С кодом шаблона, лежащего в основе сайта, можно ознакомиться по ссылке.
Введение
Изначально сайт был разработан в Dash. Он представлял собой информационную панель, как показано ниже:
Информационные панели создавались с помощью Dash и Plotly.
Но тут выяснилось, что я не могу отображать посты блога в разметке Markdown. Вот почему мне пришлось искать другой способ создания сайта.
Я начала изучать информацию в интернете. Мне нужно было найти подход для разработки такого сайта, который бы отображал разметку Markdown и использовал преимущества Dash для создания информационных панелей. Однако поиски не увенчались успехом.
Зато я натолкнулась на описание практического опыта разработки Джеймса Хардинга. Он состоял в создании простого статического блога на основе Markdown с помощью Flask. Я воспользовалась им для настройки основного сайта и с помощью пары приемов согласовала его работу с информационной панелью.
Структура каталога
Основная структура выглядит следующим образом:
.
|-- virtualenv/
|-- main/
| |-- content
| | |-- posts
| | | `-- about_website.md
| |-- dash
| |-- data
| |-- static
| |-- templates
| |-- __init__.py
|-- app.py
|-- Dockerfile
|-- .pylintrc
`-- requirements.txt
В __init__.py
происходит настройка сервера Flask, а также регистрация Flatpages и компонентов Dash.
Сайт разделен на статические файлы и файлы HTML. Выводимые на сайте изображения или файлы CSS и JavaScript располагаются в папке static
, а файлы HTML — в папке templates
.
Регистрация приложения Flask
Приложение вызывается из файла app.py
. Сам он вызывает функцию create_app()
, находящуюся в файле __init__.py
.
def create_app():
app = Flask(__name__, static_url_path='/static')
app.config.from_object(__name__)
app.config['FLATPAGES_HTML_RENDERER'] = my_renderer
register_dashapps(app)
register_routes(app)
return app
Эта функция включает настройки сервера и указание места, в котором статические файлы наделяют сайт уникальными характеристиками.
Примечание. Если не добавить static_url_path
в качестве параметра, сервер Flask не сможет определить, где искать файлы CSS и JavaScript. Столкнувшись с ошибкой 404 при вызове данных файлов, знайте, что проблема может быть именно в этом.
После регистрации сервера Flask добавляем компоненты Dash и страницы разметки Markdown Flatpages.
Добавление информационной панели
Файл __init__.py
включает функцию register_dashapps
, которая представлена ниже:
def register_dashapps(app):
from .main.layout import html_layout
# Метатеги для отзывчивости viewport
meta_viewport = {"name": "viewport",
"content": "width=device-width, initial-scale=1, shrink-to-fit=no"}dash_app = dash.Dash(
server=app,
routes_pathname_prefix="/projects/dashapp/",
external_stylesheets=[
"https://fonts.googleapis.com/css?family=Lato",
],
)with app.app_context():
dash_app.index_string = html_layout
dash_app.layout = init_dashboard()
Главное отличие между обычным Dash и данной функцией заключается в дополнительном контексте Flask. Теперь информационная панель запускается через app_context()
Flask.
Добавление блогов
Большинство блогов придерживаются общепринятого подхода и хранят контент в реляционной базе данных.
Простые и “плоские” посты моего блога взяты из файлов в исходном коде. Flatpages отлично подходит для данного случая использования и быстро добавляет программу визуализации в конфигурацию приложения Flask, которая преобразует или переводит Markdown в HTML.
FLATPAGES_EXTENSION = '.md'
FLATPAGES_ROOT = 'content'
POST_DIR = 'posts'def my_renderer(text):
body = render_template_string(markdown2.markdown(
text, extras=['fenced-code-blocks']))
return pygmented_markdown(body)def create_app():
app = Flask(__name__, static_url_path='/static')
app.config.from_object(__name__)
app.config['FLATPAGES_HTML_RENDERER'] = my_renderer
return app
Кроме того, нам нужно зарегистрировать маршруты сайта, указывающие на посты.
def register_routes(app):
pages = FlatPages(app)
freezer = Freezer(app)
Добавление блокнотов Jupyter
Заключительный этап предусматривает добавление блокнотов Jupyter.
Прежде чем добавить переадресацию в файл __init__.py
, убедимся в наличии доступа к блокноту Jupyter с сайта. Я задействовала инструмент nbviewer
, позволяющий бесплатно разместить этот блокнот. Затем данный URL можно использовать в переадресации (<URL>), как показано ниже:
@app.route('/<title_for_redirect>')
def project_jupyter_notebook():
return redirect('https://mybinder.org/<your_binder_url>')
Теперь вы знаете, как объединить вместе Flask, Dash и Jupyter Notebook и создать прекрасный сайт.
Читайте также:
- Бэкенд-разработчик: какие знания нужны для трудоустройства
- Управляем интернетом с помощью Python
- Овладей Python, создавая реальные приложения. Часть 6
Читайте нас в Telegram, VK и Яндекс.Дзен
Перевод статьи Sarah Floris: Create an Analytical Website From Scratch Using Python
На чтение 10 мин Просмотров 17.5к. Опубликовано 18.11.2021
Flask — это фреймворк для веб-разработки. В Python есть два модуля, которые можно использовать для веб-разработки: Django и Flask. Однако Flask более легкий и легкий в освоении. В этом руководстве мы создадим очень простой веб-сайт, используя модуль Python Flask.
Для начала устанавливаем колбу:
Содержание
- Шаг 1: минимальное веб-приложение
- Шаг 2: Добавление HTML
- Шаг 3: Добавление CSS
- Шаг 4: добавление изображения
- Шаг № 5: Добавление JavaScript
Шаг 1: минимальное веб-приложение
Минимальное приложение можно найти по адресу https://flask.palletsprojects.com/en/2.0.x/quickstart/#a-minimal-application. Это веб-страница, на которой отображается «Hello World». Первым делом мы создали экземпляр Flask () с аргументом «__name__». Декоратор маршрута используется для того, чтобы сообщить Flask URL-адрес, который активирует написанную нами функцию.
from flask import Flask
app = Flask(__name__)
@app.route(‘/’)
def index():
return «Hello World»if «__name__» == «__main__»:
app.run(debug=True)
Затем в терминале PyCharm введите следующее (где имя моего файла Python — main.py; в вашем случае замените main.py именем вашего файла Python):
set FLASK_APP=main.py
$env:FLASK_APP = «main.py»
flask run
Как только вы запустите «flask run», терминал выдаст URL-адрес с портом. Этот URL: ПОРТ — это место, где загружается веб-страница. Вы всегда можете нажать Control + c, чтобы выйти. В моем случае написано: «Запуск на http://127.0.0.1:5000/ (нажмите CTRL + C, чтобы выйти)». Итак, откройте свой веб-браузер, скопируйте и вставьте указанный URL. В моем случае я скопировал и вставил «http://127.0.0.1:5000/». Также обратите внимание, что предыдущие строки должны запускаться каждый раз, когда вы перезапускаете PyCharm, чтобы он работал:
Шаг 2: Добавление HTML
Первое, что вам нужно сделать, это открыть папку, в которой находится скрипт Python, и создать папку под названием «шаблоны». Когда я впервые запустил это, я попытался указать имя «шаблон» в качестве имени папки, и вся программа вылетела и не работала. Поэтому обязательно назовите папку « Шаблоны ». В этой папке «шаблонов» создайте файл index.html с вашим HTML-кодом. Затем используйте render_template () и передайте index.html в качестве аргумента. Теперь, если вы запустите «flask run» в терминале, ваш HTML-код должен отобразиться:
Мой html-код (index.html) на данный момент выглядит следующим образом:
<!DOCTYPE html>
<html lang=«en»>
<head>
<meta charset=«UTF-8»>
<title>Kalyani‘s Resume</title>
</head>
<body>
<h1>
Kalyani’s Resume
This page will contain my resume
</h1>
</body>
</html>
И мой код файла Python (main.py) выглядит следующим образом:
from flask import Flask, render_template
app = Flask(__name__)
@app.route(‘/’)
def index():
return render_template(«index.html»)if «__name__» == «__main__»:
app.run(debug=True)
Последний будет отображать простую HTML-страницу.
Шаг 3: Добавление CSS
Теперь я хочу добавить CSS в свой HTML. Для этого создайте папку с именем «static» и создайте файл с именем «main.css». Здесь имя фактического файла CSS может быть любым. Я решил назвать свой «main.css». Однако имя папки должно быть «статическим»! Фактически, в «статической» папке можно разместить все, что является статическим, например CSS, JavaScript и изображения. Итак, если вы собираетесь размещать изображения, JavaScript и CSS, вы можете создать подпапки.
Сначала напишем нужный мне CSS (main.css):
body {
margin:0;
color: #333
font-family: verdana;
font-size: 20px;
background-color: rgb(201, 76, 76);
}
.styled {
background-color: #92a8d1;
font-family: verdana;
font-size: 20px;
}
Здесь, в index.html, нам нужно написать & lt; link rel = «stylesheet» type = «text / css» href = «{{url_for (‘static’, filename = ‘main.css’)}}» > в заголовке HTML-файла. Здесь имя файла — это имя файла CSS (у меня main.css). Если, например, «main.css» находится с подпапкой «css», вы должны написать следующее:
<link rel=«stylesheet» type=«text/css» href=«{{ url_for(‘static’, filename=’css/main.css’)}}»>.
После этого вы можете использовать созданный вами CSS. Например, я создал один под названием «стилизованный» и использовал его в классе h1.
Мой файл index.html будет следующим:
<!DOCTYPE html>
<html lang=«en»>
<head>
<meta charset=«UTF-8»>
<title>Kalyani‘s Resume</title>
<link rel=»stylesheet» type=»text/css» href=»{{ url_for(‘static‘, filename=’main.css‘)}}»>
</head>
<body><h1 class=»styled»>
Kalyani’s Resume
This page will contain my resume
</h1>
</body>
</html>
Главный файл Python — main.py — остается прежним.
from flask import Flask, render_template
app = Flask(__name__)
@app.route(‘/’)
def index():
return render_template(«index.html»)if «__name__» == «__main__»:
app.run(debug=True)
Шаг 4: добавление изображения
Теперь давайте добавим изображение на созданную HTML-страницу! Для этого мы используем созданную нами «статическую» папку. Внутри «статической» папки я создал другую папку под названием «изображения». В папке изображений я поместил изображение. Теперь давайте добавим изображение в HTML-код следующим образом: <img src = ”/ static / images / kalyani.jpg” height = ”200 ″ />. В этом случае я установил высоту изображения на 200, но вы можете изменить ее на все, что захотите, и добавить CSS, если хотите.
HTML-код будет выглядеть следующим образом:
<!DOCTYPE html>
<html lang=«en»>
<head>
<meta charset=«UTF-8»>
<title>Kalyani‘s Resume</title>
<link rel=»stylesheet» type=»text/css» href=»{{ url_for(‘static‘, filename=’main.css‘)}}»>
</head>
<body>
<img src=»/static/images/kalyani.jpg» height=»200″ />
<h1 class=»styled»>
Kalyani’s Resume
</h1>
This page will contain my resume
</body>
</html>
В качестве альтернативы можно также использовать следующее:
<img src=«{{ url_for(‘static’, filename=’images/kalyani.jpg’)}}» height=«200» />.
В этом случае HTML-код будет выглядеть так:
<!DOCTYPE html>
<html lang=«en»>
<head>
<meta charset=«UTF-8»>
<title>Kalyani‘s Resume</title>
<link rel=»stylesheet» type=»text/css» href=»{{ url_for(‘static‘, filename=’main.css‘)}}»>
</head>
<body>
<img src=»{{ url_for(‘static‘, filename=’images/kalyani.jpg‘)}}» height=»200″ />
<h1 class=»styled»>
Kalyani’s Resume
</h1>
This page will contain my resume
</body>
</html>
Шаг № 5: Добавление JavaScript
Есть два способа добавить JavaScript. В этой первой демонстрации я создам кнопку. Когда кнопка нажата, она активирует функцию myFunction (), которая будет JavaScript (находится в теге <script>). Для этого настройте кнопку. Затем установите тег скрипта в заголовке HTML-кода и определите в нем функцию. В моем случае я определил функцию, которая будет добавлять «все резюме» к элементу ap при нажатии кнопки.
Вы можете добавить его в файл index.html следующим образом:
<!DOCTYPE html>
<html lang=«en»>
<head>
<meta charset=«UTF-8»>
<title>Kalyani‘s Resume</title>
<link rel=»stylesheet» type=»text/css» href=»{{ url_for(‘static‘, filename=’main.css‘)}}»>function myFunction() {
document.getElementById(«para»).innerHTML = «WHOLE RESUME»;
}
</script>
</head>
<body>
<img src=»/static/images/kalyani.jpg» height=»200″ />
<h1 class=»styled»>
Kalyani’s Resume
</h1>
This page will contain my resume
<br>
<br>
<p id=«para»> </p>
<<button id=«button» type=«button» onclick=«myFunction()»> Click to see Resume </button>
</body>
</html>
Однако в большинстве случаев файлы JavaScript, как правило, сами по себе являются документами, а не однострочниками. В таких случаях у нас будет файл.js, который нужно связать. В моем случае я бы написал: <script src = ”/ static / javascript / javascript.js”> </script>. Итак, как и в случае с файлом изображения, мы связываем файл js следующим образом:
<!DOCTYPE html>
<html lang=«en»>
<head>
<meta charset=«UTF-8»>
<title>Kalyani‘s Resume</title>
<link rel=»stylesheet» type=»text/css» href=»{{ url_for(‘static‘, filename=’main.css‘)}}»>
<script src=»/static/javascript/javascript.js»>
</script>
</head>
<body>
<img src=»/static/images/kalyani.jpg» height=»200″ />
<h1 class=»styled»>
Kalyani’s Resume
</h1>
This page will contain my resume
<br>
<br>
<p id=«para»> </p>
<button id=«button» type=«button» onclick=«myFunction()»> Click to see Resume </button>
</body>
</html>
В качестве альтернативы вы также можете использовать это: <script src = ”{{url_for (‘static’, filename = ‘javascript / javascript.js’)}}”> </script>. Последний сгенерирует этот HTML-код:
<!DOCTYPE html>
<html lang=«en»>
<head>
<meta charset=«UTF-8»>
<title>Kalyani‘s Resume</title>
<link rel=»stylesheet» type=»text/css» href=»{{ url_for(‘static‘, filename=’main.css‘)}}»><script src=»{{ url_for(‘static‘, filename=’javascript/javascript.js‘)}}»>
</script>
</head>
<body>
<img src=»{{ url_for(‘static‘, filename=’images/kalyani.jpg‘)}}» height=»200″ /><h1 class=»styled»>
Kalyani’s Resume
</h1>
This page will contain my resume
<br>
<br>
<p id=«para»> </p>
<button id=«button» type=«button» onclick=«myFunction()»> Click to see Resume </button>
</body>
</html>
Заключение
Flask — это микро-фреймворк, который удобен в использовании и отлично подходит для начинающих. В частности, сама документация великолепна, и ее можно найти по адресу https://flask.palletsprojects.com/en/2.0.x/quickstart/#static-files. В этом руководстве мы узнали, как создать простой веб-сайт, добавить CSS, добавить изображения и добавить JavaScript на веб-сайт с помощью модуля Python Flask. Мы надеемся, что эта статья оказалась для вас полезной, и, пожалуйста, ознакомьтесь с Linux Hint для получения более информативных статей.
Статические (а точнее – пререндеренные) сайты переживают второе рождение, и неудивительно: они мгновенно загружаются, выдерживают любой трафик, им не нужен дорогой хостинг, они не используют базы данных и потому их практически невозможно взломать. С помощью генератора можно быстро сделать сайт-визитку, резюме или портфолио на основе любого готового HTML/CSS/JS-шаблона.
Самые популярные генераторы статических сайтов (SSG) написаны на Ruby (Jekyll) и Go (Hugo), но есть и несколько интересных решений на Python: Pelican, Lektor, Nikola и Hyde. Pelican – наиболее простой и в то же время мощный Python-генератор: с его помощью можно создать собственный сайт или блог в считаные минуты.
Pelican работает по тому же принципу, что и другие генераторы:
- Пользователь создает контент в виде ReST или Markdown файлов. Каждый файл состоит из невидимого блока YAML (метаданных) и видимого на странице текста. Файлы сохраняются в папке content, при этом посты блога располагаются в поддиректории articles, а страницы – в pages. Картинки для постов и страниц хранятся в общей папке images.
- Движок обрабатывает файлы в соответствии с выбранным шаблоном. Шаблон устанавливается в конфигурационном файле проекта pelicanconf. Как и другие веб-фреймворки на основе Python, Pelican использует шаблонизатор Jinja2. Язык Jinja2 прост, понятен, и очень похож на Python (на котором и написан сам шаблонизатор).
Преимущества и недостатки Pelican
Пеликан разделяет все плюсы и минусы других SSG. Среди плюсов:
- Простота редактирования и обновления контента.
- Мгновенная загрузка готовых страниц и безопасность сайта.
- Молниеносная смена дизайна.
- Простота создания новых тем – если вы знакомы с Jinja2, то легко сможете адаптировать готовый HTML/CSS/JS-шаблон для работы с Pelican.
- Возможность использовать бесплатный хостинг – сайт можно разместить на GitHub Pages и даже в Dropbox.
- Предельно простая процедура переноса сайта с одного хостинга на другой.
- Открытый исходный код.
- Неплохой набор готовых плагинов (по сравнению с другими SGG на Python).
Есть и минусы:
- Pelican работает медленнее Hugo. Например, генерация блога, состоящего из сотни страниц, займет не менее 10 секунд.
- Нет панели администрирования – все команды вводятся в CMD.
- Выбор тем и плагинов, по сравнению с популярными динамическими CMS (WordPress), ограничен.
- Нет WYSIWYG-редактора – для создания постов придется освоить Markdown, а для адаптации готовых шаблонов под работу с Пеликаном нужно понимание языка Jinja2 и базовые познания в HTML и CSS.
- Для подключения комментариев, форм и поиска нужны дополнительные манипуляции. Ниже мы рассмотрим, как подключить к Pelican-сайту поиск, комментарии и контактную форму.
Установка, настройка и запуск Pelican
У большинства генераторов статических сайтов, за исключением Lektor, нет админ-панели: управлять контентом приходится через CLI. Pelican тоже управляется из командной строки, но, в отличие от других генераторов, его команды максимально просты. Для запуска Пеликана необходимо наличие в системе Python 3.6+.
Как и любой более-менее серьезный Python-проект, Pelican целесообразно устанавливать в виртуальное окружение. Сначала создадим директорию для нового проекта, а затем воспользуемся менеджером зависимостей pipenv
:
mkdir e:myblog
cd e:myblog
mkdir .venv
pipenv install pelican[Markdown]
Процесс установки займет около минуты. После завершения установки активируем виртуальное окружение:
pipenv shell
Пока виртуальное окружение активно, перед именем директории проекта отображается (.venv)
. Запустим команду для создания файла конфигурации Пеликана, pelicanconf.py:
pelican-quickstart
На экране один за другим будут появляться вопросы о базовых настройках сайта. Отвечать на них можно как угодно – потом настройки можно будет поправить вручную в pelicanconf.py.
После того как мастер настройки Pelican получит ответы на все вопросы, можно приступать к созданию содержимого сайта. Пеликан автоматически создает две папки – content и output. В первой папке пользователь сохраняет посты, страницы и изображения, во вторую генератор выгружает готовые html-страницы. Посты нужно сохранять в поддиректории articles, страницы – в pages, изображения – в images. Поддиректории придется создать вручную.
Для генерации сайта нужно положить в папку contentarticles хотя бы один Markdown файл. Например, такой:
Title: Это мой новый блог на Пеликане
Date: 2022-03-15 10:20
Category: Новости
Slug: first-post
Pelican – быстрый и простой в использовании генератор статических сайтов с CLI. В стандартный дистрибутив входят две темы оформления. Эта тема называется simple.
После создания первого поста можно запускать генератор:
pelican content
Запустить сервер можно тремя способами:
pelican --listen
– стандартный;pelican -l
– сокращенный;pelican -r -l
– с автоматической регенерацией контента (используется в режиме разработки – для кастомизации темы, тестирования плагинов и так далее). Команду запуска можно комбинировать с командой генерации контента:pelican content -l
.
Сайт будет доступен в браузере по адресу http://localhost:8000/.
Остановить сервер можно комбинацией Ctrl + C
, а выйти из виртуального окружения – командой exit
.
Темы оформления для Pelican
Хотя по количеству тем Пеликан пока что уступает Hugo, у пользователей все-таки есть неплохой выбор: подходящую тему можно подыскать на сайте Pelican Themes или в репозитории на Гитхабе. Изменить оформление сайта очень просто: архив нужно распаковать в поддиректорию .venvLibsite-packagespelicanthemes, а в конфигурационном файле указать название темы:
THEME = 'flex'
После этого нужно сгенерировать сайт в соответствии с новой темой – pelican content -r -l
, и можно любоваться новым дизайном.
По сути, изменить оформление Pelican-сайта так же просто, как сменить тему динамической CMS наподобие WordPress.
Если в каталоге готовых тем не нашлось шаблона по вкусу, его несложно сделать самостоятельно. В этом блоге есть подробный урок по созданию темы для Pelican-сайта на основе готового бесплатного HTML/CSS-шаблона.
Поиск, комментарии и формы
Главный недостаток статических сайтов в сравнении с динамическими CMS – отсутствие встроенного поиска, комментариев и форм для общения с посетителями. Возможность компенсировать эти недостатки существует.
Поиск
Решить проблему с поиском на Pelican-сайте можно двумя способами:
- Установить плагин pelican-search – он создает индексный файл, в котором хранится все текстовое содержимое сайта. Недостатков у этого способа два – чем больше на сайте статей, тем быстрее будет увеличиваться размер файла. Кроме того, плагин пока что адекватно работает только с английским языком.
- Подключить пользовательский поиск от Яндекс или Google. Как показывает практика, Яндекс со статическими сайтами работает адекватнее – перенаправляет на нужный пост, в то время как Гугл упорно открывает главную страницу сайта, на которой впервые зафиксировал искомую фразу (несмотря на то, что пост уже давно перекочевал на одну из предыдущих страниц).
Формы для опросов и обратной связи
Для опроса посетителей можно подключить Google-формы. Для обработки формы обратной связи удобнее использовать сервисы:
- Formspree
- 99Inbound
- KwesForms
Подобных платформ много, набор услуг у них примерно одинаков:
- можно подключить код к собственной форме или использовать форму, созданную в конструкторе сервиса;
- почти везде есть спам-фильтр;
- предусмотрена переадресация после отправки данных.
На бесплатных тарифах, как правило, количество обработок ограничено, но в большинстве случаев для частного блога этого лимита будет вполне достаточно.
Комментарии
Самый простой способ подключить комментарии к статическому блогу – использовать Disqus. Этот способ также можно назвать самым нежелательным: сервис загружает массу трекеров и использует личные данные пользователей.
Другие решения:
- Discourse – поддерживает и комментарии, и целые форумы. Можно использовать бесплатно, если разместить на своем хостинге.
- StaticMan – хранит комментарии в GitHub-репозитории владельца сайта.
- Utterances – использует систему комментариев GitHub Issues.
- Giscus – система комментирования на основе GitHub Discussions. Документация русифицирована.
Заключение
Долгое время пользователям приходилось выбирать динамические CMS с базами данных только потому, что перспектива редактирования нескольких десятков страниц статического сайта приводила их в ужас. Добавился или изменился один пункт в меню, которое отображается на всех страницах? Надо редактировать все страницы. А уж если нужно изменить дизайн…
Генератор статических сайтов снимает проблемы редактирования и смены дизайна: эти операции Pelican выполняет так же быстро, как динамическая CMS. Гибкость и простота Pelican позволяют использовать его с любыми шаблонами. Нашли свежую Bootstrap-тему с трендовыми анимационными эффектами? Pelican наполнит броский шаблон контентом и превратит его в быстрый, функциональный, масштабируемый сайт, которому подойдет самый простой хостинг.
***
Материалы по теме
- 🐍 Регулярные выражения в Python за 5 минут: теория и практика для новичков и не только
- 🐍 Конкурентность и параллелизм в Python: в чем разница?
- 🐍📈 Как «оживлять» графики и впечатлять всех красивыми анимациями с помощью Python
Статья будет полезна тем, кто хотя-бы минимально разбирается в Python. Наверняка каждый пользователь интернета знает, что такое браузерные MMO(RPG) игры. В наше время они встречаются очень часто. Причем они бывают самыми разными – как простейшими текстовыми играми, так и агрегатами на HTML5 или Flash. К тому же, вы можете использовать в своей игре несколько разных технологий одновременно.
В рамках данной статьи мы разберем cоздание сайта на языке программирования Python. Естественно, есть масса конструкторов, позволяющих всего за несколько минут создавать подобные проекты, но собственная разработка наверняка будет полезным опытом для каждого.
Установка
Предполагается, что у вас уже есть установленный Python. В противном случае, его можно загрузить с официального сайта и инсталлировать на ваш сервер или компьютер.
В этом примере мы будем пользоваться Web.Python 0.37, но, если хотите вы можете воспользоваться и последней версией.
Необходимо распаковать и скопировать папку web в директорию, где находится ваше приложение, либо просто выполнить следующую команду:
python setup.py install
В некоторых UNIX-подобных системах эту команду нужно выполнить с правами администратора:
sudo python setup.py install
Есть и другой способ установки – через EasyInstall, выполнив команду:
sudo easy_install web.py
Основные моменты
Теперь нужно создать текстовый файл под названием code.py. Открываем его и пишем в нем такой код:
import web
Это нужно для загрузки модуля Web.Py, для которого мы и делали все описанные выше операции.
Далее нужно объяснить серверу, какая у нас URL-структура. Ниже пишем:
urls = (
'/', 'index'
)
Теперь, если войти в корень нашего сайта, загрузится страничка index. Но, пока у нас еще ничего не готово, это только начало.
Страницы сайта, запросы GETPOST
Большинство из вас уже прекрасно понимают, чем отличаются запросы GET и POST. GET передается в адресную строку, POST – в тело скрипта.
Надежный сервис doctorsmm.com готов предложить Вам выгодные цены на покупку подписчиков в Инстаграме. Здесь, при заказе, Вы сможете выбрать любое качество добавляемых аккаунтов, а также скорость их поступления на профиль. К тому же на сайте действует таргетинг аудитории по географическим критериям. Торопитесь, пока предложение еще актуально!
Отметим еще один момент – передавать вручную POST-запросы без скриптов и форм – это тоже, что тягать кота за хвост, чтобы согнать его с дивана, вместо того, чтобы просто взять и переместить его куда надо.
На данном этапе необходимо создать класс index, который будет предусматривать главную страницу нашего сайта, или игры, смотря какой проект вы реализуете.
class index:
def GET(self):
return "Hello, world!"
Теперь, если зайти на сайт, отобразится текст Hello, world! Все как обычно.
Далее нужно сделать так, чтобы наше приложение выводило нам HTML-код сайта. Чтобы это сделать дописываем следующий код:
if __name__ == "__main__":
app = web.application(urls, globals())
app.run()
В результате у нас получается такой вот код:
import web
urls = (
'/', 'index'
)
class index:
def GET(self):
return "Hello, world!"
if __name__ == "__main__":
app = web.application(urls, globals())
app.run()
Это скриптовая часть простейшего сайта, она уже готова, остался лишь запуск.
Запускаем сервер
Нужно войти в командную строку вашего сервера (либо SSH-терминала), где выполнить команду:
$ python code.py
http://0.0.0.0:8080/
http://0.0.0.0:8080/ — адрес с портом нашего сайта. Его можно заменить на домен, если вы его уже прикрепили, локальный или внешний IP-адрес. Оттуда, собственно, мы и будем заходить на сайт. На этом первый этап создания сайта можно считать законченным. Далее нужно будет работать с шаблонизатором, базой данный и формами, но это уже темы для других статей.
В этом проекте по поиску вакансий соискатели, нуждающиеся в работе, могут связаться с компаниями. Это отличная платформа как для соискателей, так и для всех компаний.
О системе портала размещения вакансий:
На этом портале по поиску работы могут зарегистрироваться как соискатели, так и компании. И тем, и другим предоставляются различные роли. Соискатель видит список доступных вакансий и может откликнуться на любую, которая соответствует его/ее квалификации. Аналогичным образом, компании могут добавлять новые вакансии и отбирать кандидатов, подавших заявку на эту работу, просматривая их резюме.
Сайт по поиску работы на Django :
Основная цель этого проекта — создать возможности трудоустройства для соискателей. Это отличная возможность для соискателей получить шанс найти работату в различных компаниях.
Предварительные условия проекта
Вы должны быть хорошо знакомы со следующим:
- Python
- Html, CSS
- Bootstrap
Скачать исходный код портала по поиску работы на Python Django
Скачать
Структура файлов проекта
Сначала рассмотрим шаги по созданию системы портала по поиску вакансий в Python Django Framework:
- Во-первых, используйте команду django-admin startproject для создания проекта.
- Затем используйте команду django-admin start-app для создания приложения внутри проекта.
- Храните все html-шаблоны в одной папке.
- Выполните команду python manage.py migrate, чтобы применить все встроенные в Django миграции.
- Создайте суперпользователя с именем пользователя, электронной почтой и паролем.
- Наконец, начните создавать урлы для проекта.
Urls.py
from django.urls import path from . import views urlpatterns = [ path("", views.index, name="index"), # for users or applicants path("user_login/", views.user_login, name="user_login"), path("signup/", views.signup, name="signup"), path("user_homepage/", views.user_homepage, name="user_homepage"), path("logout/", views.Logout, name="logout"), path("all_jobs/", views.all_jobs, name="all_jobs"), path("job_detail/<int:myid>/", views.job_detail, name="job_detail"), path("job_apply/<int:myid>/", views.job_apply, name="job_apply"), # for Company path("company_signup/", views.company_signup, name="company_signup"), path("company_login/", views.company_login, name="company_login"), path("company_homepage/", views.company_homepage, name="company_homepage"), path("add_job/", views.add_job, name="add_job"), path("job_list/", views.job_list, name="job_list"), path("edit_job/<int:myid>/", views.edit_job, name="edit_job"), path("company_logo/<int:myid>/", views.company_logo, name="company_logo"), path("all_applicants/", views.all_applicants, name="all_applicants"), # for admin path("admin_login/", views.admin_login, name="admin_login"), path("view_applicants/", views.view_applicants, name="view_applicants"), path("delete_applicant/<int:myid>/", views.delete_applicant, name="delete_applicant"), path("pending_companies/", views.pending_companies, name="pending_companies"), path("accepted_companies/", views.accepted_companies, name="accepted_companies"), path("rejected_companies/", views.rejected_companies, name="rejected_companies"), path("all_companies/", views.all_companies, name="all_companies"), path("change_status/<int:myid>/", views.change_status, name="change_status"), path("delete_company/<int:myid>/", views.delete_company, name="delete_company"), ]
Объяснение кода:
Приведенный выше код состоит из url для всего проекта. Эти пути разделяются для соискателей, для администратора и для компаний.
Models.py :
from django.db import models from django.contrib.auth.models import User class Applicant(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) phone = models.CharField(max_length=10) image = models.ImageField(upload_to="") gender = models.CharField(max_length=10) type = models.CharField(max_length=15) def __str__(self): return self.user.first_name class Company(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) phone = models.CharField(max_length=10) image = models.ImageField(upload_to="") gender = models.CharField(max_length=10) type = models.CharField(max_length=15) status = models.CharField(max_length=20) company_name = models.CharField(max_length=100) def __str__ (self): return self.user.username class Job(models.Model): company = models.ForeignKey(Company, on_delete=models.CASCADE) start_date = models.DateField() end_date = models.DateField() title = models.CharField(max_length=200) salary = models.FloatField() image = models.ImageField(upload_to="") description = models.TextField(max_length=400) experience = models.CharField(max_length=100) location = models.CharField(max_length=100) skills = models.CharField(max_length=200) creation_date = models.DateField() def __str__ (self): return self.title class Application(models.Model): company = models.CharField(max_length=200, default="") job = models.ForeignKey(Job, on_delete=models.CASCADE) applicant = models.ForeignKey(Applicant, on_delete=models.CASCADE) resume = models.ImageField(upload_to="") apply_date = models.DateField() def __str__ (self): return str(self.applicant)
Объяснение кода:
Всего для проекта было создано четыре модели. Модель кандидатов используется для хранения всех основных данных о соискателях. Модель компании используется для хранения данных о различных компаниях, регистрирующихся на портале. Модель вакансий хранит данные о вакансиях, которые компания может открыть для соискателей. Соискатели, претендующие на работу в какой-либо компании, сохраняются в модели Application.
1. Панель навигации главной страницы (basic.html):
<nav class="navbar navbar-expand-lg sticky-top navbar-dark"> <div class="container-fluid w-50"> <a class="navbar-brand" href="#">Job Portal</a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <ul class="navbar-nav me-auto mb-2 mb-lg-0"> {% if not request.user.is_authenticated %} <li class="nav-item"> <a class="nav-link {% block home %} {% endblock %}" aria-current="page" href="/">Home</a> </li> <li class="nav-item"> <a class="nav-link {% block user_login %} {% endblock %}" href="/user_login/">User Login</a> </li> <li class="nav-item"> <a class="nav-link {% block admin_login %} {% endblock %}" href="/admin_login/">Admin Login</a> </li> <li class="nav-item"> <a class="nav-link {% block company_login %} {% endblock %}" href="/company_login/">Company Login</a> </li> {% else %} <li class="nav-item"> <a class="nav-link active" href="/logout/">Logout</a> </li> </ul> {% endif %} </div> </div> </nav>
Объяснение кода:
Всего есть 4 навигационные панели для главной страницы, страниц регистрации и входа, для пользователей, для компаний и, наконец, для администратора. Приведенный выше код предназначен для главной страницы проекта, страниц регистрации и входа. Как только проект будет открыт, будут доступны 3 варианта: авторизация пользователя, авторизация администратора и авторизация компании.
Пользователи могут войти или зарегистрироваться через опцию входа пользователя и аналогично, администратора и компании. Если пользователи уже аутентифицированы, то вместо опций входа будет показана опция выхода из системы.
2. Главная страница (index.html):
<div class="container-fluid mt-2"> <img src="{% static 'industries-recruitment.png' %}" alt="" width="100%" height="450px"> </div> <div class="container-fluid mt-2" style="background-color: #4f868c; width: 100%;"> <div class="row"> <div class="col-md-4"> <h3 style="color: aliceblue;">Contact Us</h3> <p style="color: aliceblue">Email: [email protected]</p> <p style="color: aliceblue">Mobile No.: 9745632121</p> </div> </div> </div>
Views.py :
def index(request): return render(request, "index.html")
Объяснение кода:
На главной странице раскрывается панель навигации (basic.html). Также показано изображение с контейнером для контактов. В разделе «Контакты» в качестве контактных данных указаны адрес электронной почты и номер мобильного телефона.
3. Страница регистрации и входа пользователя (user_login.html) и (signup.html):
User Login:
<form method="POST"> {% csrf_token %} <div class="container mt-5"> <h6>Haven't register yet, then click here <a href="/signup/" type="submit" class="btn" style="background-color: #4f868c; color: white;">Signup</a> </h6> <div class="mb-3"> <label for="username" class="form-label"><i style="font-weight: bold;">Username</i></label> <input type="text" class="form-control" id="username" name="username" placeholder="Enter Username"> </div> <div class="mb-3"> <label for="password" class="form-label"><i style="font-weight: bold;">Password</i></label> <input type="password" class="form-control" id="password" name="password" placeholder="Enter Password"> </div> <br> <input type="submit" value="Submit" class="btn" style="background-color: #4f868c; color: white; font-size: larger; width: 8rem;"> </div> </form>
Views.py :
def user_login(request): if request.user.is_authenticated: return redirect("/") else: if request.method == "POST": username = request.POST['username'] password = request.POST['password'] user = authenticate(username=username, password=password) if user is not None: user1 = Applicant.objects.get(user=user) if user1.type == "applicant": login(request, user) return redirect("/user_homepage") else: thank = True return render(request, "user_login.html", {"thank":thank}) return render(request, "user_login.html")
User Signup:
<form class="container mt-4" method="POST" enctype="multipart/form-data"> {% csrf_token %} <div class="row"> <div class="form-group col-md-6"> <label>First Name</label> <input type="text" class="form-control" name="first_name" id="first_name" placeholder="Enter First Name"> </div> <div class="form-group col-md-6"> <label>Last Name</label> <input type="text" class="form-control" name="last_name" id="last_name" placeholder="Enter Last Name"> </div> </div> <div class="row mt-4"> <div class="form-group col-md-6"> <label>Password</label> <input type="password" class="form-control" name="password1" id="password1" placeholder="Enter Password"> </div> <div class="form-group col-md-6"> <label>Confirm Password</label> <input type="password" class="form-control" name="password2" id="password2" placeholder="Confirm Password"> </div> </div> <div class="row mt-4"> <div class="form-group col-md-6"> <label>Email Id</label> <input type="email" class="form-control" name="email" id="email" placeholder="Enter Email Id"> </div> <div class="form-group col-md-6"> <label>Contact Number</label> <input type="tel" class="form-control" name="phone" id="phone" placeholder="Enter Contact Number"> </div> </div> <div class="row mt-4"> <div class="form-group col-md-6"> <label>Gender</label> <div style="border: 1px solid lightgrey; padding: 5px; border-radius: 6px;"> <div class="form-check form-check-inline"> <input type="radio" class="custom-control-input" name="gender" id="male" value="Male"> <label for="male" class="custom-control-label">Male</label> </div> <div class="form-check form-check-inline"> <input type="radio" class="custom-control-input" name="gender" id="female" value="Female"> <label for="female" class="custom-control-label">Female</label> </div> </div> </div> <div class="form-group col-md-6"> <label>Profile Picture</label> <input type="file" class="form-control" name="image" id="image" placeholder="Enter Last Name"> </div> </div> <br> <input type="submit" value="Submit" class="btn" style="background-color: #4f868c; color: white; font-size: larger; width: 8rem;"> </form>
Views.py :
def signup(request): if request.method=="POST": username = request.POST['email'] first_name=request.POST['first_name'] last_name=request.POST['last_name'] password1 = request.POST['password1'] password2 = request.POST['password2'] phone = request.POST['phone'] gender = request.POST['gender'] image = request.FILES['image'] if password1 != password2: messages.error(request, "Passwords do not match.") return redirect('/signup') user = User.objects.create_user(first_name=first_name, last_name=last_name, username=username, password=password1) applicants = Applicant.objects.create(user=user, phone=phone, gender=gender, image=image, type="applicant") user.save() applicants.save() return render(request, "user_login.html") return render(request, "signup.html")
Объяснение кода:
Все кандидаты могут нажать на вход, а если они еще не зарегистрировались, то могут нажать на регистрацию. Там они могут заполнить необходимые данные и зарегистрироваться на портале в качестве соискателя. После успешной регистрации пользователь будет зарегистрирован как соискатель и сможет войти в систему, используя имя пользователя и пароль.
4. Страница профиля пользователя (user_homepage.html):
<div class="container"> <div class="row"> <div class="col-sm-6"> <form class="container mt-4" method="POST" enctype="multipart/form-data"> {% csrf_token %} <div class="row"> <div class="form-group col-md-6"> <label>First Name</label> <input type="text" class="form-control mt-2" name="first_name" id="first_name" value="{{applicant.user.first_name}}" required> </div> <div class="form-group col-md-6"> <label>Last Name</label> <input type="text" class="form-control mt-2" name="last_name" id="last_name" value="{{applicant.user.last_name}}" required> </div> </div> <div class="row mt-4"> <div class="form-group col-md-12"> <label>Username</label> <input type="text" class="form-control mt-2" name="username" id="username" value="{{applicant.user.username}}" readonly> </div> </div> <div class="row mt-4"> <div class="form-group col-md-6"> <label>Email Id</label> <input type="email" class="form-control mt-2" name="email" id="email" value="{{applicant.user.email}}" required> </div> <div class="form-group col-md-6"> <label>Contact Number</label> <input type="tel" class="form-control mt-2" name="phone" id="phone" value="{{applicant.phone}}" required> </div> </div> <div class="row mt-4"> <div class="form-group col-md-6"> <label>Gender</label> {% if applicant.gender == "Male" %} <div class="mt-2" style="border: 1px solid lightgrey; padding: 5px; border-radius: 6px;"> <div class="form-check form-check-inline"> <input type="radio" class="custom-control-input" name="gender" value="Male" checked> <label for="male" class="custom-control-label">Male</label> </div> <div class="form-check form-check-inline"> <input type="radio" class="custom-control-input" name="gender" value="Female"> <label for="female" class="custom-control-label">Female</label> </div> </div> {% else %} <div style="border: 1px solid lightgrey; padding: 5px; border-radius: 6px;"> <div class="form-check form-check-inline"> <input type="radio" class="custom-control-input" name="gender" value="Male"> <label for="male" class="custom-control-label">Male</label> </div> <div class="form-check form-check-inline"> <input type="radio" class="custom-control-input" name="gender" value="Female" checked> <label for="female" class="custom-control-label">Female</label> </div> </div> {% endif %} </div> <div class="form-group col-md-6"> <label>Profile Photo</label> <input type="file" class="form-control mt-2" name="image" id="image"> </div> </div> <input type="submit" value="Submit" class="btn mt-4" accept="image/*" style="background-color: #4f868c; color: white; font-size: larger; width: 8rem;"> </form> </div> <div class="col-sm-4 mt-5 text-center"> <img src="{{applicant.image.url}}" alt="" width="200px" height="200px"> </div> </div> </div>
Views.py :
def user_homepage(request): if not request.user.is_authenticated: return redirect('/user_login/') applicant = Applicant.objects.get(user=request.user) if request.method=="POST": email = request.POST['email'] first_name=request.POST['first_name'] last_name=request.POST['last_name'] phone = request.POST['phone'] gender = request.POST['gender'] applicant.user.email = email applicant.user.first_name = first_name applicant.user.last_name = last_name applicant.phone = phone applicant.gender = gender applicant.save() applicant.user.save() try: image = request.FILES['image'] applicant.image = image applicant.save() except: pass alert = True return render(request, "user_homepage.html", {'alert':alert}) return render(request, "user_homepage.html", {'applicant':applicant})
Объяснение кода:
Как только кандидат входит в систему, он перенаправляется на страницу профиля. На странице профиля отображается вся информация о соискателе, которую он указал во время регистрации. Соискатель также может редактировать некоторые данные после входа в систему.
5. Страница списка вакансий (all_jobs.html):
<div class="container mt-4"> <table class="table table-hover" id="example"> <thead> <tr> <th>Sr.No</th> <th>Company Name</th> <th>Job Title</th> <th>Salary</th> <th>Location</th> <th>Created On</th> <th>Apply</th> </tr> </thead> <tbody> {% for job in jobs %} <tr> <td>{{forloop.counter}}</td> <td>{{job.company.company_name}}</td> <td>{{job.title}}</td> <td>{{job.salary}}</td> <td>{{job.location}}</td> <td>{{job.creation_date}}</td> {% if job.id in data %} <td><a class="btn btn-success">Applied</a></td> {% else %} <td><a href="/job_detail/{{job.id}}/" class="btn btn-success">Apply</a></td> {% endif %} </tr> {% endfor %} </tbody> </table> </div>
Views.py :
def all_jobs(request): jobs = Job.objects.all().order_by('-start_date') applicant = Applicant.objects.get(user=request.user) apply = Application.objects.filter(applicant=applicant) data = [] for i in apply: data.append(i.job.id) return render(request, "all_jobs.html", {'jobs':jobs, 'data':data})
Объяснение кода:
В навигационной панели для всех соискателей, вошедших под своей учетной записью, имеется опция списка вакансий. Нажав на опцию списка вакансий, соискатель может просмотреть все доступные вакансии. Для каждой вакансии создана кнопка «Откликнуться». Если название вакансии соответствует навыкам или интересам соискателя, он может нажать на кнопку «Откликнуться», чтобы подробно ознакомиться с вакансией.
6. Страница детализации (job_detail.html):
<div class="container mt-4 shadow-lg py-3 mb-4"> <div class="row"> <div class="col-md-4"> <img src="{{job.image.url}}" alt="" width="350px" height="250px"> </div> <div class="col-md-6"> <h2>{{job.title}}</h2> <p>{{job.company.company_name}}<i><a href=""> (View All Jobs)</a></i></p> <i class="fa fa-map-marker">{{job.location}}</i> <i class="fa fa-calendar">{{job.creation_date}}</i> <br> <strong>Salary: <i class="fa fa-inr mr-2"></i>₹ {{job.salary}}/month</strong> <div class="mt-3"> <a href="/job_apply/{{job.id}}/" class="btn btn-danger">Apply For The Job</a> </div> </div> </div> <div class="mt-4"> <h3>Overview</h3> <p>{{job.description}}</p> <h4>Required Experience</h4> <p>{{job.experience}} years</p> <h4>Skills Required</h4> <p>{{job.skills}}</p> <h4>Start Date</h4> <p>{{job.start_date}}</p> </div> </div>
Views.py :
def job_detail(request, myid): job = Job.objects.get(id=myid) return render(request, "job_detail.html", {'job':job})
Объяснение кода:
Когда соискатель нажимает на кнопку «Откликнуться», он может просмотреть все подробности об этой вакансии. После просмотра всех подробностей кандидат может нажать на кнопку «Откликнуться на вакансию», если он хочет подать заявку.
7. Загрузка резюме на вакансию (job_apply.html):
<div class="container mt-4 shadow-lg py-3 mb-4"> <form method="POST" enctype="multipart/form-data"> {% csrf_token %} <div class="form-row"> <label>Upload Resume</label> <input type="file" class="form-control mt-3" name="resume" id="resume"> </div> <input type="submit" value="Submit" class="btn btn-danger mt-3"> </form> </div>
Views.py :
def job_apply(request, myid): if not request.user.is_authenticated: return redirect("/user_login") applicant = Applicant.objects.get(user=request.user) job = Job.objects.get(id=myid) date1 = date.today() if job.end_date < date1: closed=True return render(request, "job_apply.html", {'closed':closed}) elif job.start_date > date1: notopen=True return render(request, "job_apply.html", {'notopen':notopen}) else: if request.method == "POST": resume = request.FILES['resume'] Application.objects.create(job=job, company=job.company, applicant=applicant, resume=resume, apply_date=date.today()) alert=True return render(request, "job_apply.html", {'alert':alert}) return render(request, "job_apply.html", {'job':job})
Объяснение кода:
Соискатель может окончательно отправить резюме в компанию, в которую он/она хочет подать заявку. Компания может проверить резюме и при желании связаться с соискателем.
8. Вход и регистрация компании (company_login.html) и (company_signup.html):
Авторизация компании:
<form method="POST"> {% csrf_token %} <div class="container mt-5"> <h6>Haven't register yet, then click here <a href="/company_signup/" type="submit" class="btn" style="background-color: #4f868c; color: white;">Signup</a> <div class="mb-3"> <label for="username" class="form-label"><i style="font-weight: bold;">Username</i></label> <input type="text" class="form-control" id="username" name="username" placeholder="Enter Username"> </div> <div class="mb-3"> <label for="password" class="form-label"><i style="font-weight: bold;">Password</i></label> <input type="password" class="form-control" id="password" name="password" placeholder="Enter Password"> </div> <br> <input type="submit" value="Submit" class="btn" style="background-color: #4f868c; color: white; font-size: larger; width: 8rem;"> </div> </form>
Views.py :
def company_login(request): if request.method == "POST": username = request.POST['username'] password = request.POST['password'] user = authenticate(username=username, password=password) if user is not None: user1 = Company.objects.get(user=user) if user1.type == "company" and user1.status != "pending": login(request, user) return redirect("/company_homepage") else: alert = True return render(request, "company_login.html", {"alert":alert}) return render(request, "company_login.html")
Регистрация компании:
<form class="container mt-4" method="POST" enctype="multipart/form-data"> {% csrf_token %} <div class="row"> <div class="form-group col-md-6"> <label>First Name</label> <input type="text" class="form-control" name="first_name" id="first_name" placeholder="Enter First Name"> </div> <div class="form-group col-md-6"> <label>Last Name</label> <input type="text" class="form-control" name="last_name" id="last_name" placeholder="Enter Last Name"> </div> </div> <div class="row mt-4"> <div class="form-group col-md-12"> <label>Username</label> <input type="text" class="form-control" name="username" id="username" placeholder="Enter Username"> </div> </div> <div class="row mt-4"> <div class="form-group col-md-6"> <label>Password</label> <input type="password" class="form-control" name="password1" id="password1" placeholder="Enter Password"> </div> <div class="form-group col-md-6"> <label>Confirm Password</label> <input type="password" class="form-control" name="password2" id="password2" placeholder="Confirm Password"> </div> </div> <div class="row mt-4"> <div class="form-group col-md-6"> <label>Email Id</label> <input type="email" class="form-control" name="email" id="email" placeholder="Enter Email Id"> </div> <div class="form-group col-md-6"> <label>Contact Number</label> <input type="tel" class="form-control" name="phone" id="phone" placeholder="Enter Contact Number"> </div> </div> <div class="row mt-4"> <div class="form-group col-md-6"> <label>Gender</label> <div style="border: 1px solid lightgrey; padding: 5px; border-radius: 6px;"> <div class="form-check form-check-inline"> <input type="radio" class="custom-control-input" name="gender" id="male" value="Male"> <label for="male" class="custom-control-label">Male</label> </div> <div class="form-check form-check-inline"> <input type="radio" class="custom-control-input" name="gender" id="female" value="Female"> <label for="female" class="custom-control-label">Female</label> </div> </div> </div> <div class="form-group col-md-6"> <label>Logo of the Company</label> <input type="file" class="form-control" name="image" id="image" placeholder="Enter Last Name"> </div> </div> <div class="row mt-4"> <div class="form-group col-md-12"> <label>Company Name</label> <input type="text" class="form-control" name="company_name" id="company_name" placeholder="Enter Name of the Company"> </div> </div> <br> <input type="submit" value="Submit" class="btn" style="background-color: #4f868c; color: white; font-size: larger; width: 8rem;"> </form>
Views.py :
def company_signup(request): if request.method=="POST": username = request.POST['username'] email = request.POST['email'] first_name=request.POST['first_name'] last_name=request.POST['last_name'] password1 = request.POST['password1'] password2 = request.POST['password2'] phone = request.POST['phone'] gender = request.POST['gender'] image = request.FILES['image'] company_name = request.POST['company_name'] if password1 != password2: messages.error(request, "Passwords do not match.") return redirect('/signup') user = User.objects.create_user(first_name=first_name, last_name=last_name, email=email, username=username, password=password1) company = Company.objects.create(user=user, phone=phone, gender=gender, image=image, company_name=company_name, type="company", status="pending") user.save() company.save() return render(request, "company_login.html") return render(request, "company_signup.html")
Объяснение кода:
Как и кандидаты, все компании сначала должны зарегистрировать свою компанию на портале. В процессе регистрации будут получены все основные данные компании. После успешной регистрации компания может войти в систему, используя имя пользователя и пароль.
9. Страница профиля компании (company_homepage.html):
<div class="container"> <div class="row"> <div class="col-sm-6"> <form class="container mt-4" method="POST" enctype="multipart/form-data"> {% csrf_token %} <div class="row"> <div class="form-group col-md-6"> <label>First Name</label> <input type="text" class="form-control" name="first_name" id="first_name" value="{{company.user.first_name}}" required> </div> <div class="form-group col-md-6"> <label>Last Name</label> <input type="text" class="form-control" name="last_name" id="last_name" value="{{company.user.last_name}}" required> </div> </div> <div class="row mt-4"> <div class="form-group col-md-12"> <label>Username</label> <input type="text" class="form-control" name="username" id="username" value="{{company.user.username}}" readonly> </div> </div> <div class="row mt-4"> <div class="form-group col-md-12"> <label>Company Name</label> <input type="text" class="form-control" name="company_name" id="company_name" value="{{company.company_name}}" readonly> </div> </div> <div class="row mt-4"> <div class="form-group col-md-6"> <label>Email Id</label> <input type="email" class="form-control" name="email" id="email" value="{{company.user.email}}" required> </div> <div class="form-group col-md-6"> <label>Contact Number</label> <input type="tel" class="form-control" name="phone" id="phone" value="{{company.phone}}" required> </div> </div> <div class="row mt-4"> <div class="form-group col-md-6"> <label>Gender</label> {% if company.gender == "Male" %} <div style="border: 1px solid lightgrey; padding: 5px; border-radius: 6px;"> <div class="form-check form-check-inline"> <input type="radio" class="custom-control-input" name="gender" value="Male" checked> <label for="male" class="custom-control-label">Male</label> </div> <div class="form-check form-check-inline"> <input type="radio" class="custom-control-input" name="gender" value="Female"> <label for="female" class="custom-control-label">Female</label> </div> </div> {% else %} <div style="border: 1px solid lightgrey; padding: 5px; border-radius: 6px;"> <div class="form-check form-check-inline"> <input type="radio" class="custom-control-input" name="gender" value="Male"> <label for="male" class="custom-control-label">Male</label> </div> <div class="form-check form-check-inline"> <input type="radio" class="custom-control-input" name="gender" value="Female" checked> <label for="female" class="custom-control-label">Female</label> </div> </div> {% endif %} </div> <div class="form-group col-md-6"> <label>Logo of the Company</label> <input type="file" class="form-control" name="image" id="image"> </div> </div> <input type="submit" value="Submit" class="btn mt-4" style="background-color: #4f868c; color: white; font-size: larger; width: 8rem;"> </form> </div> <div class="col-sm-4 mt-5 text-center"> <img src="{{company.image.url}}" alt="" width="200px" height="200px"> </div> </div> </div>
Views.py :
def company_homepage(request): if not request.user.is_authenticated: return redirect("/company_login") company = Company.objects.get(user=request.user) if request.method=="POST": email = request.POST['email'] first_name=request.POST['first_name'] last_name=request.POST['last_name'] phone = request.POST['phone'] gender = request.POST['gender'] company.user.email = email company.user.first_name = first_name company.user.last_name = last_name company.phone = phone company.gender = gender company.save() company.user.save() try: image = request.FILES['image'] company.image = image company.save() except: pass alert = True return render(request, "company_homepage.html", {'alert':alert}) return render(request, "company_homepage.html", {'company':company})
Объяснение кода:
После входа в систему отображается страница профиля компании, где компания может редактировать некоторые данные.
10. Добавление вакансий от компании (add_job.html)
<form class="container mt-3" method="POST" enctype="multipart/form-data"> {% csrf_token %} <div class="row"> <div class="form-group col-md-12"> <label>Job Title</label> <input type="text" class="form-control" name="job_title" id="job_title" placeholder="Job Title" required> </div> </div> <div class="row mt-3"> <div class="form-group col-md-6"> <label>Start Date</label> <input type="date" class="form-control" name="start_date" id="start_date" placeholder="Start Date" required> </div> <div class="form-group col-md-6"> <label>End Date</label> <input type="date" class="form-control" name="end_date" id="end_date" placeholder="End Date" required> </div> </div> <div class="row mt-3"> <div class="form-group col-md-6"> <label>Company Logo</label> <input type="file" class="form-control" name="logo" id="logo" placeholder="Enter Company Logo" required> </div> <div class="form-group col-md-6"> <label>Salary (per month)</label> <input type="tel" class="form-control" name="salary" id="salary" placeholder="Enter Salary (per month)" required> </div> </div> <div class="row mt-3"> <div class="form-group col-md-12"> <label>Skills Required</label> <input type="text" class="form-control" name="skills" id="skills" placeholder="Enter the required skills for the job" required> </div> </div> <div class="row mt-3"> <div class="form-group col-md-6"> <label>Experience (in years)</label> <input type="text" class="form-control" name="experience" id="experience" placeholder="Experience required (in years)" required> </div> <div class="form-group col-md-6"> <label>Company Location</label> <input type="text" class="form-control" name="location" id="location" placeholder="Enter exact location of the Company" required> </div> </div> <div class="row mt-3"> <div class="form-group col-md-12"> <label>Job Description</label> <textarea name="description" id="description" class="form-control" cols="30" rows="4" placeholder="Description of the exact job" required></textarea> </div> </div> <input type="submit" value="Submit" class="btn mt-3" style="background-color: #4f868c; color: white; font-size: larger; width: 8rem;"> </form>
Views.py :
def add_job(request): if not request.user.is_authenticated: return redirect("/company_login") if request.method == "POST": title = request.POST['job_title'] start_date = request.POST['start_date'] end_date = request.POST['end_date'] salary = request.POST['salary'] image = request.FILES['logo'] experience = request.POST['experience'] location = request.POST['location'] skills = request.POST['skills'] description = request.POST['description'] user = request.user company = Company.objects.get(user=user) job = Job.objects.create(company=company, title=title,start_date=start_date, end_date=end_date, salary=salary, image=image, experience=experience, location=location, skills=skills, description=description, creation_date=date.today()) job.save() alert = True return render(request, "add_job.html", {'alert':alert}) return render(request, "add_job.html")
Объяснение кода:
Компании могут добавлять новые вакансии, которые будут просматриваться соискателями. Если соискатели заинтересованы в работе, то они могут отправить резюме и подать заявку на эту позицию. При добавлении вакансии компании должны предоставить подробную информацию о ней.
11. Полный список вакансий, добавленных компанией (job_list.html):
<div class="container mt-4"> <table class="table table-hover" id="example"> <thead> <tr> <th>Sr.No</th> <th>Job Title</th> <th>Created On</th> <th>Action</th> <th>Delete</th> </tr> </thead> <tbody> {% for job in jobs %} <tr> <td>{{forloop.counter}}</td> <td>{{job.title}}</td> <td>{{job.creation_date}}</td> <td><a href="/edit_job/{{job.id}}/" class="btn"><i class="fa fa-edit"></i></a></td> <td><a href="#" class="btn"><i class="fa fa-trash"></i></a></td> </tr> {% endfor %} </tbody> </table> </div>
Views.py :
def job_list(request): if not request.user.is_authenticated: return redirect("/company_login") companies = Company.objects.get(user=request.user) jobs = Job.objects.filter(company=companies) return render(request, "job_list.html", {'jobs':jobs})
Объяснение кода:
После добавления вакансий компании могут просматривать все добавленные ими вакансии. При необходимости они могут удалить вакансию или отредактировать информацию о ней.
12. Все претенденты подали заявки на эту вакансию (all_applicants.html):
<div class="container mt-4"> <table class="table table-hover" id="example"> <thead> <tr> <th>Sr.No</th> <th>Job Title</th> <th>Applicant</th> <th>Applied On</th> <th>Resume</th> <th>Delete</th> </tr> </thead> <tbody> {% for i in application %} <tr> <td>{{forloop.counter}}</td> <td>{{i.job}}</td> <td>{{i.applicant}}</td> <td>{{i.apply_date}}</td> <td><a href="{{i.resume.url}}" class="btn"><i class="fa fa-file"></i></a></td> <td><a href="#" class="btn"><i class="fa fa-trash"></i></a></td> </tr> {% endfor %} </tbody> </table> </div>
Views.py :
def all_applicants(request): company = Company.objects.get(user=request.user) application = Application.objects.filter(company=company) return render(request, "all_applicants.html", {'application':application})
Объяснение кода:
Компания может просматривать всех кандидатов, подавших заявку на работу в эту компанию. Компания может просмотреть резюме всех претендентов и затем отобрать претендентов, которые соответствуют требованиям компании.
13. Страница входа в систему администратора (admin_login.html):
<form method="POST"> {% csrf_token %} <div class="container mt-5"> <div class="mb-3"> <label for="username" class="form-label"><i style="font-weight: bold;">Username</i></label> <input type="text" class="form-control" id="username" name="username" placeholder="Enter Username"> </div> <div class="mb-3"> <label for="password" class="form-label"><i style="font-weight: bold;">Password</i></label> <input type="password" class="form-control" id="password" name="password" placeholder="Enter Password"> </div> <br> <input type="submit" value="Submit" class="btn" style="background-color: #4f868c; color: white; font-size: larger; width: 8rem;"> </div> </form>
Views.py :
def admin_login(request): if request.method == "POST": username = request.POST['username'] password = request.POST['password'] user = authenticate(username=username, password=password) if user.is_superuser: login(request, user) return redirect("/all_companies") else: alert = True return render(request, "admin_login.html", {"alert":alert}) return render(request, "admin_login.html")
Объяснение кода:
Администратор может войти в систему, указав имя пользователя и пароль. Для администратора не предусмотрена возможность регистрации, так как администратор является суперпользователем и может вносить изменения или управлять всем порталом.
14. Все компании (all_companies.html):
<div class="container mt-4"> <table class="table table-hover" id="example"> <thead> <tr> <th>Sr.No</th> <th>Full Name</th> <th>Email Id</th> <th>Contact</th> <th>Gender</th> <th>Company Name</th> <th>Image</th> <th>Status</th> <th>Change Status</th> <th>Delete</th> </tr> </thead> <tbody> {% for company in companies %} <tr> <td>{{forloop.counter}}</td> <td>{{company.user.get_full_name}}</td> <td>{{company.user.email}}</td> <td>{{company.phone}}</td> <td>{{company.gender}}</td> <td>{{company.company_name}}</td> <td><img src="{{company.image.url}}" class="rounded-circle" width="90px" height="70px"></td> <td>{{company.status}}</td> <td><a href="/change_status/{{company.id}}/" class="btn btn-secondary">Change Status</a></td> <td><a href="/delete_company/{{company.user.id}}/" class="btn btn-danger" onclick="return confirm('Are you sure you want to delete this company?')">Delete</a></td> </tr> {% endfor %} </tbody> </table> </div>
Views.py :
def all_companies(request): if not request.user.is_authenticated: return redirect("/admin_login") companies = Company.objects.all() return render(request, "all_companies.html", {'companies':companies})
Объяснение кода:
После того как администратор войдет в систему, ему доступен весь список компаний, зарегистрированных на портале. Он может проверить все детали компании, а затем принять или отклонить эту компанию на основании данных, предоставленных этой компанией. Администратор также может удалить компанию.
15. Все заявители (view_applicants.html):
<div class="container mt-4"> <table class="table table-hover" id="example"> <thead> <tr> <th>Sr.No</th> <th>Full Name</th> <th>Email Id</th> <th>Contact</th> <th>Gender</th> <th>Image</th> <th>Action</th> </tr> </thead> <tbody> {% for applicant in applicants %} <tr> <td>{{forloop.counter}}</td> <td>{{applicant.user.get_full_name}}</td> <td>{{applicant.user.email}}</td> <td>{{applicant.phone}}</td> <td>{{applicant.gender}}</td> <td><img src="{{applicant.image.url}}" class="rounded-circle" width="90px" height="70px"></td> <td><a href="/delete_user/{{applicant.user.id}}/" class="btn btn-danger" onclick="return confirm('Are you sure you want to delete this applicant?')">Delete</a></td> </tr> {% endfor %} </tbody> </table> </div>
Views.py :
def view_applicants(request): if not request.user.is_authenticated: return redirect("/admin_login") applicants = Applicant.objects.all() return render(request, "view_applicants.html", {'applicants':applicants})
Объяснение кода:
Администратор также может просматривать список всех соискателей, зарегистрированных на портале. Администратор может удалить любого кандидата по своему усмотрению.
Скриншоты сайта по поиску работы
Список вакансий для соискателей:
Подробности о вакансии:
Все компании, где администратор может принять или отклонить компанию:
Компании могут размещать вакансии после входа в систему:
Заключение
Итак, мы успешно создали портал по поиску вакансий, используя фронтенд и бэкенд навыки в Django. Я надеюсь, что это был полезный опыт.