Instant Django простая разработка на django под windows

В статье "Instant Django easy django development for windows"автор объясняет основные принципы работы с фреймворком Django на примере сайта Chicagocrime

Введение

Django - это web-Фреймворк с открытым исходным кодом, написанный на языке программирования Python . Он был создан разработчиками в одной из газет в Lawrence, Kansas , и предназначался для облегчения многих трудностей, связанных с созданием функциональных, наращиваемых и поддерживаемых динамических web-сайтов.

В отличие от большинства проектов с открытым исходным кодом, Django имеет отличную документацию , которая активно поддерживается основными разработчиками. Двое из разработчиков также написали Django Book , которую опубликовало издательство Apress , и которая находится в свободном доступе в сети.

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

Я думаю, что данный сайт будет выполнять немного иную роль, предоставив введение в фреймворк Django для начинающих - как я - что является простым для понимания и интересным для чтения. Этот сайт является лишь введением, позволяя читателям ознакомиться с Django до того как они решат потратить свое время и энергию, для изучения работы данного фреймворка.

В каждой главе мы будем создавать web-сайт с помощью Django, подробно излагая все проделанные шаги. Так как я не очень сведущ в этой теме, мы рассмотрим технологию самых популярных сайтов, которые уже существуют, и выполним их в Django. Например, в первой главе мы создадим упрощенный клон Chicagocrime , это популярный web-сайт, отображающий  Google-карты преступлений в городе Чикаго.

Не требует установки

Новички в Django часто считают его установку трудной, поэтому я создал простой автономный  Django setup, работающий под Windows. Согласно моим тестам, он успешно работает с Windows XP и Windows 2000, а также согласно сообщениям пользователей и под Windows Vista. Он не требует установки и даже может быть запущен с USB-флэшки. Скачиваемый файл представляет собой самораспаковывающийся zip-архив. После закачки, двойной щелчок мыши распакует архив в папку под названием Django .

Установка Django в режиме standalone включает Python, Django, и несколько утилит для упрощения работы. Установка запускается двойным щелчком по файлу start.bat , который может быть найден в корне директории Django .

Чтобы Python и Django работали корректно, необходимо временно изменить некоторые переменные в среде Windows. Сделанные изменения необходимо вернуть после выхода. Если на вашем компьютере уже установлен Python, у вас могут возникнуть временные проблемы при использовании режима standalone. Если так произойдет, просто перезагрузите ваш компьютер. При использовании режима standalone не требуется вносить изменения в окружение ОС.

Договоренности

Образцы кода в этой статье отображаются в том виде, как если бы читатели использовали Django в режиме standalone. Если Вы установили Django самостоятельно, то вводимый вами код должен быть очень похож на тот, который приведен в образцах, и должен легко переводиться в вашу среду.

На этом сайте, команды, вводимые в командную строку, будут появляться со следующим цветом фона и начертанием шрифта:

django-admin startproject crimemap

Результат команд будет отображаться со следующим цветом фона и начертанием шрифта:

Validating models...

Примеры исходного кода будут иметь следующий вид:

from django.db import models

class Article(models.Model):
headline = models.CharField(max_length=100, default='Default headline')
pub_date = models.DateTimeField()

def __str__(self):
return self.headline

Оговорка

Я не программист. У меня нет знакомых в проекте Django, и я никогда не встречался ни с кем из разработчиков. Я не очень хорошо знаю Python. Я не профессионал в HTML, DHTML, XHTML, CSS, или Javascript. Я никогда не создавал web-сайты для клиентов, не выступал на конференциях по web-разработкам, и не публиковал соответствующие статьи о каком-либо респектабельном web-сайте.

А еще я ненавижу джаз.

Я действительно интересуюсь построением динамических web-сайтов. После оценки различных вариантов имеющихся в настоящее время я решил попробовать Django и Python. По ходу изучения фреймворка я делаю заметки и в результате получился этот сайт. Если вы ищите экспертную оценку Django, то вы не найдете ее здесь.

Я хорошо знаю, что существуют другие фреймворки и языки программирования. Возможно, у вас возникнет желание сказать мне, чем конкретный фреймворк или язык превосходит Python и Django. Пожалуйста, не надо этого делать. Это наводит меня на последнее заключение:

Этот сайт может содержать фактические, эстетические и моральные ошибки. Он будет усеян грамматическими, пунктуационными и орфографическими ошибками. Я могу случайно оскорбить людей, с которыми я лично не знаком, и сделать широкий ряд утверждений о вещах, о которых я практически ничего не знаю.

На этом сайте нет никаких гарантий, и фактически он может повредить вашей вашему намерению стать Django- разработчиком. Итак, Вы предупреждены.

Если вам все еще интересно, читайте дальше.

Карта преступности

Сайт Chicagocrime был создан в 2005, и был одним из первых web-сайтов, предназначенных для наложения пользовательской информации на карту Google. Сегодня эти web-сайты обычно называют "гибридными" (mashups). Этот web-сайт создал Adrian Holovaty ,  один из основных разработчиков Django. Верстку и дизайн сайта осуществил Wilson Miner , который помог создать дизайн интерфейса администрирования Django

