Разработка новостного веб-сайта с интегрированной картой на Django
Определение функциональности разрабатываемого веб-сайта. Выбор вспомогательных средств: языка программирования, веб-фреймворка, СУБД, веб-сервера и системы кэширования. Диаграмма вариантов использования. Расширение модели пользователя, навигация.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | дипломная работа |
Язык | русский |
Дата добавления | 04.07.2018 |
Размер файла | 4,0 M |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
Размещено на http://www.allbest.ru/
ВВЕДЕНИЕ
Одним с основных показателей формирования в государстве нормальных рыночных отношений считается состояние рынка недвижимости. Биржа недвижимости является существенным элементом в государственной экономике, поскольку недвижимое имущество - ключевая доля государственного имущества.
Вместе с этим, развитие интернета как рекламной и торговой площадки позволило многим компаниям, в том числе и риэлторским, размещать свои объявления в глобальной сети.
Целю данной ВКР является создание риэлторского сайта, который будет удобен и прост в обслуживании (администрировании).
В соответствии с целю ВКР были поставлены следующие задачи:
1) разработать архитектуру серверного приложения;
2) реализовать серверное приложения
3) предусмотреть возможность разделения пользователей по правам;
4) разработать удобный интерфейс администратора;
5) интегрировать сайт с существующей CRM;
6) реализовать отображение объектов недвижимости на интерактивной карте
1. АНАЛИТИЧЕСКИЙ ОБЗОР
1.1 Описание предметной области
Вместе со стремительным развитием информационных технологий появилась новая информационная среда - Интернет. Количество ресурсов, предоставляющих информацию рекламного характера, увеличилось из-за большого притока пользователей в сети Интернет. Благодаря этому, эффективность различных видов рекламы в интернете растет с каждым годом. Буквально несколько лет назад многие риэлторы не представляли, для чего им может пригодиться сайт, как он должен функционировать, как с ним работать и какую пользу он способен принести. Сейчас же все по-другому, владельцы агентств осознали, что собственный сайт может стать прекрасной площадкой для привлечения новых клиентов. Также сайт свидетельствует о процветании компании, о ее солидности и современности. Однако далеко не любой сайт может принести бизнесу пользу. Он должен быть грамотно построен и привлекать целевых клиентов.
В общих чертах риэлторский веб-сайт должен содержать информацию о самой компании и предоставляемых услугах. Хорошим дополнением будет наличие на сайте новостных и рекламных статей. Во времена больших объемов данных неоспоримым преимуществом перед другими сайтами будет являться структурированный каталог недвижимости. В совокупности, все это даст начало развитию нового бизнеса и откроет новые рекламные и информационные каналы для уже существующего.
1.2 Определение функциональности разрабатываемого веб-сайта
В данной выпускной квалификационной работе будет разрабатываться веб-сайт риэлторской компании со следующим функционалом:
· Хранение новостных и рекламных статей;
· Рубрикация новостей;
· Подписка на новостную рассылку;
· Хранение объектов недвижимости и их отображение на карте;
· Фильтрация и поиск объектов недвижимости
· Хранение карточек клиентов и сотрудников;
1.3 Обзор имеющихся аналогов
1) realty.yandex.ru
На данном сайте отсутствуют новости и статьи. Объекты недвижимости подгружаются на страницу динамически, что позволяет уменьшить время ответа сервера.
Плюсы:
· Интеграция с сервисом Яндекс.Карты
· Удобная фильтрация
· Возможность сравнения объектов недвижимости
2) www.avito.ru
Недвижимость не является приоритетной темой данного сайта. Однако, из-за удобной фильтрации и большой популярности, на данном сайте размещены множество объявлений о продаже/покупке недвижимости.
3) www.domofond.ru
Серверная часть выполнена на Python/Go. Сайт имеет удобный функционал для фильтрации и сортировки объектов по параметрам. Также поиск объектов недвижимости можно осуществлять по интегрированной Яндекс-карте
· Поиск по карте
· Высокая скорость загрузки страниц
· Удобная фильтрация
· Возможность добавить объект недвижимости в избранное
· Наличие рубрики “вопрос-ответ”
· На сайт регулярно выгружаются аналитические отчеты по динамике цен на недвижимость.
4) vremenagoda-spb.ru
Сайт создан на блоговой системе KS CMS, написанной на php. На сайте размещены только объявления одного жилого комплекса, соответственно объектов недвижимости довольно мало. Помимо квартир на сайте выставлены паркинги и коммерческая недвижимость. Фильтрация осуществляется только по квартирам. Для паркингов и коммерческой недвижимости выведены схемы их расположения. Раздел для новостей и статей отсутствуют. Текстовый контент ограничен статическими страницами.
5) spb.cian.ru
Сайт является локальным представителем ЦИАНГРУПП. Одна из крупнейших баз недвижимости России. Серверная часть выполнена собственном Python фреймворке. На сайте представлены каталоги объектов от разных риэлторов и целых риэлторских агенств.
Плюсы:
· Поиск по карте
· Высокая скорость загрузки страниц
· Удобная фильтрация
· Возможность добавить объект недвижимости в избранное
· Несколько типов пользователей
· Рубрикация и поиск по новостным статьям.
1.4 Критерии выбора готовых решений
Готовые решения должны иметь следующий функционал:
· Расширение для работы с недвижимостью;
· Расширение для работы с картой;
· Наличие мультисайтовости;
· Стоимость;
· Наличие файлового менеджера;
· Возможность синхронизации с RR5;
1.5 Обзор готовых решений
В данном разделе будут рассмотрены 3 самые популярные CMS по версии рейтинга Microsoft за 2017 год.
WordPress - это платформа для создания и публикации веб-сайтов и блога с инструментами для эстетического проектирования, отслеживания посетителей, хранения и загрузки контента и т. Д. С помощью WordPress пользователи могут получить блог или веб-сайт, или и то, и другое, запустив очень мало времени, используя только адрес электронной почты.[1].
Модуль для работы с недвижимостью: “Объекты недвижимости”
Joomla - система управления содержимым, являющаяся свободным программным обеспечением, распространяемым под лицензией GNU GPL. Система довольно удобна, лучше подходит для электронной коммерции, но для ее использования требуются некоторые навыки [2].
Модуль для работы с недвижимостью: “Недвижимость +”
1C-Bitrix - система, поставляемая ООО «1С-Битрикс». Система отличается надежностью и устойчивостью к высоким нагрузкам. Существует несколько версий системы управления содержимым. Необходимая нам версия является платной [3]. сайт программирование фреймворк
Модуль для работы с недвижимостью: “САН”
Модуль для работы с картой: “Карта объектов инфоблока”
1.6 Выбор инструментов разработки
Ниже приведена таблица №1, в которой были сравнены CMS. Критериями сравнения является наличие/отсутствие того или иного функционала.
Таблица 1 - Сравнение популярных CMS
Wordpress |
Joomla |
1С-Битрикс |
||
Расширение для работы с недвижимостью |
+ |
+ |
+ |
|
Расширение для работы с Яндекс/Google картой объектов. |
- |
- |
+ |
|
Мультисайтовость |
+ |
+ |
+ |
|
Файловый менеджер |
- |
+ |
+ |
|
Синхронизация с RR5 CRM |
- |
- |
+ |
|
Цена |
$ |
$$ |
$$$ |
На основе выставленных оценок можно увидеть, что 1C-Bitrix подходит по большинству требований. Однако, из-за высокой стоимости, эта система не подходит для данного проекта. Помимо покупки самого ПО, желательной является оплата подписки на обновления и техническую поддержку.
Исходя из предыдущих пунктов было принято решение самостоятельно разработать систему, реализующую весь необходимый функционал.
2. ОБОСНОВАНИЕ ТЕХНИЧЕСКОГО ПРЕДЛОЖЕНИЯ
Серверная часть веб-сайта для риэлторской компании будет выполнена на фреймворке Django по модульной архитектуре и будет содержать:
· Модуль для работы с недвижимостью;
· Модуль текстовых страниц и рубрик;
· Модуль для работы с картой объектов;
· Модуль для работы с пользователями (подписка, панель администратора)
· Модуль синхронизации с RR5
Модульность приложения позволит использовать его компоненты в следующих проектах
3. ВЫБОР ВСПОМОГАТЕЛЬНЫХ СРЕДСТВ
3.1 Выбор языка программирования
В настоящее время более 80% сайтов используют PHP в качестве серверного языка [4]. Это связано с тем, что PHP изначально проектировался для этих целей. Благодаря этому, для PHP написано огромное количество библиотек. Однако, несмотря на все эти преимущество, в последние 10 лет PHP постепенно теряет популярность. Если не учитывать высокую распространенность PHP, то у него обнаружатся несколько конкурентов. Самыми популярными являются:
1. Python - язык общего назначения, который используется практически в любой области от финансовых структур и статистического анализа до робототехники. Для веб-разработки на Python существует множество фреймворков, например Flask, Pyramid и Django. [5].
2. Ruby - динамический язык программирования с открытым исходным кодом с упором на простоту и продуктивность. Отличительной особенностью является простой и элегантный синтаксис. Самый популярный фреймворк Ruby on rails [6].
3. Node.js - фреймворк для превращения языка JavaScript в нечто, исполняемое на сервере. Позволяет людям, уже знающим JavaScript, сразу перейти к разработке серверной части приложения[7].
По результатам рейтинга, составленного компанией Tiobe Software, python занял четвртое место по востребованности и второе место по темпам роста популярности [8].
Особенности Python:
· Простой
· Лёгкий для изучения
· Свободно распространяется
· Высокоуровневый язык
· Переносимый
· Интерпретируемый
· Объектно-ориентированный
· Расширяемый
· Встраиваемый
· Обширные библиотеки
3.2 Выбор веб-фреймворка
Программной основой будет служить фреймворк Django. Данный фреймворк был выбран из-за наличия встроенной панели администратора, удобной ORM системы и наличия механизмов для работы с сессиями и пользователями. Благодаря большой базе пользователей, Django имеет огромное количество пользовательских расширений, решающих такие проблемы, как кэширование страниц и запросов, создание миниатюр изображений и подключение файлового менеджера. Django -- свободный фреймворк для веб-приложений на языке Python, использующий шаблон проектирования MVC [9]. Model-View-Controller (MVC, «Модель-Представление-Контроллер» -- идея разделения пользовательского интерфейса, данных, и бизнес-логики на независимые компоненты. Это позволяет модифицировать каждый компонент без влияния на другие.
· Model(M) - модель данных. Важно понимать, что это лишь интерфейс доступа к данным, а не сами данные.
· View(V) - пользовательский интерфейс. То, что мы видим в браузере или в интерфейсе приложения.
· Controller(C) - бизнес-логика, отвечающая за вызов метода модели. Принимает от пользователя сигналы, сформированные в представлении.
Рисунок 3.1 - Взаимодействие компонентов MVC
Сайт на Django состоит из модулей, которые следует делать независимыми. Один из основных принципов фреймворка -- DRY (англ. Don't repeat yourself). Еще одной особенностью Django является то, что обработчики URL настраиваются явно при помощи регулярных выражений.
3.3 Выбор СУБД
Базы данных созданы для того чтобы решать очень важную проблему: хранение данных. Хранение данных, само по себе не является достаточно большой проблемой. Однако большую роль играют сопутствующие проблемы:
* Размер;
* Простота обновления;
* Точность;
* Безопасность;
* Избыточность и дублирование;
* Важность.
Довольно длительное время безоговорочной популярностью пользовались СУБД с четко определенной структурой таблиц и схем, определяющих как будут храниться данные. Такие СУБД названы реляционными.
На рисунке 3.2 приведено сравнение популярности самых распространенных реляционных СУБД по данным сайта DB-Engines [10]:
Рисунок 3.2 - Сравнение популярности MySQL, PostgreSQL и SQLite
Рассмотрим подробнее данные СУБД:
* SQLite - легковесная однопользовательская база данных. Представляет из себя самостоятельную библиотеку. Плюсом является то, что при работе с БД все данные извлекаются непосредственно из файла, находящегося локально. Минусом является отсутствие системы пользователей [11];
* MySQL - самая популярная СУБД. Благодаря этому имеет огромное количество написанных библиотек и модулей. К недостаткам можно отнести: относительная ограниченность, проблемы с надежностью, стагнация в развитии [12];
* PostgreSQL - самая развитая СУБД. Имеет возможность программного расширения и содержит “встраиваемые функции” [13];
Сравнение скорости выполнения основных операций приведены на рисунке 3.3 [14].
Рисунок 3.3 - Сравнение скорости выполнения основных операций.
Так как в Django присутствует ORM система, нет особой разницы, какую СУБД использовать. Однако была выбрана PostgreSQL из-за удобного механизма импорта-экспорта, высокой надежности и возможности хранения raw XML и JSON.
3.4 Выбор веб-сервера
Веб-сервер -- сервер, принимающий HTTP-запросы от клиентов, обычно веб-браузеров, и выдающий им HTTP-ответы, как правило, вместе с HTML-страницей, изображением, файлом, медиа-потоком или другими данными.
Apache и Nginx -- два самых широко популярных бесплатных веб-сервера. Более 50% мирового трафика обслуживаются этими двумя серверами. Несмотря на то, что у Apache и Nginx много схожих качеств, они не взаимозаменяемы. В зависимости от ситуации они могут показывать разные результаты [15,16].
Из основных моментов можно отметить, что Apache проще в настройке и обслуживании, однако Nginx является более гибким инструментом и больше подходит для высоконагруженных сервисов.
Для связи Nginx и Django необходим веб-сервер низкого уровня, работающий по стандарту WSGI.
До появления WSGI, двумя основными способами обслуживания веб-приложения python были CGI и mod_python. Оба они упали в своей популярности в пользу WSGI, потому что приложения CGI работают медленнее, так как они порождают новый процесс для каждого запроса. В свою очередь, mod_python напрямую интегрируется с Python, что повышает производительность по сравнению с CGI. Однако он доступен только для Apache.
Рис 3.4. График зависимости скорости ответа от количества одновременных запросов.
В настоящий момент активно используются uWSGI и Gunicorn.
uWSGI - это сервер, который реализует протокол WSGI для связи с другими веб-серверами (Nginx, Apache, Cherokee и т. д.). Пока веб-сервер занимается файлами статики и другими запросами, uWSGI интерпретирует код Python uWSGI был написан специально для Python [17].
Gunicorn - это HTTP-сервер Python WSGI, очень похожий на uWSGI. Сервер Gunicorn прост в настройке и легко интегрируется с Django.
Мною был выбран uWSGI, так как по результатам тестов он более устойчив к высоким нагрузкам. На рисунке 3.4 представлены результаты тестов [18].
Общий вид взаимодействия веб-приложения и выбранных веб-серверов представлен на рисунке 3.5.
Рис. 3.5 взаимодействие веб-серверов и приложения
3.5 Выбор системы кэширования
Главная особенность современных веб сайтов в том, что динамичные. Каждый раз, при запросе данных, серверу приходится выполнить огромное множество вычислений и только после этого выдать результат.
Для большинства небольших веб приложений такие лишние вычисления не особо заметны, однако, для крупных сайтов становится важна экономии времени и ресурсов.
Кэширование означает сохранение результатов вычисления. При следующем запросе можно избежать повторных вычислений.
В данном проекте используется кэширование на основе сетевого хранилища Redis. При этом в памяти сохраняются не только пары “sql запрос” - “объект ответа ”, но и шаблоны страниц [19].
Также существует возможность использовать другой тип кэша Memcached. Этот тип кэширования является самым быстрым, так как он полностью располагается в оперативной памяти. Но этот факт является не только главным преимуществом, но и главным недостатком. При масштабировании сайта количество потребляемой оперативной памяти может увеличиться в разы [20].
3.6 Клиентская часть.
Для упрощения работы с элементами html была использована библиотека jquery. Также библиотека содержит удобный API для AJAX взаимодействия.
В данном проекте технология AJAX используется для реализации валидации форм, пагинации и фильтрации объектов недвижимости.
4. ПРОЕКТИРОВАНИЕ САЙТА
4.1 Диаграмма вариантов использования
Рис. 4.1. Диаграмма вариантов использования
Сайт будет представлять из себя новостной сайт с каталогом недвижимости и тремя типами пользователей. use case диаграмма представлена на рисунке 4.1.
На приведенной use case -диаграмме видны предполагаемые сценарии использования для пользователя, риэлтора и администратора. Пользователь может просматривать каталог объектов, пользуясь предложенными фильтрами, читать новости и подписываться на новостную рассылку. Риэлтор имеет возможность размещать и изменять объекты недвижимости и новостные статьи. Администратор имеет возможность управлять подписками, инициировать синхронизацию с RR5, модерировать новости и акции.
4.2 Проектирование модулей
Проектирование является важным этапом создания программного продукта. Так как в Django используется модульная система приложения, когда одно приложение состоит из нескольких приложений, отвечающих каждое за свой функционал, достаточно разбить проектирование приложения на проектирование отдельных модулей.
Личный кабинет
Модуль личного кабинета является расширением стандартной системы аутентификации пользователей Django.
Модуль предназначен для добавления новых полей в модели пользователя, изменения системы регистрации, добавления страницы личного кабинета, организации привязки пользователей к агентам-модераторам.
Каталог
В модуле каталога будут описаны классы объектов недвижимости по модели Entity-attribute-value. это значит, что к одному объекту недвижимости могут быть привязаны неограниченное количество атрибутов. Однако, атрибуты, присутствующие у большинства объектов, или отмеченные как обязательные, вынесены как поля таблицы объекта в базе данных.
Важной составляющей данного модуля является реализация фильтрации и пагинации объектов недвижимости.
Контент
Данный модуль будет создан для статичных текстовых страниц, новостей, акций. Все текстовые страницы будут описаны одним классом. Идентификатором будет являться поле “Тип контента”. Предполагается, что любая страница текстового контента может состоять из таких блоков: текст, фотогаллерея, видеогалерея, слайдер. Данные блоки будут реализованы через отдельные классы и иметь связь один-ко-многим с текстовыми страницами.
Обратная связь
Модуль обратной связи позволяет назначать список получателей заявок на определенные формы обратной связи.
Навигация
В докладе по веб-юзабилити, подготовленным агентством KoMarketing, сообщается, что примерно половина опрошенных в ходе исследования использует навигационное меню при знакомстве с новым веб-ресурсом. При этом 37% респондентов заявили, что неудобная навигация по сайту -- это достаточное основание, чтобы покинуть сайт и больше никогда на него не возвращаться.
Модуль навигации необходим для создания элементов навигационного меню, таких как боковые и заголовочные меню. Навигационное меню состоит из последовательного, возможно иерархического набора объектов. Необходимо предоставить возможность как вводить ссылки вручную, так и выбирать объекты, на страницу которых будет вести данный пункт меню.
Информационный обмен
Данных модуль необходим для реализации сообщения между сайтом и CRM RR5. Предполагается, что будет содержать методы для получения и разбора XML файла с данными.
Django-cron
Данный модуль предназначен для запуска кода Django/Python по определенному расписанию. Также необходимостью является обеспечение базового функционала для отслеживания выполнения задач.
5. РЕАЛИЗАЦИЯ
5.1 Создание проекта
Django работает как с Python 2.7, так и с 3.х. В данной работе будет использоваться Python версии 3.5.2 и Djnago 1.11. Для установки всех зависимостей в Python используется пакетный менеджер PIP.
Активировав виртуальное окружение, через утилиту PIP установим Django. После завершения установки можно создавать проект. Делается это командой:
django-admin startproject main
Результатом выполнения данной команды станет директория проекта, содержимое которой представлено на рисунке 5.1.
Рисунок 5.1 - содержимое директории main
Немного подробнее об этих файлах:
* main/settings.py - конфигурационный файл проекта. В нем указываются любые стартовые глобальные настройки проекта.;
* main/urls.py - файл содержащий регулярные выражения для менеджера URL;
* main/__init__.py - файл, который указывает Python, что данная директория main является модулем Python;
* main/wsgi.py - входная точка для WSGI-совместимых веб- серверов для исполнения нашего проекта.
После этого необходимо содать нужные приложения, из которых и будет состоять будущий сайт. Произведем это на примере приложения catalog:
django-admin startapp catalog
И затем подключаем это приложение в файле settings.py. После подклбчения, это приложение активно в данном проекте.
В общем случае, приложение (модуль) Django состоит из следующих компонентов:
· Модель данных: предоставляет интерфейс для работы с данными. В данном файле обычно содержатся классы, описывающие данные модуля. Объектно-ориентированный маппер (ORM) обеспечивает таким классам доступ непосредственно к базам данных. Если бы не было ORM, программисту пришлось бы писать запросы непосредственно на SQL. Модель не зависит от конкретного приложения. Данными можно манипулировать из любого места, будь то Web-сервер или командная строка.
· Шаблоны: они являются формой представления данных. Шаблоны имеют свой собственный простой метаязык и являются одним из основных средств вывода на экран.
· URL: это всего лишь механизм внешнего доступа к представлениям (view). При этом одно представление может быть сконфигурировано к нескольким url, предоставляя доступ различным приложениям.
· Представление (view): view в django - обычная функция или класс, отвечающие за принятие запросов от пользователя, их обработка и выдача пользователю страниц или других данных.
5.2 Создание каталога
Каталог является важной частью риэлторского сайта. Каждый объект недвижимости своим атрибутом будет иметь имя, цену, площадь, идентификатор в RR5, описание, адрес и точные координаты. Также были добавлены поля для хранения настроек и контента SEO. Дополнительные необязательные атрибуты выполнены по паттерну “Сущность-атрибут-значение”. Для этого были созданы классы для хранения числовых и строковых атрибутов. Все объекты будут распределены по категориям. Модель категории наследует модель MPTTModel, предоставляющую методы и логику для работы с древовидными структурами. Это необходимо по причине возможной вложенности категорий. Для создания каталога обратимся к файлу models.py, который Django автоматически создал при инициализации приложения сatalog. Добавим туда код, представленный на рисунках 5.2-5.4. Схема БД данного модуля представлена в приложении 3.
Рисунок 5.2 - Код класса категории объектов недвижимости.
Рисунок 5.3 - Код класса объекта недвижимости.
Для отсутствия конфликтов в системе ссылок необходимо на данном этапе определить, какие URL паттерны будет поддерживать данное приложение. В файл urls.py добавим код, приведенный на рисунке 5.5. Из рисунка видно, что модуль каталога решает такие задачи, как: работа с избранными объектами недвижимости, отображение объектов недвижимости, отображение категорий, отображение всего каталога, различные API для получения объектов и их атрибутов в формате json. В файл views.py добавим методы, реализующие перечисленный функционал.
Рисунок. 5.4 - Код классов числового атрибута, дополнительного фото, атрибута-словаря, значения атрибута-словаря.
Рисунок 5.5 - URL паттерны для приложения каталог
Как уже было сказано ранее, Django обеспечивает интерфейс для администраторов сайта «из коробки». Наличие гибкой системы настроек является огромным плюсом. Для настройки отображения обратимся к файлу admin.py в приложении catalog.
Важным и очень полезным элементом в модуле каталога является пользовательская фильтрация. На сайте представлены 2 типа фильтров - флажковые фильтры для атрибутов-словарей и фильтры диапазонов для числовых атрибутов. Внешний вид страницы фильтрации представлен на рисунке 5.6. Страница фильтрации с картой представлена на рисунке 5.7.
Рисунок 5.6 - Страница фильтрации
Процесс фильтрации:
· При загрузке страницы происходит формирование HTML блока с фильтрами, где name input - псевдоним фильтра в формате US-ASCII.
· При нажатии на кнопку “Показать …”, на сервер отправляется GET-запрос с параметрами фильтрации. Запрос десериализуется и разбивается на параметры. На основе параметров фильтрации или поиска формируется список объектов недвижимости.
· При помощи шаблонизатора Django формируется список объектов недвижимости в виде HTML блока. Клиентская часть получает HTML блок с объектам недвижимости и количество объектов после фильтрации в формате json
· Средствами javascript полученные данные вставляются на страницу.
Рис.5.7 - Страница фильтрации с отображением объектов на карте.
Если открыта вкладка “На карте”, ответ сервера меняется. При фильтрации или изменении масштаба карты, на сервер отправляется запрос c параметрами фильтрации. Ответом на этот запрос является список объектов недвижимости в формате GeoJSON. Яндекс.Карты предоставляют удобный API для работы с объектами.
5.3 Расширение модели пользователя
Для расширения стандартной модели пользователя была создана дополнительная таблица и использована связь “один-к-одному”. Код класса представлен на рисунке 5.8.
Рисунок 5.8 - Код класса пользователя
5.4 Контент
Под контентом подразумеваются страницы новостей, акций и статичные страницы. У каждой страницы будет название, дата размещения, краткое описание и логотип.
Рис.5.9 - Код классов текстовой страницы, текстового блока, блока файлов и галереи
Также полезными могут оказаться SEO настройки. Для того, чтобы администратор мог проверить страницу перед публикацией, введено поле “активность”. Схема базы данных данного приложения представлена в приложении 4.
Сам по себе, объект, описанный выше, не включает в себя содержимое страницы. Блоки текста, файлы и фотогалереи являются отдельными объектами, которые через внешний ключ связываются с объектами страниц. Для блоков текста используется библиотека CKEditor. Данная библиотека предоставляет удобный интерфейс для заполнения текстовых блоков в панели администратора. Для хранения изображений используется библиотека Filer. Во избежание конфликтов с URL паттернами остальных модулей, ссылки текстовых страниц имеют префикс “pages”.
5.5 Обратная связь
В модуле обратной связи будут хранится идентификаторы форм обратной связи, к которым при помощи связи многие-ко-многим будут привязаны объекты пользователей. Привязка нужна для определения списка электронных адресов для отправки оповещений. Помимо привязки электронных адресов, в данном приложении содержатся методы для обработки и хранения входящий заявок.
5.6 Навигация
Модель навигации наследует класс MPTTmodel для реализации древовидного меню. Каждый пункт меню может иметь заголовок, родителя, псевдоним для быстрого получения определенного пункта и ссылку. Помимо простых ссылок к элементам меню могут быть привязаны объекты текстовых страниц, новостей, категорий и акций при помощи встроенного в Djnago фреймворка contenttypes. Данный фреймворк позволяет при помощи одного поля, хранящего внешний ключ, и поля, хранящего идентификатор модели объекта, обращаться к различным моделям по одному интерфейсу. Для реализации данного функционала был написан класс HrefModelBase, представленный на рисунке 5.10. Для привязки к пункту меню объект должен наследовать данный класс. Конечный вариант класса представлен на рисунке 5.11.
Рис. 5.10 - Код класса навигационного меню.
Рис.5.11 - Код базового класса объекта-ссылки.
5.7 Информационный обмен
Данное приложение содержит методы для работы с файлом, содержащим данные из RR5.
Для разбора XML была использована библиотека ElementTree. ElementTree (полное название xml.etree.ElementTree) является частью стандартных библиотек свободно распространяющихся вместе языком Python. ElementTree является простым и эффективным решением, предназначенным для создания и хранения XML как иерархических структур данных в памяти. С помощью данной библиотеки можно осуществлять множество манипуляций с XML-файлом: парсинг, поиск элементов, добавление записей и т.д.
5.8 Django cron
Рисунок 5.12 - Интерфейс модуля Django cron.
Принцип работы данного модуля построен на использовании стандартной программы UNIX - cron. Каждую минуту cron инициирует проверку наступления определенного события на стороне Django. Событием будем считать наступление определенного времени. В базе данных хранятся название, время исполнения, частота и исполняемая команда. Также необходимо поле для хранения аргументов команды. Многие элементы данного модуля, такие как менеджеры объектов и логирование, были заимствованы из библиотеки Chronograph и адаптированы под актуальную версию Python. На рисунке 5.12 показан интерфейс данного модуля в панели администратора.
6. РАЗВЕРТЫВАНИЕ НА СЕРВЕРЕ
Развёртывание программного обеспечения (Развёртывание ПО, англ. Software deployment) -- это все действия, которые делают программную систему готовой к использованию. Данный процесс является частью жизненного цикла программного обеспечения. [21]
Для размещения сайта был выбран виртуальный сервер с предустановленной OS Debian 8. Для загрузки проекта и его настройки были использованы протоколы ssh и ftp. На данном сервере были установлены и настроены:
· nginx;
· PostgreSQL;
· Redis;
· Python 3;
Для корректной работы связки uwsgi - nginx, необходимы локальные конфигурации, приведенные на рисунке 6.1.
В файле настроек прописаны домашняя директория проекта, исполняемый python скрипт, расположение сокета, путь до виртуального окружения, пользователь, от лица которого запускается процесс, и расположение лог-файла.
Рисунок 6.1 - локальные настройки uwsgi в формате YAML.
В локальном конфигурационном файле nginx прописаны сокет, директории со статическими файлами и доменное имя, по которому на данном сервере будет доступен сайт. Настройки приведены на рисунке 6.2.
Рисунок 6.2 - локальные настройки nginx
7. ТЕСТИРОВАНИЕ
Тестирование в какой-то степени можно назвать завершающим этапом разработки веб-сайта. Однако он также играет важную роль в процессе создания программного продукта. Ведь только после его успешного выполнения можно смело показать готовый проект заказчику, который будет содержать минимальное число некритичных ошибок.
В соответствии с IEEE Std 829-1983 тестирование -- это процесс анализа программного обеспечения, направленный на выявление отличий между его реально существующими и требуемыми свойствами (дефект) и на оценку свойств ПО. [22].
В рамках выполнения данного этапа были протестированы такие элементы, как: фильтрация и поиск, отправка заявок, синхронизация, создание и удаление пользователей, текстовых страниц и объектов недвижимости.
Рисунок 7.1 - Результаты тестирования формы обратной связи.
Результаты тестирования формы обратной связи при незаполненных полях формы представлены на рисунке 7.1. При заполнении необходимых полей сообщение, содержащее эти данные, пришло на электронный адрес, указанный в панели администратора.
Результаты тестирования создания и удаления пользователей представлены на рисунке 7.2.
При проверке фильтрации были проверены ответы сервера и результаты выполнения javascript. Никаких непредвиденных ситуаций не произошло.
Рисунок 7.2 - Результаты тестирования создания и удаления пользователей.
Помимо функциональных элементов важную роль играет быстродействие сайта. Определяющей характеристикой быстродействия будет выступать скорость загрузки страницы каталога. Результаты тестирования представлены на рисунке 7.3.
Рисунок 7.3 - Результаты тестирования скорости загрузки страницы.
После проведения данных тестов можно сказать, что основные модули сайта полностью работоспособны и не содержат критических ошибок.
ЗАКЛЮЧЕНИЕ
В результате выполнения выпускной квалификационной работы был разработан веб-сайта для агентства “Школа недвижимости”. В ходе проделанной работы были рассмотрены плюсы и минусы готовых сайтов данной тематики. Также были рассмотрены готовые решения.
Проектирование сайта производилось при помощи Django framework. Исходя из требований заказчика были разработаны модули каталога недвижимости, навигации, синхронизации с RR5 и текстового контента.
Проведено тестирование веб-сайта. По завершению тестирования, критичных ошибок не обнаружено.
Сайт был представлен заказчику и получил одобрение на размещение на сервере.
В будущем для развития сайта так же возможна его доработка в соответствии с новыми требованиями заказчика и пожеланиями посетителей.
СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ
1. Введение в WordPress [Электронный ресурс]. - Режим доступа: https://ru.wordpress.org/
2. CMS Joomla! [Электронный ресурс]. - Режим доступа: https://joomlaportal.ru/
3. Готовые решения “1С-Битрикс” [Электронный ресурс]. - Режим доступа: https://www.1c-bitrix.ru/solutions/index.php
4. Рейтинг ЯП и динамика PHP [Электронный ресурс]. - Режим доступа: https://dou.ua/lenta/articles/language-rating-jan-2016/
5. Все о Python [Электронный ресурс]. - Режим доступа: https://www.python.org/about/
6. Введение в Ruby [Электронный ресурс]. - Режим доступа: https://www.ruby-lang.org/ru/
7. Node.js для начинающих [Электронный ресурс]. - Режим доступа: https://nodejs.org/en/
8. Рейтинг языков tiobe [Электронный ресурс]. - Режим доступа: https://www.tiobe.com/tiobe-index/
9. Разработка на django [Электронный ресурс]. - Режим доступа: https://www.djangoproject.com/foundation/
10. Рейтинг популярности СУБД [Электронный ресурс]. - Режим доступа: https://db-engines.com/en/ranking
11. About SQLite [Электронный ресурс]. - Режим доступа: https://www.sqlite.org/about.html
12. Why MySQL? [Электронный ресурс]. - Режим доступа: https://www.mysql.com/why-mysql/
13. About Postgresql [Электронный ресурс]. - Режим доступа: https://www.postgresql.org/about/
14. Сравнение скорости СУБД [Электронный ресурс]. - Режим доступа: https://tproger.ru/translations/sqlite-mysql-postgresql-comparison/
15. Apache web-сервер [Электронный ресурс]. - Режим доступа: https://httpd.apache.org/
16. Работа nginx [Электронный ресурс]. - Режим доступа: https://nginx.ru/ru/
17. Pyhon uWSGI project [Электронный ресурс]. - Режим доступа: https://uwsgi-docs.readthedocs.io/en/latest/
18. Сравнение популярных веб-серверов [Электронный ресурс] - Режим доступа: http://info-comp.ru/sisadminst/221-popular-web-servers.html
19. Redis in action [Электронный ресурс]. - Режим доступа: https://redis.io/clients
20. memcached [Электронный ресурс]. - Режим доступа: https://memcached.org/about
21. Software Deployment [Электронный ресурс]. - Режим доступа: https://en.wikipedia.org/wiki/Software_deployment
22. Стандартизация проведения тестирования ПО [Электронный ресурс]. - Режим доступа: https://ieeexplore.ieee.org/document/741968/
23. ГОСТ Р ИСО/МЭК 12207-2010 Информационная технология (ИТ). Системная и программная инженерия. Процессы жизненного цикла программных средств [Электронный ресурс]. - Введ. 01.01.2013 - Режим доступа: http://docs.cntd.ru/document/1200082859
24. Орлов, С. А. Технологии разработки программного обеспечения: учебник / С.А. Орлов, - Санкт-Петербург: Питер, 2003. - 464с.
ПРИЛОЖЕНИЕ
Код представлений модуля “Каталог”
from django.shortcuts import render
from django.http import Http404, HttpResponse, HttpResponseRedirect
from catalog import models as catalog_models
from django.template.loader import get_template
from django.db.models import Count,Q
import json
from site_settings.models import Settings
from django.db.models import Avg, Max, Min
import datetime
from pycbrf.toolbox import ExchangeRates
from index.models import IndexBlock
from utils.utils import format_word_tovar
def robots_view(request):
robots = Settings.get_singleton().get_robots_txt()
return render(request, 'robots.txt', locals())
def sitemap_view(request):
return render(request, 'sitemap.xml', locals())
def add_favorite_product(request):
try:
product_id = int(request.POST.get("product_id", "").strip(" \n\t"))
except:
product_id = ""
return HttpResponse( json.dumps( {'count':count,'error':1,'message':'Объекта не найдено'} ), content_type = "application/json" )
try:
if not product_id in request.session['favorites_products']:
request.session['favorites_products'].append(product_id)
else:
count = len(request.session['favorites_products'])
return HttpResponse(json.dumps({'count':count,'error':2,'message':'Объект уже был добавлен'}), content_type = "application/json")
except:
request.session['favorites_products'] = []
request.session['favorites_products'].append(int(product_id))
request.session.save()
count = len(request.session['favorites_products'])
return HttpResponse(json.dumps({'count':count,'error':0,'message':'Объект успешно добавлен'}), content_type = "application/json")
def del_favorite_product(request):
try:
product_id = int(request.POST.get("product_id", "").strip(" \n\t"))
except:
product_id = ""
count = len(request.session['favorites_products'])
return HttpResponse(json.dumps({'count':count,'error':1,'message':'Объекта не найдено'}), content_type = "application/json")
if product_id in request.session['favorites_products']:
request.session['favorites_products'].remove(product_id)
else:
count = len(request.session['favorites_products'])
return HttpResponse(json.dumps({'count':count,'error':2,'message':'Объект удалён ранее'}), content_type = "application/json")
request.session.save()
count = len(request.session['favorites_products'])
return HttpResponse(json.dumps({'count':count,'error':0,'message':'Объект успешно удалён'}), content_type = "application/json")
def get_favorite_products(request):
try:
sort = request.GET.get("sort", "").strip(" \n\t")
prods = request.session['favorites_products']
if sort == "low":
s = "price"
elif sort == "heig":
s = "-price"
else:
s = "id"
sorts = [("по умолчанию","def"),("по возрастанию цены","low"),("по убыванию цены","heig")]
products = catalog_models.Product.objects.filter(id__in=prods).order_by(s)
count = products.count()
except:
products = ""
count = 0
return render(request, 'catalog/compare.html', locals())
def get_real_estate(request):
if request.is_ajax():
cat = request.GET.get("subcat", "").strip(" \n\t")
if cat:
cat = catalog_models.Category.objects.get(id = int(cat))
else:
return HttpResponse(json.dumps({"error":1,"message":"Заданной категории не обнаружено"}), content_type = "application/json")
filters = cat.get_fast_attrs()
for f in filters:
f.get_all_values()
filters = catalog_models.NameAttr.render_filters(filters)
return HttpResponse(json.dumps({"error":0,"message":"","filters":filters}), content_type = "application/json")
main_cat = request.GET.get("cat", "").strip(" \n\t")
if main_cat == "0":
main_cat = catalog_models.Category.objects.get(title__iexact = "аренда")
main = 0
else:
main_cat = catalog_models.Category.objects.get(title__iexact = "продажа")
main = 1
cats = catalog_models.Category.objects.filter(parent = main_cat)
cats_property = catalog_models.CategoryProperty.objects.filter(categorys__parent = main_cat).distinct().order_by("-position")
name_attrs = catalog_models.NameAttr.objects.filter(Q(categorys__in = cats) & Q(active = True) & (Q(title__iexact = 'метро') | Q(title__iexact = 'улица') | Q(title__iexact = 'Количество комнат'))).distinct().order_by("-odering")
data = ""
products = catalog_models.Product.objects.filter(category__in = cats)
INFO = {'prices':None, 'filters':None}
for name_attr in name_attrs:
#values dependence ot type
name_attr.get_values(products, data)
if name_attr.title == 'Улица':
INFO['street'] = name_attr
elif name_attr.title == 'Метро':
INFO['metro'] = name_attr
elif name_attr.title == 'Количество комнат':
INFO['location'] = name_attr
INFO['prices'] = products.exclude(price = 0).exclude(price = None).aggregate(min = Min('price'), max = Max('price'))
filters = INFO
blocks = IndexBlock.objects.filter(category__parent = main_cat).order_by("-position")
return render(request, 'catalog/base.html', locals())
def get_catalog_object():
object = {}
object['get_title'] = "Каталог товаров"
object['title'] = object['get_title']
object['get_seo_title'] = Settings.get_seo_title_template().replace("||NO||", object['title'])
object['get_meta_decription'] = Settings.get_meta_description()
object['get_meta_keywords'] = Settings.get_meta_keywords()
object['get_breadcrumps'] = (
("/", "Главная"),
("/catalog/", object['title'])
)
return object
def product_in_tile(x1,y1,x2,y2):
return catalog_models.Product.objects.filter(Q(coord_x__gte = x1) & Q(coord_y__gte = y1) & Q(coord_x__lte = x2) & Q(coord_y__lte = y2))
def get_map_products(request):
bbox = request.GET.get("bbox", "").split(",")
callback = request.GET.get("callback", "")
try:
cat = request.GET.get("cat", "")
except:
cat = ""
if cat:
category = catalog_models.Category.objects.get(id=int(cat))
prods = catalog_models.Product.objects.filter(Q(active = True) & Q(category__in = category.get_descendants(include_self = True)) & Q(coord_x__gte = float(bbox[0])) & Q(coord_y__gte = float(bbox[1])) & Q(coord_x__lte = float(bbox[2])) & Q(coord_y__lte = float(bbox[3])))
else:
prods = catalog_models.Product.objects.filter(Q(active = True) & Q(coord_x__gte = float(bbox[0])) & Q(coord_y__gte = float(bbox[1])) & Q(coord_x__lte = float(bbox[2])) & Q(coord_y__lte = float(bbox[3])))
products, after_filters = catalog_models.Product.filter_products(prods, request.GET)
prods = []
for p in products:
s = {}
s["type"] = "Feature"
s["id"] = str(p.id)
s["geometry"] = {"type":"Point","coordinates":[p.get_coord_x(),p.get_coord_y()]}
s["properties"] = {"balloonContent": p.render_product_map(),"clusterCaption":p.get_title()}
s["options"] = {"iconColor":"#f26121"}
prods.append(s)
result = dict(type= "FeatureCollection",features = prods)
return HttpResponse("{0}({1})".format(callback,json.dumps(result)), content_type = "application/json")
def get_catalog(request):
cats = catalog_models.Category.get_show_cats()
object = get_catalog_object()
search = request.GET.get("search", "").strip(" \t\n")
if search:
return get_category(request)
return render(request, 'catalog/category.html', locals())
def get_category(request, slug):
if slug:
try:
category = catalog_models.Category.objects.get(slug = slug)
except:
raise Http404
category.plus_count_showing()
products = catalog_models.Product.get_products(category)
childs = category.get_childs()
object = category
else:
products = catalog_models.Product.get_products()
products = catalog_models.Product.search_products(products, request.GET.get("search", "").strip(" \t\n"))
childs = catalog_models.Product.get_cats_products(products)
object = get_catalog_object()
if request.GET.get("ajax", "") == "Y":
products, info = catalog_models.Product.filter_products(products, request.GET)
count_products = catalog_models.Product.get_count_str(products)
try:
page = int(request.GET.get("page", 1))
except:
page = 1
if products:
PAGIN = catalog_models.Product.paginate_products(products, page)
products = PAGIN.items
if PAGIN.next:
pagination_str = get_template("pagination.html").render({'PAGIN':PAGIN,'show_more':True})
else:
pagination_str = get_template("pagination.html").render({'PAGIN':PAGIN,'show_more':False})
else:
pagination_str = ""
try:
prods = request.session['favorites_products']
except:
request.session['favorites_products'] = []
request.session.save()
prods = ""
products_list = []
for prod in products[0:16]:
favorite = False
if prod.id in prods:
favorite = True
products_list.append(prod.render_product_item(favorite))
return HttpResponse(json.dumps({'products':products_list, 'pagination':pagination_str, 'count':count_products, 'word_count':format_word_tovar(count_products)}), content_type = "application/json")
filters = catalog_models.Product.get_filters(products, request.GET, category)
products, after_filters = catalog_models.Product.filter_products(products, request.GET)
currency = str(request.GET.get("curr", ""))
if currency == "USD" or currency == "EUR":
now_date = str(datetime.datetime.now().date())
d = str(datetime.datetime.now().date())
curr = ExchangeRates(d,locale_en=True)
val = float(curr[currency].value)
prices = filters['prices']
min_pr = prices['min']
max_pr = prices['max']
filters['prices']['min'] = min_pr*val
filters['prices']['max'] = max_pr*val
min_pr = after_filters['price_min']
max_pr = after_filters['price_max']
if min_pr:
after_filters['price_min'] = float(min_pr)*val
try:
page = int(request.GET.get("page", 1))
except:
page = 1
count_products = products.count()
word_count = format_word_tovar(count_products)
if products:
PAGIN = catalog_models.Product.paginate_products(products,page)
products = PAGIN.items
pagination_str = get_template("pagination.html").render({'PAGIN':PAGIN})
else:
pagination_str = ""
products_list = []
try:
prods = request.session['favorites_products']
except:
request.session['favorites_products'] = []
request.session.save()
prods = ""
for prod in products:
favorite = False
if prod.id in prods:
favorite = True
products_list.append(prod.render_product_item(favorite))
products = None
ymap = 0
if request.GET.get("ymap", "") == "Y":
ymap = 1
if category.parent:
main_cat = category.parent
else:
main_cat = category
cats_property = catalog_models.CategoryProperty.objects.filter(categorys__parent = main_cat).distinct().order_by("-position")
return render(request, 'catalog/category.html', locals())
def get_product_crm(request,idcrm):
try:
pr = catalog_models.Product.objects.get(id_crm=idcrm)
except:
raise Http404
return HttpResponseRedirect(pr.get_absolute_url())
def get_product(request, cat_slug, pr_slug):
if request.GET.get("pr-id", ""):
product = catalog_models.Product.objects.get(id=int(request.GET.get("pr-id", "")))
prods = []
for p in product.get_neighbors():
s = {}
s["type"] = "Feature"
s["id"] = str(p.id)
s["geometry"] = {"type":"Point","coordinates":[p.get_coord_x(),p.get_coord_y()]}
s["properties"] = {"balloonContent": p.render_product_map(),"clusterCaption":p.get_title()}
s["options"] = {"iconColor":"#4d90fe"}
prods.append(s)
result = json.dumps(dict(type= "FeatureCollection",features = prods))
return HttpResponse(result, content_type = "application/json")
try:
product = catalog_models.Product.objects.get(active = True, slug = pr_slug, category__slug = cat_slug)
except:
raise Http404
settings = Settings.get_singleton()
object = product
favorite = False
try:
prods = request.session['favorites_products']
except:
request.session['favorites_products'] = []
request.session.save()
prods = ""
if product.id in prods:
favorite = True
return render(request, 'catalog/product.html', locals())
def get_filters(request):
if request.is_ajax():
cat = request.POST.get("cat", "").strip(" \n\t")
if cat:
category = catalog_models.Category.objects.get(id = int(cat))
else:
return HttpResponse(json.dumps({"error":1,"message":"Заданной категории не обнаружено"}), content_type = "application/json")
products = catalog_models.Product.get_products(category)
filters = catalog_models.Product.get_filters(products, request.GET, category)
filters = catalog_models.NameAttr.render_catalog_filters(filters)
return HttpResponse(json.dumps({"error":0,"message":"","filters":filters}), content_type = "application/json")
Код представлений модуля “Контент”
from django.shortcuts import render
from . import models
from django.http import Http404
from utils import utils
from django.template.loader import get_template
from site_settings.models import Settings
from service_catalog.models import Service
import re
from navigation.models import HeaderMenu
from django.http import Http404, HttpResponse
import json
def get_heading(request, slug):
try:
heading = models.Heading.objects.get(slug = slug)
except:
raise Http404
if request.GET.get("ajax", "") == "Y":
PAGES = models.Page.objects.filter(heading = heading)
try:
page = request.GET.get("page", 1)
except:
page = 1
pagin = utils.pagination(PAGES,page, 6)
if pagin:
PAGES = pagin.items
PAGINATION_STR = get_template("page/pagination.html").render({'PAGIN':pagin})
object = heading
pages = models.Page.render_items(PAGES)
return HttpResponse(json.dumps({'pages':pages, 'pagination':PAGINATION_STR,}), content_type = "application/json")
headings = models.Heading.get_headings()
PAGES = models.Page.objects.filter(heading = heading)
try:
page = request.GET.get("page", 1)
except:
page = 1
pagin = utils.pagination(PAGES,page, 6)
if pagin:
PAGES = pagin.items
PAGINATION_STR = get_template("page/pagination.html").render({'PAGIN':pagin})
object = heading
return render(request, 'page/pages.html', locals())
#list pages
def news(request):
if request.GET.get("ajax", "") == "Y":
PAGES = models.Page.get_all_news()
try:
page = request.GET.get("page", 1)
except:
page = 1
pagin = utils.pagination(PAGES,page, 6)
if pagin:
PAGES = pagin.items
PAGINATION_STR = get_template("page/pagination.html").render({'PAGIN':pagin})
pages = models.Page.render_items(PAGES)
return HttpResponse(json.dumps({'pages':pages, 'pagination':PAGINATION_STR,}), content_type = "application/json")
PAGES = models.Page.get_all_news()
####
headings = models.Heading.get_headings()
try:
page = request.GET.get("page", 1)
except:
page = 1
pagin = utils.pagination(PAGES,page, 6)
if pagin:
PAGES = pagin.items
PAGINATION_STR = get_template("page/pagination.html").render({'PAGIN':pagin})
all_tab = True
object = {}
object['get_title'] = "Новости"
object['get_seo_title'] = Settings.get_seo_title_template().replace("||NO||", "Новости")
object['get_meta_description'] = Settings.get_meta_description()
object['get_meta_keywords'] = Settings.get_meta_keywords()
object['generate_breadcrumps'] = (("/", "Главная"),("/pages/", "Полезные статьи"))
return render(request, 'page/pages.html', locals())
###sort by position
def sortPosition(value):
return value.position*(-1)
#show page
def get_news(request, slug):
try:
page = models.Page.objects.get(active = True, slug = slug)
except:
raise Http404
headings = models.Heading.get_headings()
object = page
contents = []
texts = page.text_blocks.all()
contents += list(texts)
contents += list(page.file_blocks.all())
contents += list(page.headers_line.all())
contents += list(page.certificates.all())
contents += list(page.minisliders.all())
contents += list(page.bigsliders.all())
contents += list(page.citatas.all())
contents += list(page.galerris.all())
contents += list(page.tables.all())
contents += list(page.videos.all())
contents.sort(key = sortPosition)
return render(request, 'page/page.html', locals())
Схема базы данных модуля “Каталог”
Схема базы данных модуля “Каталог”
Размещено на Allbest.ru
Подобные документы
Компоненты приложения Vue.js, использование шаблона MVVM. Характеристика Webpack и фреймворка NuxtJs. Python как язык программирования, модель MVC, компоненты и инструментарий фреймворка Django. Технология программирования Object Relational Mapping.
контрольная работа [296,4 K], добавлен 22.03.2017Технология разработки веб–ориентированных систем. Выбор языка программирования, фреймворка и СУБД. Создание сайта в виде текстового форума с функцией оповещения о важных новостях по почте. Выбор хостинга, доменного имени и размещение его в Интернет.
курсовая работа [1,9 M], добавлен 10.11.2015Предметная область и проектирование сайта: определение потенциальных пользователей, информационные направления сайта (контент, дизайн, навигация, web-формы). Разработка сайта и дополнительные технические сведения: web-server и СУБД, CMS и хостинг.
курсовая работа [637,4 K], добавлен 18.06.2012Функциональное назначение, обоснование необходимости WEB-сайта, технические требования. Структурная схема системы, выбор языка программирования и программных средств. Перенос сайта на хостинг, регистрация на поисковиках. Тестирование на кроссбраузерность.
дипломная работа [4,9 M], добавлен 18.12.2011Случаи использования PHP фреймворка. Обзор современных фреймворков. Выбор фреймворка для разработки сайта. Поддержка баз данных и сообщества. Model View Controller архитектура. Скорость развития фреймворка. Наличие встроенных javascript-библиотек.
курсовая работа [1,8 M], добавлен 31.05.2012Вопросы реализации шаблона типового сайта диссертационного совета СевКавГТУ. Разработка базы данных для шаблона сайта с помощью фреймворка Django и Aptana Studio 3. Обоснование требований к техническому обеспечению. Расчет цены программного продукта.
дипломная работа [2,5 M], добавлен 26.09.2012Разработка проекта веб-сайта для медицинского центра, предоставляющего платные услуги. Анализ целевой аудитории создаваемого сайта как информационного ресурса. Навигация сайта, описание профилей пользователей и алгоритмов их взаимодействия с системой.
курсовая работа [1,9 M], добавлен 13.12.2014Назначение информационно-новостного сайта. Структура пользовательской и административной частей. Эмулятор Web–сервера Denwer 3. Типы данных, используемые в PHP. MySQL база данных. Каскадная таблица стилей CSS. Язык гипертекстовой разметки документов HTML.
дипломная работа [2,0 M], добавлен 05.02.2013Анализ состояния использования сайтов сайтостроения в профессиональном образовании. Особенности сайта училища. Обсуждение аудитории, схемы поведения пользователей. Требования к содержимому и внешнему виду сайта. Модульная сетка, навигация, каналы связи.
дипломная работа [3,3 M], добавлен 07.02.2014Анализ методов разработки сайта с помощью веб-инструментов, конструктора, системы управления сайтом. Выбор языка веб-программирования, графического редактора. Разработка корпоративного сайта, его внедрение в интернет и тестирование на различных браузерах.
курсовая работа [2,5 M], добавлен 22.03.2017