Simplifying your Django Frontend Tasks with Grunt

grunt-logoGrunt is a powerful task runner with an amazing assortment of plugins. It’s not limited to the frontend, but there are many frontend-oriented plugins that you can take advantage of to combine and minify your static media, compile sass and less files, watch for changes during development and reload your browser automatically, and much more.

In the last several years, the amount of tooling around frontend development has expanded dramatically. Frameworks, libraries, preprocessors and postprocessors, transpilers, template languages, module systems, and more! Wiring everything together has become a significant challenge, and a variety of build tools have emerged to help ease this burden. Grunt is the current leader because of its fantastic plugin community, and it contains a wide array of plugins that can be very valuable to a Django developer. Today I’m going to talk about an easy way to integrate Grunt with Django’s runserver, and highlight a few plugins to handle common frontend tasks that Django developers often deal with.

Installing Grunt

Grunt uses Node.js, so you’ll need to have that installed and configured on your system. This process will vary depending on your platform, but once it’s done you’ll need to install Grunt. From the documentation:

 

This will put the grunt command in your system path, allowing it to be run from any directory.

Note that installing grunt-cli does not install the Grunt task runner! The job of the Grunt CLI is simple: run the version of Grunt which has been installed next to a Gruntfile. This allows multiple versions of Grunt to be installed on the same machine simultaneously.

Next, you’ll want to install the Grunt task runner locally, along with a few plugins that I’ll demonstrate:

 

Managing Grunt with runserver

There are a few different ways to get Grunt running alongside Django on your local development environment. The method I’ll focus on here is by extending the runserver command. To do this, create a gruntserver command inside one of your project’s apps. I commonly have a «core» app that I use for things like this. Create the «management/command» folders in your «myproject/apps/core/» directory (adjusting that path to your own preferred structure), and make sure to drop an __init__.py in both of them. Then create a «gruntserver.py» inside «command» to extend the built-in.

In your new «gruntserver.py» extend the built-in and override a few methods so that you can automatically manage the Grunt process:

 

A barebones grunt config

To get started with Grunt, you’ll need a barebones «Gruntfile.js» at the root of your project to serve as your config.

 

Combining static media

A common task for the frontend, and one that we often use complex apps for in Django, is combining and minifying static media. This can all be handled by Grunt if you like, avoiding difficulties sometimes encountered when using an integrated Django app.

To combine files, use the concat plugin. Add some configuration to the «grunt.initConfig» call, using the name of the task as the key for the configuration data:

 

This will combine all Javascript files under «myproject/static/app/js» into one file called «myproject/build/static/js/app.js». It will also combine all Javascript files under «myproject/static/vendor» into one file called «myproject/build/static/js/lib.js». You’ll likely want to refine this quite a bit to pick up only the files you want, and possibly build different bundles for different sections of your site. This will also work for CSS or any other type of file, though you may be using a preprocessor to combine your CSS and won’t need this.

You’ll probably want to use this along with the «watch» plugin for local development, but you’ll use the «uglify» plugin for deployment.

Minifying static media

Once your app is ready for production, you can use Grunt to minify the JavaScript with the uglify plugin. As with concatenation, minification of your CSS will likely be handled by your preprocessor.

This task should be run as part of your deploy process, or part of a pre-deploy build process. The uglify config will probably be very similar to your concat config:

 

The main difference is that uglify takes the new-style «files» option instead of the classic «src» and «dest» options that concat uses.

Compiling Sass

You can compile Sass with Compass using the compass plugin, but I prefer to use the speedier sass plugin that uses libsass. Here’s an example that includes the Foundation library:

 

Compiling Less

Less is compiled using the less plugin.

 

Watching for changes and live reloading

Now that you’ve got your initial operations configured, you can use the watch plugin to watch for changes and keep the files up to date. It also will send livereload signals, which you can use to automatically refresh your browser window.

 

Note the way the task is specified in the «sass» watch config. Calling «sass:dev» instructs it to use the «dev» config block from the «sass» task. Using «sass» by itself as the name of the task would have invoked both «sass:dev» and «sass:deploy» from our configuration above.

Also note how we’re using a top-level «options» definition here to make livereload the default. You can then override that for an individual watch definition if you don’t need livereload for that one.

In order for the browser to make use of the livereload signals, we’ll need to add a <script> tag that retrieves code from the livereload server that Grunt starts in the background. In Django, you’ll want to hide this tag behind a DEBUG check.

 

You can also use a LiveReload browser extension instead.

More to come

Grunt is a fantastic tool and one that makes it easier to work with the growing set of frontend tools that are emerging. There’s a vibrant plugin ecosystem, and its capabilities are growing all the time. I’ll be covering more of those tools in the future, and I’ll be sure to include Grunt configuration for each one. Enjoy!

Brandon Konkle