Сайта Chicagocrime больше нет в сети, он был заменен на сайт Everyblock, но мне удалось перехватить следующий screenshot прежде, чем его удалили:

chicago crime

Давайте проигнорируем то, как выглядит этот сайт, а сконцентрируемся на данных, которые он представляет пользователю.

Весьма очевидно, что основной единицей данных для этого сайта является "преступление". Доступна конкретная информация о каждом преступлении, и она используется, чтобы позволить пользователю сузить результаты отображения на карте. Мы можем вообразить, какой должна быть база данных для этого web-сайта. Как минимум нам необходимо отслеживать следующие данные для каждого преступления:

  • Дата
  • Тип Преступления
  • Широта
  • Долгота
  • Адрес (улица)

Этот список не является всеобъемлющим, но вы видите, что, если Вы хотите, чтобы пользователь смог увидеть двадцать последних убийств в Чикаго, то вам необходимо знать тип каждого преступления, чтобы из базы данных были отобраны только убийства. Вам также необходимо будет знать дату каждого преступления, чтобы выбрать самые недавние преступления из базы данных и расположить их в правильном порядке. Для нанесения места каждого  преступления на карту Google, вам необходимо знать широту и долготу. Если мы хотим, чтобы пользователь увидел преступление, совершенное на определенной улице, то мы должны знать точный почтовый адрес данного преступления.

Написание кода

Теперь, когда мы знаем, какие типы данных мы будем отслеживать, мы можем начать писать код для нешего приложения. Откройте каталог Django, и дважды щелкните по файлу start.bat . Появится окно консоли. В зависимости от того, куда вы сохранили программу на ваш компьютер, ваша командная строка может отличаться от той, которую вы видите ниже. Например, если вы скопировали файл на USB устройство, с маркировкой "диск Е ", то ваша командная строка будет выглядеть следующим образом:

E:\Django\>

При использовании фреймворка Django часто бывает удобнее объединять сайты, которые мы создаем в проекты и приложения . В проекте находятся важные базы данных и настройки конфигурации, тогда как приложение реализует функциональность сайта. Часто сайт состоит из одного проекта с нескольких приложений. В нашем примере, мы создадим проект для управления настройками для нашего сайта, и одно приложение для отражения преступления на карте Google.

Наберите следующее в командной строке, и затем нажмите ввод:

django-admin startproject crimemap

Команда должна завершиться через несколько секунд. Был создан новый каталог под названием crimemap . Давайте зайдем в этот каталог, введя следующее:

cd crimemap

cd - это команда DOS для смены каталога . Теперь в командной строке отобразиться то, что вы перешли в недавно созданный каталог:

E:\Django\crimemap

Чтобы увидеть файлы, созданные командой startproject , наберите следующее:

dir

dir - это команда DOS для каталога , которая отображает его содержимое. Вы увидите следующие файлы:

manage.py
__init__.py
settings.py
urls.py

Эти файлы были созданы с помощью Django, после того, как мы выполнили команду startproject , и они являются основными файлами, необходимыми большинству проектов. Settings.py это файл где хранятся все базы данных нашего проекта и параметры настройки. Manage.py это утилита, которую мы будем использовать из командной строки, которая поможет нам обновить, запустить, диагностировать и проверить наш проект. Файл urls.py позволяет нам наносить на карту конкретные URL для конкретных функций python, извлекая информацию из URL-адресов и передавая извлеченную информацию вызываемой функции. Мы поработаем с этим файлом позже в этой главе.

Теперь перейдем к файлу settings.py . Я включил текстовый редактор notepad++ в автономной среде Django. Notepad + + представляет собой полнофункциональный текстовый редактор с открытым исходным кодом, который является прекрасным средством при редактировании исходного кода python, javascript, html, и почти любого другого формата файлов.  Для того чтобы запустить редактор и начать редактирование файла settings.py , введите следующую команду:

notepad++ settings.py

Откроется текстовый редактор notepad++, с загруженным файлом settings.py . По всему файлу находятся поучительные комментарии, на прочтение которых вам следует потратить время.

Python 2.5 имеет встраиваемый движок баз данных SQlite, который мы будем использовать для проектов в этом учебном разделе. Проекты Django могут также использовать другие базы данных, типа Postgres, Mysql, и Oracle.

Измените раздел баз данных вашего файла settings.py , так чтобы он выглядел следующим образом:

DATABASE_ENGINE = 'sqlite3'
DATABASE_NAME = 'crime.db'
DATABASE_USER = ''
DATABASE_PASSWORD = ''
DATABASE_PORT = ''

Изменения, которые Вы только что сделали, указывают Django, что Вы хотите использовать движок баз данных sqlite3 для проекта crimemap . Django также получит название базы данных для использования. Для движка баз данных sqlite3 не нужно имени пользователя или пароля.

Сохраните изменения в файле, и выйдите из notepad++.

Наше Приложение

Мы создали наш проект и определили базу данных. Теперь нам предстоит создать приложение для сохранения данных о преступлениях и их отображения. В командной строке DOS наберите следующее:

python manage.py startapp mapper

Эта команда должна завершиться быстро. Если Вы снова отобразите в виде списка контент каталога crimemap , Вы увидите подкаталог с именем картограф, который только что был создан командой startapp .

Перейдите в директорию mapper , и отобразите контент каталога:

