Диплом: Создание web-сервисов средствами стека технологий Django+Python3.x+Nginx+Gunicorn+PostgreSQL

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам
42
cart_id = cart.id
request.session['cart_id'] = cart_id
cart = Cart.objects.get(id=cart_id)
form = OrderForm(request.POST or None)
categories = Category.objects.all()
context = {
"form": form,
'cart': cart,
'categories': categories,
}
return render(request, 'order.html', context)
Здесь используется форма заполнения которая наследуется от класса
OrderForm.
После заполнения всех полей формы оформления заказа, вызывается
функция make_order_view() Которая создаёт в базе данных новую запись о
заказе.
def make_order_view(request):
try:
cart_id = request.session['cart_id']
cart = Cart.objects.get(id=cart_id)
request.session['total'] = cart.item.count()
except:
cart = Cart()
cart.save()
cart_id = cart.id
request.session['cart_id'] = cart_id
cart = Cart.objects.get(id=cart_id)
form = OrderForm(request.POST or None)
categories = Category.objects.all()
if form.is_valid():
name = form.cleaned_data['name']
last_name = form.cleaned_data['last_name']
phone = form.cleaned_data['phone']
address = form.cleaned_data['address']
buying_type = form.cleaned_data['buying_type']
comments = form.cleaned_data['comments']
new_order = Order.objects.create(
user=request.user,
items=cart,
total=cart.cart_total,
first_name=name,
last_name=last_name,
phone=phone,
address=address,
buying_type=buying_type,
comments=comments,
)
43
del request.session['cart_id']
del request.session['total']
return HttpResponseRedirect(reverse('thank_you'))
return render(request, 'order.html', {'categories':categories})
Если форма заполнена верно, то заказ заносится в БД, а пользовательская
корзина очищается. Пользователя перенаправляет на информативную
страницу.
Функция account_view() используется для перенаправления
пользователя в личный кабинет.
def account_view(request):
order = Order.objects.filter(user=request.user).order_by('-id')
categories = Category.objects.all()
context ={
'order': order,
'categories':categories,
}
return render(request, 'account.html', context)
В личном кабинете пользователь может посмотреть на свои заказы –
ознакомиться с их деталями и на какой стадии выполнения находится заказ.
Если я ничего не забыл, то все важные функции и классы бизнес логики были
описаны.
Теперь рассмотрим скрипты JS [2], используемые для отображения
информации на страницах.
<script src='{% static "js/jquery.js" %}'></script>
<script>
$(document).ready(function () {
$('#div_id_address').css('display', 'none')
$('#id_buying_type').on('click', function () {
buying_type = $(this).val()
if(buying_type == 'delivery'){
$('#div_id_address').css('display', 'block')
}else {
$('#div_id_address').css('display', 'none')
}
})
$('#id_date_month').css('width', '100px')
$('#id_date_month').css('display', 'inline')
$('#id_date_year').css('width', '100px')
$('#id_date_year').css('display', 'inline')
$('#id_date_day').css('width', '100px')
$('#id_date_day').css('display', 'inline')
})
</script>
44
Этот скрипт позволяет на странице оформления заказа скрывать поле адреса
в случае если пользователь выбирает самовывоз товара.
Следующий скрипт срабатывает при клике на кнопку добавления товара в
корзину.
<script>
$(document).ready(function () {
$('.add_to_cart').on('click', function(e) {
e.preventDefault()
product_slug = $(this).attr('data-slug')
data = {
"product_slug":product_slug
}
$.ajax({
type: 'GET',
url: "{% url 'add_to_cart' %}",
data: data,
success: function (data) {
$("#cart_count").html(data.cart_total)
}
})
})
})
</script>
При нажатии на кнопку вызывается ранее описанная функция add_to_cart().
Для работы с изображением необходимо подключить библиотеку
Pillow. А для единообразия форм подключается библиотека crispy. Полный
текст программного кода будет записан на диск с электронной версией
работы.
3.2 Настройка связки Nginx и Gunicorn
Весь проект я выполнял в Oracle VM VirtualBox на установленной системе
Linux Mint 18.1. Данная система практически не отличается от Ubuntu
консольными командами, если быть точнее, то дистрибутив Linux Mint был
создан на основе Ubuntu. Главное различие в интерфейсе – в Linux Mint
интерфейс приближен к интерфейсу операционной системы Windows.
В Unix подобных системах web-сервер представляет собой daemon.
Daemon – это программа, не связанная с консолью или графическим
интерфейсом машины, на которой она работает. Она постоянно висит в
45
памяти и обрабатывает данные которые, в большинстве случаев приходят по
сети через какой-то сокет.
Так как Nginx[1] является daemon – ном, он запускается с помощью init
скрипта. Далее приведена команда, с помощью которой запускается
Nginx[34]:
sudo /etc/init.d/nginx start
При запуске данного скрипта, запускает исполняемы код web-сервера,
который читает файл конфигурации, но если в файле конфигурации будет
ошибка, то web-сервер сообщит об это и не станет запускаться. Стоит
отметить, что web-сервер должен запускаться с привилегиями супер
пользователя (sudo) потому, что web-серверу необходимо открыть и
прослушивать порт 80, а все порты с порядковым номер ниже 1024 требуют
привилегий супер пользователя. Так же, web-сервер пишет logfiles, которые
доступны лишь супер пользователю. После всех манипуляций, как было
сказано ранее, web-сервер понижает привилегии до уровня простого
пользователя. После этого запускает дочерние workers и приступает к
обработке запросов.
Обычно конфиг web-сервера очень большой, поэтому он делится на
несколько частей, по сути, конфиг web-сервера – это набор связанных между
собой файлов. Конфиг файл хранится в директории /etc/nginx/nginx.conf.
Открыв его, можно увидеть команды подобные unclude /etc/nginx/sites-
enabled/*. Данная команда означает включение указанного файла в файл
конфига.
После того как web-сервер запущен, он полностью отключается от
консоли и работает независимо от того, кто его запустил. Иногда возникает
необходимость остановить web-сервер и для этого используется стандартный
механизм. Любой daemon при запуске складывает свой идентификатор
процесса (PID - process identifier. Порядковый номер процесса, запущенный в
системе Linux) в определённый файл, который и называется pid-file.
46
Располагается он в директории /var/run/nginx.pid Из этого файла можно
получить идентификатор web-сервера и сделать необходимые манипуляции.
Так же у web-сервер есть два принципиально разных log-файла: Error-лог
и Access-лог. В Error-лог содержатся сообщения об ошибках web-сервера. В
Access-лог складываются сообщения об успешно или неуспешно
обработанные http запросы, при этом формат ведения этого лога задаётся
жестко, и он доступен для парсинга с помощью средств обработки.
Процессы операционной системы, которые запущенны в web сервере
делятся на Master (root, 1 процесс) и Worker (www-data, 1+ процесс). Master
процесс – это по сути процесс, запущенный из init скрипта. В его задачи
входит:
1) Чтение и валидация конфига
2) Открытие сокета (ов) и логов
3) Запуск и управление дочерними процессами (worker)
После запуска worker процесс переходит в режим мониторинга, и его задача
заключается в поддержании правильного количества работающих worker.
При необходимости он добавляет или уменьшает worker процессы. Важно
сказать, что Master процесс работает с root правами.
Worker процессы запускаются с пониженными правами и их
количество варьируется от одного до произвольного количества, в
зависимости от модели обработки сетевых соединений которые использует
web сервер. В задачи worker процессов входит лишь циклическая обработка
входящих запросов.
На рисунке 6 изображен упрощённый цикл работы worker процесса.
47
Рисунок 6Цикл работы worker процесса
Web сервер имеет модульную архитектуру, так как является довольно
сложным и громоздким софтом и склонен к расширению. Это сделано для
того, чтобы обеспечить легкость и простоту изменения кода web сервера.
Модульная архитектура означает, что внутри web сервера выделяется ядро,
отвечающее за чтение запроса, отправку ответа и за парсинг http заголовков,
простыми словами, ядро отвечает за работу с протоколом http. И выделяются
модули, которые добавляют функционал web серверу. В случае с Nginx
модули вкомпилированы в код web сервера.
Подробно остановимся на конфигурации web сервера Nginx[35].
Важно прояснить два понятия, которые используются очень часто:
1) Virtual host, виртуальный хост - секция конфига web сервера,
отвечающая за обслуживание определенного домена
2) Location – секция конфига, отвечающая за обслуживание определённой
группы URL
Рассмотрим основные, наиболее важные директивы конфига Nginx.
48
1) user – имя пользователя и группы под которым будут запущены
worker процессы
2) error_log - файл в который web сервер будет помещать сообщения
об ошибках
3) http – секция конфигурации HTTP сервера
4) include – директива включает указанного файла в котором
содержится описание расширений и mime типов
5) default_type – директива, указывающая на тип по умолчанию для
отдаваемого mime документа
6) log_format - указывает на формат access-лога
Перечисленные директивы применяются ко всему серверу Nginx в целом.
Теперь рассмотрим директивы virtual host.
1) server_name – указывает каким доменам данный virtual host
соответствует
2) listen – указывается на каком IP-адресе и порту слушают данный virtual
host
3) access_logпозволяет записывать информацию о работе web сервера в
отдельный файл
4) location - представляют из себя группы URL. Есть несколько способов
записи location.
location = /img/1.gif точное совпадение URL
location ^~/pic/ совпадение по префиксу приоритетнее чем
по регулярному выражению
location ~* \.jpg$ совпадение по регулярному выражению
location /img/ совпадение по префиксу
Указанные способы задания location идут в порядке
убывания приоритета
Теперь, разобравшись с принципами работы Nginx можно перейти к
практической части.
49
Для начала необходимо установить Nginx в Linux Mint (далее в
систему). Это делается с помощью команды sudo apt-get install nginx
После установки создаём новый блок server (виртуальный хост) в каталоге
sites-available:
sudo nano /etc/nginx/sites-available/myproject
Теперь можно записать в него необходимые директивы, а именно:
user sds;
worker_processes 2;
pid /var/run/nginx.pid;
error_log /var/log/nginx.error_log info;
events {
worker_connections 2000;
use kqueue;
}
http {
include conf/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $bytes_sent '
'"$http_referer" "$http_user_agent" '
'"$gzip_ratio"';
client_header_timeout 3m;
client_body_timeout 3m;
send_timeout 3m;
client_header_buffer_size 1k;
large_client_header_buffers 4 4k;
server {
listen 80;
server_name 127.0.0.1;
50
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/user/shop;
}
location / {
include proxy_params;
proxy_pass http://unix:/home/user/shop/myshop.sock;
}
location ~* ^.[^.]$ {
return 404;
}
location ~* \.(jpg|jpeg|gif)$ {
root /spool/www;
access_log off;
expires 30d;
}
}
Сохраняем файл и создаём символьную ссылку на каталог sites-enabled
sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled
Проверьте синтаксис Nginx на наличие ошибок:
sudo nginx –t
Если ошибок нет, перезапускаем сервер
sudo service nginx restart
Теперь, что касательно Gunicorn.
Для начала установим его sudo apt-get install gunicorn. После этого
нужно создать файл сервиса для системы инициализации systemd. Такой
файл позволяет системе инициализации автоматически запускать Gunicorn и
обслуживать приложение. Создаём и открываем unit-файл для Gunicorn с
расширением .service в каталоге /etc/systemd/system:
sudo nano /etc/systemd/system/gunicorn.service
51
И записываем в него настройки.
[Unit]
Description=gunicorn daemon
After=networking.target
[Service]
User=user
Group=www-data
WorkingDirectory=/home/user/shop
ExecStart=/home/user/shop/my_shop_env/bin/gunicorn --workers 3 --bind
unix:/home/user/shop/myshop.sock myshop.wsgi:application
[Install]
antedBy=multi-user.target
Сохраняем изменения, закрываем файл и ставим на автозапуск Gunicorn
sudo systemctl start gunicorn
sudo systemctl enable gunicorn
После всех манипуляций у нас есть рабочая связка Nginx и Gunicorn.
3.3 Размещение web сервиса на сервере
При размещении сервиса на «боевом» сервере необходимо учитывать
несколько немаловажных вещей.
1) Выбор доменной зоны
Доменные зоны делятся на региональные (.ru, .kw, .kz и т.д.) и
тематические (.com, .tv, .market, .travel и т.д.) Всё это необходимо для
того, что бы упростить поиск необходимых сайтов для пользователей, а
так же упростить работу поисковикам. С недавних пор появились
русскоязычные домены (.рф, .москва, .онлайн и т.д.), при их выборе
нужно учитывать, что могут возникнуть проблемы с программным
обеспечением, к примеру старые поисковики не будут их распознавать
или же попросту нельзя будет отправить или получить почту. Это
возникает из-за то, что данные домены еще слишком «молодые» и

Смотрите также:

"Автоматизация обработки заявок ООО "Проектно-Строительная Компания"
"Автоматизация процесса аттестации персонала для ООО "Нэт Бай Нэт Холдинг"
"Анализ интернет-активности конкурентов ( на примере конкурентов "Газпром нефть")
"Бухгалтерский учёт и аудит расчётов с подотчётними лицами в организации на примере ООО "ЛОЦ 10""
«Психологическое сопровождение персонала в организации на примере ООО «Крокус»
Cовершенствование деловой оценки персонала в организации (на примере ООО "Даймонд кейтеринг развитие")
PR как средство продвижения организации (на примере ПАО "Тамбовский завод "Комсомолец им. Н.С. Артемова")
PR-коммуникации в сфере общественного питания (на примере кафе-кондитерской «Cream Cheese»)
SMM как средство повышения эффективности работы учреждений социокультурной сферы (на примере Малого театра)
Value-based education: ценности в системе образования и способы их реализации на уроке английского языка. Опыт Европейских стран