MongoDB + Django

mongodbmongoDB — документо-ориентированная система управления базами данных (СУБД) с открытым исходным кодом, не требующая описания схемы таблиц. Написана на языке C++ и распространяется в рамках лицензии Creative Commons.

В последнее время становится довольно популярной и восстребованой. И вот возникла идея использовать ее в связке с фреймворком Django. Собственно о чем далее и пойдет речь.

Для решения поставленной задачи мы будем использовать приложение mongodb-engine. Данное приложение тесно связано еще с несколькими приложениями, установкой которых мы и займемся вначале.

Django-nonrel — используется для поддержки NoSQL в Django.

djangotoolbox — набор инструментов для работы с нереляционными базами данных, лишним не будет.

А теперь уже ставим и mongodb-engine:

Указываем нашу базу данных в settings:

При необходимости также можно указать host, port, user, password.

Данное приложение предоставляет два типа полей для хранения произвольных данных, не входящих в стандартную django модель.

ListField

Списки и им подобные, представление массивов в формате BSON

Вариант с указанием типа:

Данный тип поля удобно использовать для организации связи один-ко-многим:

EmbeddedModelField — используется для организации связей между моделями.

DictField

Второй тип поля DictField, который используется в BSON для обьектов.

Вариант с указанием типа:

Обновление данных

Можно использовать для обновления оператор $set

А также функцию F()

В результате получится что то такое:

Использование низко-уровневых запросов

Если Вам не хватает возможностей Django ORM, можно использовать запросы к MongoDB минуя стандартный механизм.

raw_query() — принимает один аргумент, возвращает данные в виде стандартного Django queryset. Что хорошо для дальнейшей обработки данных.

Пример с geo данными, модель:

получим все точки рядом с конкретными координатами:

raw_update() — используется если нам недостаточно стандартных средств для обновления данных.

Модель:

использование:

В данном примере выполняется побитовое or для каждого foo в базе.

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

Ссылки:
MongoDB
mongodb-engine
GitHub

Установка Django 1.4 на хостинг NIC.RU

django-logo-positiveУстанавливаем Django:

1. Создать файл ~/.pydistutils.cfg со следующим содержимым:

2. Создать файл ~/.bashrc со следующим содержимым:

3. Создаём директории:

4. Выполняем

5. Загружаем и устанавливаем Django:

6. Проверяем версию

Таким же образом мы можем ставить и любые django-python модули.

virtualenv

На официальном сайте virtualenv в разделе «Installation» рекомендуется устанавливать virtualenv через менеджер Python-пакетов pip (командой «pip install virtualenv«). Однако далеко не всегда pip установлен в системе по-умолчанию. Я не стал исключением: команду pip система не понимает. Идем на официальный сайт и видим, что pip рекомендуется использовать в пределах виртуального окружения virtualenv. При установке virtualenv, pip устанавливается автоматически. Выходит, официальные сайты обеих программ рекомендуют устанавливать virtualenv через pip, а pip — через virtualenv.

Примечание: есть, конечно, множество других способов установки того и другого (через easy_install, скачивание deb-пакетов или python-установщиков) —  все эти способы также описаны на официальных сайтах или на чьих-то блогах. Но все-таки что-то тянет меня придерживаться рекомендуемых способов от официальных разработчиков.

Если следовать концепции виртуальных окружений — логично использовать pip в пределах virtualenv, а не глобально во всей системе. Тем более нахаляву, что и поставится он автоматически вместе с virtualenv. Значит, прежде всего нужно устанавливать virtualenv. Как?

Лучшее решение — установка из репозиториев (почему-то этот вариант не упоминается на официальном сайте virtualenv).

Python 2.x

1. Для установки virtualenv набираем в терминале:

2. Создаем папку, внутри которой будут храниться папки будущих виртуальных окружений. Лучше всего создать такую папку в пределах своей домашней директории, чтобы не было проблем с правами доступа. Пусть эта папка будет называться «projects«:

3. Создаем виртуальное окружение внутри папки projects. Пусть наше первое виртуальное окружение будет называться «project_one«.

(Аналогично могут создаваться виртуальные окружения для каких-то других проектов).

В результате внутри папки /projects/project_one/ создастся маленькая рабочая среда с папками bin/, include/, lib/, local/, содержащими минимальный «набор джентльмена» для работы — python, менеджеры пакетов pip и easy_install. Сюда же могут доставляться все необходимые пакеты, фреймворки (в том числе Django) и утилиты. В пределах каждого виртуального окружения они будут изолированы друг от друга, не оказывая никакого взаимного «паразитного» влияния.

Примечание: во многих руководствах по работе с виртуальными окружениями рекомендуется выполнять команду virtualenv с ключом —no-site-packages. Применение этого ключа позволяет создавать виртуальное окружение, изолированное от системной питоновской папки site-packages, что повышает степень автономности. Так вот в новых версиях virtualenv указывать этот ключ не обязательно, поскольку в них эта опция включена по-умолчанию.