cd mapper
E:\django\crimemap\mapper>dir

Вы увидите следующие файлы:

models.py
views.py
__init__.py

Эти файлы были созданы командой startapp , и они являются основными файлами, необходимые для приложения. Models.py - это место, где наше приложение будет хранить данные. Views.py - это место, откуда по нашему определению будут вызываться функции python, когда потребуется конкретные URL, как определено в файле urls.py в нашем проекте.

Мы рассмотрим URL и views позже в этой главе.  А пока, давайте изменим файл models.py

notepad++ models.py

Вы увидите следующее:

from django.db import models

# Create your models here.

Очевидно, что здесь нам придется потрудиться самим. Потому что только мы знаем за каким типом данных, мы следим в нашем приложении.

Команда from django.db import models позволяет использовать Django ORM. В Django нам нравится думать о наших данных как об объектах, которые могут быть созданы, отсортированы или найдены. Реляционные базы данных не рассматривают данные как объекты, поэтому ORM переводит, или "отображает на карте" взаимодействие между объектно-ориентированными данными в Django и реляционными данными в базе данных .

Измените файл models.py так, чтобы он содержал следующее:

from django.db import models

class Crime(models.Model):
type = models.CharField(max_length=20)
date = models.DateField()
latitude = models.DecimalField(max_digits=8, decimal_places=6)
longitude = models.DecimalField(max_digits=8, decimal_places=6)
address = models.CharField(max_length=50)

В начале этой главы мы решили сохранять минимальную информацию в нашей базе данных для отображения на карте преступлений. Для каждого типа данных объекта, который мы хотим отслеживать, определим класс. Сначала давайте определим класс Преступления, который укажет Django как необходимо создавать объекты данного класса. Затем для каждого конкретного элемента данных в рамках наших объектов определим область. В данном случае мы определили области для хранения информации о конкретных преступлениях, которые необходимо разместить на карте Google Crime .

Скоро наша база данных будет содержать много объектов Преступлений. Каждый объект преступления будет содержать информацию о типе преступления, дату, широту, долготу и адрес. Детали каждого преступления будут отличаться, но все они будут содержать разделы, о которых мы говорили выше.

Полный список типов разделов, которые может содержать объект, можно посмотреть здесь: model-api .

В некоторые разделы необходимо внести дополнительную информацию, или аргументы, если они определены. Например, в раздел models.CharField вводят аргумент max_length , затем, чтобы Django определял предельную длину вводимвых символов для данного раздела. Список аргументов, которые могут  использоваться при определении разделов также доступно на model-api .

URLconfs и Views

Теперь, когда мы создали модель наших данных, мы должны написать правила, которые определяют и ограничивают взаимодействие пользователя с нашими данными. Django решает эту задачу путем использования URLconfs и views.

URLconf позволяет нам определить, как наш web-сайт отвечает на запрошенные пользователем URL. В нашем примере crimemap мы хотели бы, чтобы люди смогли отобразить преступления на карте Google, а также ограничить отображение преступлений на карте по определенным критериям. Ограничения, наложенные на отображаемые преступления, должны быть очевидны, и должны опираться на запросы URL. Вот пример URL, который должен отображать все преступления, которые являются убийствами:

http://www.crimemap.com/crime/homicide

А этот URL должен отображать все преступления, которые являются поджогами:

http://www.crimemap.com/crime/arson

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

http://www.crimemap.com/date/01042007

Фреймворк django включает мощное средство для обработки запросов по URL, как те, что перечислены выше. Вы просто предоставляете список регулярных выражений, для сопоставления с URL, с которыми вы хотите, чтобы имел дело ваш проект. Каждое регулярное выражение в списке связано с именем функции python, которая может быть вызвана, когда будет найдено соответствие URL этим регулярным выражениям.

Это может показаться запутанным, но все прояснится, как только мы создадим конфигурацию URL для нашего проекта crimemap. В командной строке перейдите в ваш каталог проекта crimemap:

cd ..

Если вы наберете cd .. в командной строке, то вы перейдёте в дерево папок, которое в данном случае переместило нас из подкаталога mapper в каталог crimemap .

Теперь необходимо отредактировать файл urls.py :

notepad++ urls.py

Вы увидите следующее:

from django.conf.urls.defaults import *

urlpatterns = patterns('',
# Example:
# (r'^crimemap/', include('crimemap.foo.urls')),

# Uncomment this for admin:
# (r'^admin/', include('django.contrib.admin.urls')),
)

Как и models.py , Django предоставляет нам очень ограниченные возможности, за исключением import, который открывает нам доступ к внутренним функциям, необходимым для настройки наших URL.

Давайте удалим строки, которые начинаются с # , и которые являются комментариями. Для этого измените файл следующим образом:

from django.conf.urls.defaults import *

urlpatterns = patterns('',
(r'^crime/([A-Za-z]+)', 'crimemap.mapper.views.crime_by_type'),
)

Я признаю, что это не самое лучшее в мире регулярное  выражение. Но когда от нашего проекта требуется URL, то он сравнивает его со списком предоставленных нами шаблонов URL. Если найдено совпадение, то вызывается соответствующая функция. Мы пока не задали эту функцию, но сделаем это позже.

Вызываемые функции, при совпадении запроса URL, как правило, называют views . Вернемся обратно в каталог приложения mapper , и изменим файл views.py . Вы увидите следующее :

#Create your views here.

На сей раз Django ничего не предоставляет по умолчанию. Мы знаем, что нам необходимо задать функцию под названием crime_by_type , потому что это указанная нами функция в urls.py , и она должна вызываться, если потребуется соответствующий URL.

Добавьте следующий код в views.py :

from django.shortcuts import render_to_response, get_list_or_404
from crimemap.mapper.models import Crime

def crime_by_type(request, crimeType):
crime_list = get_list_or_404(Crime, type=crimeType)
return render_to_response('crime_by_type.html', {'crime_list': crime_list})

Каждая функция view принимает, по крайней мере, один аргумент-запрос. Дополнительные аргументы предоставляются с помощью capture groups из соответствующих регулярных выражений. Если Вы посмотрите на наше регулярное выражение в urls.py , то увидите, что его часть содержится в скобках. Это capture group. Содержимое, запрашиваемого URL, которое совпадает с capture group, передаётся нашей функции view .

Например, предположим, что кто-то сделал запрос:

http://www.crimemap.com/crime/homicide

Текстовая строка homicide ловится при помощи регулярного выражения в urls.py , и передается нашей функции view. В определении функции view мы присваиваем этим фиксированным данным имя crimeType .

Наша функция создает crime_list (список преступлений), запрашивая Django вернуть все преступления, имеющие тип, соответствующий требуемому URL. Функция get_list_or_404 использует Django ORM для обращения к базе данных, и принимает два аргумента. В первом аргументе мы называем тип объектов, которые мы ищем, в нашем случае это Преступления . Во втором аргументе мы сообщаем,  какую конкретную информацию мы хотели бы сопоставить в наших объектах Преступления при генерации списка, в нашем случае это Преступление , тип которого соответствует запросу URL .

VФункция View обычно формулирует ответ, и делает это путем отправки данных в шаблон, который затем передается в web-браузер пользователя. В нашей функции view, мы берём crime_list , который только что сгенерировали, и отправляем его в шаблон под названием crime_by_type.html .

Вернитесь обратно в папку crimemap , и создайте новую папку с именем templates (шаблоны):

mkdir templates

Войдите в папку шаблоны, и начните редактировать новый текст файла crime_by_type.html :

notepad++ crime_by_type.html

Появится предупреждение, что файл crime_by_type.html ещё не существует. Окно предупреждений предоставляет вам возможность создать этот файл. Нажмите "Да". Откроется редактор notepad++ с пустым документом. Добавьте следующее:

{% for crime in crime_list %}
{{crime.longitude}},{{ crime.latitude }},{{ crime.address }},{{ crime.type }},{{ crime.date }}
{% endfor %}

Шаблоны это текстовые файлы, и могут содержать все, что обычно можно найти в исходном коде web-страницы. Кроме того, шаблоны Django могут содержать ряд пользовательских тегов и переменных , которые позволяют отправленным из view-функций данным быть интегрированными в шаблон перед отправкой пользователю.

Теги выглядят следующим образом: {% и %} . Список тегов можно найти здесь: built-in tag reference .

Переменные выглядят следующим образом {{ и }} . В вышеупомянутом примере мы отправили crime_list в шаблон из нашей функции view. Используя тег {% для ... в... %} , мы перемещаемся по списку и имеем доступ к полям каждого пункта, используя обозначение переменной. Когда мы имеем доступ к полям каждого пункта, используя обозначение переменной, возвращаемые значения заменяют теги переменных, и теги не обрабатываются.

Данные

На данном этапе у нас действительно есть функционирующий web-сайт, но нам необходимо добавить некоторые реальные данные в наш проект, чтобы продемонстрировать, как все части работают вместе. Django предоставляет удобный механизм, который позволяет нам выводить исходные данные в формате SQL. Перейдите в каталог приложения mapper , и создайте папку с именем SQL . Теперь зайдите в нее, и используя notepad++ создайте файл с именем crime.sql :

notepad++ crime.sql

Добавьте следующие строки в этот файл, затем сохраните изменения и выйдите из notepad++:

INSERT INTO mapper_crime (type, date, longitude, latitude, address) VALUES ('homicide', '2006-01-05', -78.817828, 42.904851, '17 Rapin Place');
INSERT INTO mapper_crime (type, date, longitude, latitude, address) VALUES ('homicide', '2006-04-17', -78.889458,42.897707, '155 Pennsylvania Street');
INSERT INTO mapper_crime (type, date, longitude, latitude, address) VALUES ('homicide', '2006-01-10', -78.884766,42.915257, '446 West Ferry');
INSERT INTO mapper_crime (type, date, longitude, latitude, address) VALUES ('arson', '2006-01-23', -78.849456,42.892344, '54 Grey Street');

Этот файл включает ряд SQL-запросов, управляемых Django при инициализации базы данных нашего проекта. Не беспокойтесь по поводу формата вышеупомянутых данных, просто поймите, что мы добавляем четыре преступления в базу данных нашего проекта, включая три убийства и один поджог.