4. Для активации нужно виртуального окружения нужно зайти в его папку («cd project_one») и выполнить следующее:

После активации командная строка изменится: перед именем пользователя появится название виртуального окружения в скобках «(project_one)имя_пользователя>@имя_компьютера ~«.

Теперь любые команды по установке пакетов (например, «pip install django«) или их удалению будут выполнятся только в пределах активированного окружения.

Для выхода из виртуального окружения и перехода в обычный режим достаточно набрать:

 

Python 3.x

 

Старт проекта на Django

Прежде всего убедитесь, что у вас подключена услуга «Поддержка Python + Django». На время разработки вам также часто будет нужен доступ по SSH, поэтому перед созданием нового Django-проекта подключите и услугу «Поддержка SSH». Если в качестве базы данных вы будете использовать MySQL, соответствующая услуга также должна быть подключена.

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


    В результате будет создана папка virtualenv/MyEnv. Вместо MyEnv вы можете выбрать и любое другое имя виртуального окружения.
  2. В рамках виртуального окружения установите свежую версию Django:pip 

    Можно установить и любую другую версию. Например, 1.0:

    Таким же образом можно установить и любые другие модули Python.
  3. Создайте папку, где будут располагаться ваши проекты. Эта папка должна находиться вне DOCUMENT_ROOT, то есть вне папок вида domains/имя_домена. Лучшим вариантом будет создать папку django рядом с директорией domains:
  4. Перейдите в папку с проектами и создайте новый проект:

    В результате будет создана папка имя_проекта со стандартным шаблоном Django-проекта.
  5. Откройте файл settings.py и измените в нем значения необходимых переменных. В качестве значения переменной STATIC_ROOT укажите

    добавив в самое начало файла строку

    Внимание! Если вы будете использовать команду syncdb через SSH, то при использовании MySQL в качестве движка баз данных в поле HOST словаря DATABASES[‘default’] обязательно нужно указать IP 127.0.0.1. Подробнее об этом здесь.

    Более подробную информацию о переменных, доступных для редактирования в settings.py, можно найти в документации Django.

  6. Если вы будете использовать mod_wsgi (предпочтительный вариант):

    В директории домена, на котором будет находиться ваш проект (domains/имя_домена) создайте файл django.wsgi и поместите в него такие строки:

    Примечание. Обратите также внимание на пятую и шестую строки этого кода: если вы в своих проектах обычно не используете имя проекта внутри оператора import (например,«from имя_приложения.models import *», а не «from имя_проекта.имя_приложения.models import *» в файле views.py), то указывать имя проекта в пятой строке нужно два раза, а во второй, наоборот, не нужно:

    Вернитесь к этому примечанию, если будете получать ошибки вида «ImportError: No module named…»

    Затем создайте в той же папке еще один файл — .htaccess — и поместите в него следующие директивы:

  7. Если вы будете использовать mod_python (не рекомендуется):

    В папке с проектами (django) создайте файл modpython_virtualenv.py с таким содержимым внутри:

    В директории домена, на котором будет находиться ваш проект (domains/имя_домена) создайте файл .htaccess и поместите в него такие строки:

    Примечание. Здесь и далее X в имени директории usersX может быть целым числом (1, 2, …) или вообще отсутствовать. Точное значение для вашего аккаунта уточняйте в разделе «Техподдержка / Техническая информация» контрольной панели аккаунта (смотрите значение параметра «Домашняя директория»).

    Позже, когда проект будет запускаться в публичную эксплуатацию, не забудьте поменять значения директив PythonDebug и PythonAutoReload на Off — это предотвратит демонстрацию отладочной информации об ошибках всем посетителям и несколько ускорит работу сайта.

    Примечание. Обратите также внимание на директивы SetEnv и PythonPath: если вы в своих проектах обычно не используете имя проекта внутри оператора import (например,«from имя_приложения.models import *», а не «from имя_проекта.имя_приложения.models import *» в файле views.py), то указывать имя проекта в директиве SetEnv не нужно, а в PythonPath, наоборот, нужно два раза:

    Кроме того, поместите файл modpython_virtualenv.py внутрь папки проекта.

    Вернитесь к этому примечанию, если будете получать ошибки вида «ImportError: No module named…»

    Далее, во всех папках в директории домена, в которых будут содержаться статические файлы (например, static), нужно также создать по файлу .htaccess с такой строкой внутри:

     

На этом установка проекта завершена. Теперь вы можете создавать приложения и приступать к разработке.

Если же в результате выполнения этих действий получаете в браузере ошибку 500, загляните в раздел «Статистика / Лог-файлы».