Хотя мы не используем это для данного проекта, пожалуйста, обратите внимание, что одной из самых сильных черт Django является администраторский интерфейс, который предоставляет для разработчиков и администраторов сайтов простой и эффективный способ для добавления и редактирования данных в проектах Django. Фреймворк Django предоставляет нам эту эффективную возможность, которая сокращает время процесса создания сайта. Вы можете узнать дополнительную информацию об управлении сайтом в, Django Book , но знайте, что способ, с помощью которого это осуществляется, изменится в ближайшем будущем, и эти изменения пока еще не вошли в документацию.

Заключительный этап

Теперь, когда код для нашего проекта, в основном завершен, мы можем инициализировать нашу базу данных и запустить встроенный web-сервер Django для проверки нашего проекта.

Нам осталось сделать одну заключительную настройку нашего проекта. Перейдите в каталог проектов crimemap и измените файл settings.py в notepad++.

В самом конце файла settings.py , вы увидите следующее:

INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
)

Мы уже знаем, что web-сайт Django обычно, но не всегда, состоит из одного проекта и нескольких приложений. Раздел INSTALLED_APPS файла settings.py это место, где мы сообщаем Django, какие приложения мы используем в нашем текущем проекте. Фреймворк Django имеет несколько приложений, которые используются, так часто, что они были включены по умолчанию в стандартном файле settings.py .

Мы не будем использовать функциональные возможности этих приложений по умолчанию в нашем текущем проекте crimemap , так что давайте их удалим. Затем, добавим приложение mapper , которое мы создали, с тем, чтобы Django знал, что это - часть проекта crimemap . Этот раздел файла settings.py должен теперь выглядеть следующим образом:

INSTALLED_APPS = (
'crimemap.mapper',
)

Затем, найдите раздел TEMPLATE_DIRS , и сделайте следующие изменения:

TEMPLATE_DIRS = (
"./templates/"
)

Эта настройка указывает Django где расположены  файлы шаблона. Обратите внимание, что мы используем относительные пути к файлам в наших объяснениях, а вообще, вы должны использовать абсолютные пути к файлам ваших проектов Django.

Теперь наши проектные настройки завершены. Давайте инициализировать проект, выполнив следующую команду:

python manage.py syncdb

Это приведёт к следующему результату:

Creating table mapper_crime
Installing custom SQL for mapper.Crime model

При запуске команды syncdb , Django анализирует INSTALLED_APPS , чтобы определить, какие таблицы необходимо создать в базе данных. В этом случае Django найдет ссылку на наше приложение mapper , и создаст таблицы в нашей базе данных, для обработки нашей модели преступлений .

После завершения этой команды, выполните следующее действие:

python manage.py runserver :80

Команда runserver запустит webserver в Django. В командном окне вы увидите следующее:

Validating models...
0 errors found.

Django version 1.1 beta 1, using settings 'crimemap.settings'
Development server is running at http://127.0.0.1:80/
Quit the server with CTRL-BREAK

Webserver сейчас работает на порту 80. Откройте любой, на ваше усмотрение браузер, и введите следующий адрес:

http://localhost/crime/arson

Вы увидите следующее сообщение:

-78.849456,42.892344,54 Grey Street,arson,2006-01-23

Это не так много, но мы почти завершили наш проект. Мы успешно приняли URL-запрос от web-браузера и передали его функции view. Наша функция view обратилась с запросом к базе данных, используя данные, полученные от нашего URL-запроса, чтобы сузить результаты. Эти результаты были, затем отображены на экране через шаблон, который мы создали.

Единственное, что осталось сделать, это изменить наш шаблон, поскольку той информации, которую мы посылаем шаблону, уже достаточно для отображения точек на карте Google.

Закройте сервер, нажав одновременно кнопки Ctrl и Break . Зайдите в каталог шаблонов , и используя notepad++ измените файл crime_by_type.html ,  удалив его контент и добавив следующее :

<html style="height:100%;">
<head>
<title>Buffalo Crime Map</title>
<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;" type="text/javascript">
</script>
</head>

<body onload="" onunload="GUnload()" style="height:100%;padding:0;margin:0;">
<script type="text/javascript">
var map_long = -78.820000;
var map_lat = 42.938000;
var map_zoom = 5;
var crimes = [{% for crime in crime_list %}[{{crime.longitude}},{{ crime.latitude }},'{{ crime.address }}','{{ crime.type }}','{{ crime.date }}']{% if not forloop.last %},{% endif %}{% endfor %}];
</script>

<div id="map" style="height:100%;width:100%;">
</div>

<script type="text/javascript">
function addCrimeMarker(lng, lat, address, crime_type, crime_date) {
var markerpt = new GPoint(lng, lat);
var marker = new GMarker(markerpt);
var html = '<b>' + crime_type + '</b><br>' + address + '<br>' + crime_date;
GEvent.addListener(marker, "click", function() { marker.openInfoWindowHtml(html); });
map.addOverlay(marker);
}

if (GBrowserIsCompatible()) {
var map_div = document.getElementById("map");
var map = new GMap2(map_div);

map.addControl(new GSmallMapControl());
map.addControl(new GMapTypeControl());

var pt = new GLatLng(top.map_lat, top.map_long);
map.setCenter(pt, 17 - top.map_zoom);

if (crimes) {
for (var i=0; i < crimes.length; i++) {
addCrimeMarker(crimes[i][0], crimes[i][1], crimes[i][2], crimes[i][3], crimes[i][4]);
}
}
}
</script>

</body>
</html>

Этот обучающий курс не может охватить Google Maps API  или javascript, но посмотрите внимательнее на шаблон и вы увидите, что мы используем теги и переменные , для получения данных от нашей базы данных в массив javascript, который используется для размещения маркеров на карту. Посмотрите на следующий раздел, который была повторно отформатирован для лучшей удобочитаемости:

var crimes = [ 
{% for crime in crime_list %}
[{{crime.longitude}},
{{ crime.latitude }},
'{{ crime.address }}',
'{{ crime.type }}',
'{{ crime.date }}']
{% if not forloop.last %},{% endif %}
{% endfor %}
];

Стало очень похоже на шаблон, который мы создали ранее в этой главе. Есть некоторые изменения форматирования, чтобы вывод был правильным javascript, и есть дополнительный тег, который помогает обрабатывать последний элемент списка по-разному. Результат обработки наших тегов и переменных подставляется в шаблон, который использует его как JavaScript-массив.

Сохраните изменения, внесенные в шаблон, а затем перезагрузите сервер с помощью команды runserver , как мы делали раньше. Теперь вернитесь в браузер, и загрузите следующий адрес еще раз:

http://localhost/crime/arson

Теперь вы увидите карту Google с единственным маркером. Этот маркер находится со стороны поджогов в нашей базе данных. Теперь пробуйте следующий URL:

http://localhost/crime/homicide

Здесь вы увидите карту Google с тремя маркерами, на месте убийств в нашей базе данных.

Для выхода из окна командной строки, сначала выйдите из сервера, а затем наберите следующее:

exit

Вас спросят, хотите ли Вы завершить пакетное задание. Вам необходимо лишь ответить Да для закрытия окна.

Статический Контент

Статический контент - это какая-либо информация на вашей web-странице, которая остается неизменной каждый раз, когда она предоставляется пользователю. Изображения, таблицы стилей, и javascript-библиотеки обычно являются  статическими.

Фреймворк Django не предназначен для обслуживания статического контента, оставляя эту работу webserver, который используется в производственной среде. Django предназначен для создания динамического контента, поэтому его использование для статического контента может быть медленным и ненадежным.

Несмотря на недостатки использования Django для работы со статическим контентом, часто возникает необходимость так сделать во время разработки. Начиная с того момента как в Django стал использоваться Django development server, появилось несколько трюков, которые мы должны знать, для обслуживания статических файлов.

Нам необходимо будет внести изменения в наш шаблон, url-конфигурацию, и настройки файла, чтобы все заработало.

Давайте начнем с шаблона. Запустите Instant Django, и зайдите в каталог вашего шаблона. Измените файл crime_by_type.html так, чтобы он содержал следующее:

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>Buffalo Crime Map</title>
<link rel=Stylesheet href="http://localhost/static/style.css" type="text/css">
<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;" type="text/javascript"></script>
<script src="http://localhost/static/cVerticalMapTypeControl.js"></script>
</head>

<body onload="" onunload="GUnload()">

<script type="text/javascript">
var map_long = -78.820000;
var map_lat = 42.938000;
var map_zoom = 5;

var crimes = [{% for crime in crime_list %}[{{crime.longitude}},{{ crime.latitude }},'{{ crime.address }}','{{ crime.type }}','{{ crime.date }}']{% if not forloop.last %},{% endif %}{% endfor %}];
</script>
<div id="map"></div>

<script type="text/javascript">
function addCrimeMarker(lng, lat, address, crime_type, crime_date) {
var markerpt = new GPoint(lng, lat);
var marker = new GMarker(markerpt);
var html = '<b>' + crime_type + '</b><br>' + address + '<br>' + crime_date;
GEvent.addListener(marker, "click", function() { marker.openInfoWindowHtml(html); });
map.addOverlay(marker);
}

if (GBrowserIsCompatible()) {
var map_div = document.getElementById("map");
var map = new GMap2(map_div);

var pos1 = new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(19,170));
map.addControl(new GSmallMapControl(),pos1 );
var pos2 = new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(7,90));
map.addControl(new cVerticalMapTypeControl(), pos2);

var pt = new GLatLng(top.map_lat, top.map_long);
map.setCenter(pt, 17 - top.map_zoom);

if (crimes) {
for (var i=0; i < crimes.length; i++) {
addCrimeMarker(crimes[i][0], crimes[i][1], crimes[i][2], crimes[i][3], crimes[i][4]);
}
}
}
</script>


<div id="banner" class="mapElement">
<div id="bannerInner">
<p><b>Buffalo</p><img src="http://localhost/static/buffalo.png"><p>Crime</b></p>
</div>
</div>

<div id="nav">
<h4>Crimes</h4>
<ul class="ul-cat">
<li><a href="http://localhost/crime/homicide/">Homicide<a></li>
<li><a href="http://localhost/crime/drugs">Drugs</a></li>
<li><a href="http://localhost/crime/prostitution/">Prostitution<a></li>
<li><a href="http://localhost/crime/robbery">Armed Robbery</a></li>
<li><a href="http://localhost/crime/automobile_theft">Automobile Theft<a/></li>
<li><a href="http://localhost/crime/arson">Arson</a></li>
</ul>
</div>

<div id="footer">
<p>Nickel Cigar Publications &copy 2007.</p>
</div>

<div id="disclaimer">
<p>Not associated with the City of Buffalo or the Buffalo Police Department.<p>
</div>

</body>
</html>

Рассматривая этот шаблон можно увидеть, что мы удалили информацию о стиле, которая была заложена в HTML нашего шаблона, и теперь ссылается на статический  CSS-файл. Мы добавили некоторые дополнительные элементы, чтобы улучшить вид страницы. Мы также ссылаемся на статический javascript-файл, в котором содержится пользовательский контроллер карты Google, и статический файл изображений. Весь статический контент ссылается, используя одну и ту же базу url:

http://localhost/static/

Перейдите из директории шаблонов в директорию crimemap . Теперь создайте папку с именем static . Войдите в эту папку и создайте новый файл с именем style.css . Добавьте следующее в этот файл:

* {
padding:0;
margin:0;
}

html, body {
height: 100%;
font-family: arial, sans-serif;
font-size: 12px;
}

h4 {
font-size: 14px;
border-bottom: 1px solid black;
}

a{
text-decoration: none;
color: black;
}

a:hover{
text-decoration: underline;
}

#map {
height: 100%;
width: 100%;
}

#banner {
position: absolute;
top: 7px;
left: 7px;
width: 5em;
}

#bannerInner {
border-style: solid;
border-color: white rgb(176, 176, 176) rgb(176, 176, 176) white;
border-width: 1px;
background-color: white;
text-align: center;
}

#bannerInner p{
margin: 2px;
}

#nav{
position: absolute;
top: 7px;
right: 7px;
width: 207px;
background-color: white;
color: black;
border: 1px solid black;
}

#nav h4, #datenav h4{
margin: 5px;
}

#nav ul, #datenav ul{
margin-top: 10px;
list-style: none;
}

#datenav{
position: absolute;
top:200px;
right:7px;
width:207px;
background-color:white;
border: 1px solid black;
}

#footer{
font-size: 10px;
font-weight: bold;
background-color: white;
border: 1px solid black;
position: absolute;
right: 7px;
width: 207px;
bottom: 65px;
}

#footer p{
margin: 3px;
}

#disclaimer {
font-size: 10px;
font-weight: bold;
background-color: white;
position: absolute;
bottom: 30px;
right: 7px;
width: 207px;
border: 1px solid black;
}

#disclaimer p{
margin: 3px;
}

.mapElement {
border: 1px solid black;
position: absolute;
background-color: white;
text-align: center;
cursor: pointer;
}

.ul-cat {
list-style: none;
margin:0px 0px 25px 5px;
padding:0px;
}
.ul-cat li{
margin: 0px;
padding: 3px 0px 2px 22px;
}
.ul-cat li.selected{
background: url(mini-nav-right.gif) no-repeat left 4px;
}

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

Теперь создайте новый файл, с именем cVerticalMapTypeControl.js , и добавьте в него следующее:

function cVerticalMapTypeControl() {
}
cVerticalMapTypeControl.prototype = new GControl();

cVerticalMapTypeControl.prototype.initialize = function(map) {
var cvmptc_ = this;

var container = document.createElement("div");
container.style.position = 'absolute';

var mapButtonContainerDiv = document.createElement("div");
this.setButtonContainerStyle(mapButtonContainerDiv);
var mapButtonDiv = document.createElement("div");
this.setSelectedButtonStyle(mapButtonDiv);
mapButtonContainerDiv.style.top = '0em';
container.appendChild(mapButtonContainerDiv);
mapButtonContainerDiv.appendChild(mapButtonDiv);
mapButtonDiv.appendChild(document.createTextNode("Map"));
GEvent.addDomListener(mapButtonDiv, "click", function() {
map.setMapType(G_NORMAL_MAP);
cvmptc_.setSelectedButtonStyle(mapButtonDiv);
cvmptc_.setUnSelectedButtonStyle(satelliteButtonDiv);
cvmptc_.setUnSelectedButtonStyle(hybridButtonDiv);
});

var satelliteButtonContainerDiv = document.createElement("div");
this.setButtonContainerStyle(satelliteButtonContainerDiv);
var satelliteButtonDiv = document.createElement("div");
this.setUnSelectedButtonStyle(satelliteButtonDiv);
satelliteButtonContainerDiv.style.top = '2em';
container.appendChild(satelliteButtonContainerDiv);
satelliteButtonContainerDiv.appendChild(satelliteButtonDiv);
satelliteButtonDiv.appendChild(document.createTextNode("Satellite"));
GEvent.addDomListener(satelliteButtonDiv, "click", function() {
map.setMapType(G_SATELLITE_MAP);
cvmptc_.setSelectedButtonStyle(satelliteButtonDiv);
cvmptc_.setUnSelectedButtonStyle(mapButtonDiv);
cvmptc_.setUnSelectedButtonStyle(hybridButtonDiv);
});


var hybridButtonContainerDiv = document.createElement("div");
this.setButtonContainerStyle(hybridButtonContainerDiv);
var hybridButtonDiv = document.createElement("div");
this.setUnSelectedButtonStyle(hybridButtonDiv);
hybridButtonContainerDiv.style.top = '4em';
container.appendChild(hybridButtonContainerDiv);
hybridButtonContainerDiv.appendChild(hybridButtonDiv);
hybridButtonDiv.appendChild(document.createTextNode("Hybrid"));
GEvent.addDomListener(hybridButtonDiv, "click", function() {
map.setMapType(G_HYBRID_MAP);
cvmptc_.setSelectedButtonStyle(hybridButtonDiv);
cvmptc_.setUnSelectedButtonStyle(mapButtonDiv);
cvmptc_.setUnSelectedButtonStyle(satelliteButtonDiv);
});

map.getContainer().appendChild(container);
return container;
}

cVerticalMapTypeControl.prototype.getDefaultPosition = function() {
return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(90,7));
}

cVerticalMapTypeControl.prototype.setButtonContainerStyle = function(div) {
div.style.border = '1px solid black';
div.style.position = 'absolute';
div.style.backgroundColor = 'white';
div.style.textAlign = 'center';
div.style.width = '5em';
div.style.cursor= 'pointer';
}

cVerticalMapTypeControl.prototype.setSelectedButtonStyle = function(div) {
div.style.border = 'solid';
div.style.borderColor = 'rgb(176, 176, 176) white white rgb(176, 176, 176)';
div.style.borderWidth = '1px';
div.style.fontSize = '12px';
div.style.fontWeight = 'bold';
}

cVerticalMapTypeControl.prototype.setUnSelectedButtonStyle = function(div) {
div.style.border = 'solid';
div.style.borderColor = 'white rgb(176, 176, 176) rgb(176, 176, 176) white';
div.style.borderWidth = '1px';
div.style.fontSize = '12px';
div.style.fontWeight = 'normal';
}

TВышеупомянутое javascript - это код, который я написал, чтобы показать нестандартный тип управления картой. Обычные кнопки управления типами карт Google предоставляют пользователю возможность выбора отображения "Карта", "Спутник", или "Гибридная карта", с помощью  кнопок, расположенных горизонтально. В моем javascript-коде я расположил их вертикально, что на мой взгляд является более визуально привлекательным.

Наш новый шаблон и CSS ссылаются на статическое изображение:

buffalo

Сохраните это изображение в ваш каталог с именем static .

Теперь, когда мы создали статический контент и обновили шаблон, нам необходимо настроить сервер Django для работы с ним. Измените файл settings.py , установив следующие переменные:

# Absolute path to the directory that holds media.
# Example: "/home/media/media.lawrence.com/"
MEDIA_ROOT = './static/'

# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash if there is a path component (optional in other cases).
# Examples: "http://media.lawrence.com", "http://example.com/media/"
MEDIA_URL = 'static/'

Теперь у Django есть путь к статическому контенту. Мы используем простую уловку, предоставляя относительный путь вместо абсолютного для того, чтобы наш код оставался портативным.

Последнее изменение, которое нам необходимо сделать для работы со статическим контентом, находится в конфигурации нашего URL. Внесите следующие изменения в файл urls.py :

from django.conf.urls.defaults import *

urlpatterns = patterns('',
(r'^crime/([A-Za-z]+)', 'crimemap.mapper.views.crime_by_type'),
(r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root': 'static'}),
)

Мы добавили дополнительный образец, который обрабатывает запросы для статического контента. Теперь все должно работать. Запустите сервер и перейдите к:

http://localhost/crime/homicide

Теперь вы должны увидеть дополнительный контент на нашей карте, включая статические изображения, дополнительные html, стилизованные через CSS, и пользовательские кнопки, созданные нашей библиотекой javascript.

buffalo crime

Резюме

Я надеюсь, что данный материал явился кратким и интересным представлением фреймворка Django. Мы рассмотрели основные этапы создания проектов Django:

  • Определение нашей модели данных
  • Создание своей схемы URL
  • Создание кода наших view-функций
  • Разработка своих шаблонов

Вполне очевидно, что нашему проекту недостает некоторых деталей, которые сделали бы его функциональным web-сайтом, таких как: рабочая навигация, обработка ошибок и безопасность, но хорошее начало уже готово. Большая часть кода в этой главе была написана для иллюстрации основных концепций, и никоим образом не должна рассматриваться как "наилучшая практика". Например, Django имеет serialization framework который облегчает вывод javascript из ваших моделей. В нашем коде мы написали javascript вручную,  для демонстрации тегов и переменных.

Если вы хотите узнать больше о Django, загляните сюда документация , или сюда Django Book .

Пожалуйста, сообщите мне, если вы найдете  ошибки в портативной среде, или в тексте статьи.

Разное

Я еще не определился, как этот сайт будет лицензироваться. Скорее всего, я буду следовать примеру Книги о Django и реализую его как документ с открытым исходным кодом. Вы можете прочесть данную информацию, распечатать её и рассказать своим друзьям, но не присваивайте её себе и не претендуйте на её написание.

Оригинал статьи на www.instantdjango.com

Перевод КОМТЕТ komtet.ru

Вам также может помочь