Итак, вы учитесь использовать Django Web Framework и вам это нравится. Но вы хотите привлекательный, простой в использовании API для вашего приложения? Смотрите не дальше, чем Django Rest Framework (DRF). DRF — мощный, сложный и удивительно простой в использовании. Он предлагает привлекательную версию вашего API с возможностью просмотра в Интернете и возможность возврата необработанного JSON. Django Rest Framework обеспечивает мощную сериализацию модели, отображает данные с использованием стандартных представлений на основе функций или обеспечивает гранулярность с мощными представлениями на основе классов для более сложной функциональности. Все в полностью REST-совместимой оболочке. Давайте копаться в.
Укладка фундамента
При работе с приложениями Python всегда полезно изолировать вашу разработку в виртуальной среде. Он помогает предотвращать конфликты версий между библиотеками, которые вам нужны в вашем приложении, и библиотеками, которые вы, возможно, уже установили на своем компьютере, упрощает установку зависимостей в виртуальном окружении с помощью файла needs.txt и, наконец, делает возможным совместное использование среды разработки с другие разработчики совсем несложно.
У Tuts + есть два отличных видео о том, как установить virtualenv и virtualenvwrapper . Потратьте несколько минут, чтобы просмотреть эти видео, чтобы установить virtualenv и virtualenvwrapper на вашем компьютере. Если они уже установлены, пропустите следующий раздел.
Настройка вашей виртуальной среды
Первое, что мы сделаем в рамках нашего приложения, — это установим виртуальную среду. Введите следующие команды в вашем терминале.
1
2
|
$ mkvirtualenv drf
$ workon drf
|
При выполнении этих команд не имеет значения, где вы находитесь в файловой системе. Все файлы virtualenv хранятся в централизованном месте и активируются по требованию.
Установка приложения Django
Поскольку эта статья не о самом Django, я сэкономил некоторое время, создав репозиторий, содержащий приложение, в котором мы будем работать. Это простое приложение с книжной полкой, которое позволит нам хранить списки авторов и книг. Загрузите репозиторий-компаньон для этой статьи в каталог по вашему выбору, затем запустите pip install -r requirements.txt
чтобы установить все зависимости. Не забудьте убедиться, что вы активировали виртуальную среду, которую мы создали на последнем шаге. После завершения установки вы сможете набрать fab runserver
чтобы запустить локальный веб-сервер и открыть веб-браузер, указывающий на http://127.0.0.1:8000/
. Если вы видите список авторов на экране, тогда вы можете идти.
Если в какой-то момент вы не получаете ожидаемых результатов, попробуйте переключить ветку вашего локального репозитория на final, чтобы увидеть результаты: git checkout final
.
Fab? Что это?
Fab == Fabric , бегунок задач Python . Из документов:
«Fabric — это библиотека Python (2.5 или выше) и инструмент командной строки для оптимизации использования SSH для развертывания приложений или задач системного администрирования».
Хотя более полное обсуждение Fabric выходит за рамки данной статьи, я реализовал несколько основных команд fab, которые немного облегчают работу с этим приложением. Вы видели команду fab runserver
. Также есть команда fab shell
которая вызывает интерактивную оболочку iPython в контексте приложения, и команда fab syncdb
которая запускает команду Django syncdb
для синхронизации изменений в моделях с базой данных.
Работа с сериализацией
Одна из мощных функций Django Rest Framework — это встроенная в сериализацию модель. С помощью всего лишь нескольких строк кода вы можете составить мощные представления ваших данных, которые могут быть представлены в различных форматах. Как упоминалось ранее, наше приложение будет простым приложением с книжными полками, с авторами и книгами. Я уже создал модели Author
и Book
для вас, поэтому откройте /app/bookreview/models.py
. В локальной базе данных SQLite уже хранится несколько авторов, поэтому давайте откроем интерактивную оболочку для нашего приложения и поэкспериментируем. Перейдите в окно терминала, убедитесь, что вы находитесь в каталоге ./app
и введите следующую команду.
1
|
$ fab shell
|
После загрузки оболочки введите следующие несколько строк, чтобы получить запись Author из базы данных, которая, как оказалось, принадлежит мне. Какое совпадение. ?
1
2
3
4
5
6
7
8
|
$ from bookreview.models import Author
$ author = Author.objects.get(pk=1)
$ author.id
> 1
$ author.first_name
> u’Andy’
$ author.last_name
> u’Matthews’
|
Точно так же вы можете извлечь все записи Author из базы данных другой командой:
1
2
3
4
|
$ from bookreview.models import Author
$ authors = Author.objects.all()
$ authors
> [<Author: Andy Matthews>, <Author: China Mieville>, <Author: Neil Gaiman>, <Author: Veronica Roth>, <Author: Suzanne Collins>, <Author: Brandon Sanderson>, <Author: Rick Riordan>, <Author: Phillip K. Dick>, <Author: John Scalzi>, <Author: Jesse Petersen>]
|
К сожалению, это не возвращает данные, которые может понять вызов AJAX. Итак, давайте добавим сериализатор для авторов. Закройте оболочку, набрав quit
и откройте bookreview/serializers.py
. Введите или вставьте следующие несколько строк кода и сохраните файл.
1
2
3
4
5
6
7
|
class AuthorSerializer(serializers.ModelSerializer):
«»»
Serializing all the Authors
«»»
class Meta:
model = Author
fields = (‘id’, ‘first_name’, ‘last_name’)
|
Не внося никаких изменений, сериализатор дает нам немного энергии. Вернитесь в оболочку и давайте рассмотрим.
1
2
3
4
5
6
|
$ from bookreview.models import Author
$ from bookreview.serializers import AuthorSerializer
$ author = Author.objects.get(pk=1)
$ serialized = AuthorSerializer(author)
$ serialized.data
> {‘id’: 1, ‘first_name’: u’Andy’, ‘last_name’: u’Matthews’}
|
Давайте добавим еще несколько строк кода и посмотрим, что наш API покажет нам в браузере после того, как наши данные AuthorSerializer
через наш новый AuthorSerializer
.
Изучаем веб-браузер API
Сначала откройте bookreview/urls.py
и добавьте следующую строку сразу после маршрута index_view
:
1
|
url(r’^authors/$’, views.AuthorView.as_view(), name=’author-list’),
|
Затем откройте bookreview/views.py
и добавьте эти строки в конец файла:
1
2
3
4
5
6
|
class AuthorView(generics.ListAPIView):
«»»
Returns a list of all authors.
«»»
model = Author
serializer_class = AuthorSerializer
|
Затем обязательно добавьте импорт для AuthorSerializer
вверху страницы:
1
|
from bookreview.serializers import AuthorSerializer
|
Представлением по умолчанию для Django Rest Framework является APIView. Это позволяет вам определять ваши собственные методы get
, put
и delete
. Это хороший способ получить базовую функциональность, но при этом иметь контроль над конечным результатом. В нашем случае, однако, мы позволяем DRF выполнять тяжелую работу за нас, расширяя ListAPIView. Нам просто нужно предоставить несколько битов информации, чтобы позволить DRF соединять части. Мы даем ему модель Author
чтобы он знал, как общаться с базой данных, и AuthorSerializer
чтобы DRF знал, как вернуть информацию. Мы будем работать только с некоторыми из встроенных APIViews, но вы можете прочитать обо всех опциях на веб-сайте Django Rest Framework.
Теперь, когда вы внесли эти изменения, убедитесь, что сервер запущен, введите fab runserver
введите URL-адрес http://127.0.0.1:8000/authors/
. Вы должны увидеть привлекательную страницу представления API, содержащую список всех авторов в базе данных.
Теперь, когда у нас есть представление API авторов, попробуйте нажать на этот URL с помощью команды curl
:
1
2
|
$ curl http://127.0.0.1:8000/authors/
> [{«id»: 1, «first_name»: «Andy», «last_name»: «Matthews»},…, {«id»: 10, «first_name»: «Jesse», «last_name»: «Petersen»}]
|
Довольно шикарно, а?
Дать авторам несколько книг!
Хотя это представление API довольно изящно, оно работает с базой данных один на один. Давайте добавим наше представление API, составив более сложный набор данных для авторов, включив список всех их книг. Откройте bookreview/serializers.py
и добавьте следующую строку кода перед определением класса AuthorSerializer
.
1
2
3
4
5
6
7
|
class BookSerializer(serializers.ModelSerializer):
«»»
Serializing all the Books
«»»
class Meta:
model = Book
fields = (‘id’, ‘title’, ‘isbn’)
|
Прежде чем мы сможем добавить книги в AuthorSerializer
, мы должны сериализовать Книги. Это должно выглядеть совершенно знакомым для вас. Поскольку он почти идентичен AuthorSerializer
, мы не будем его обсуждать.
Затем добавьте следующую строку сразу после строки AuthorSerializer
класса AuthorSerializer
:
1
|
books = BookSerializer(many=True)
|
Затем добавьте books
в свойство fields внутреннего мета-класса AuthorSerializer
:
1
|
fields = (‘id’, ‘first_name’, ‘last_name’, ‘books’)
|
Перезагрузите /authors/
конечную точку, и теперь вы увидите список книг для каждого автора. Неплохо только для нескольких строк кода, а?
Хороший парень DRF действительно!
Используйте SerializerMethodField для создания пользовательских свойств
Сериализатор умен … когда мы указываем, какую модель он должен сериализовать во внутреннем метаклассе, он знает все об этой модели … свойства, длины, значения по умолчанию и так далее. Обратите внимание, что мы не определяем ни одно из свойств, найденных в модели непосредственно в сериализаторе, мы только указываем, какие поля должны быть возвращены API в свойстве fields
.
Поскольку DRF уже знает о свойствах модели, нам не нужно повторяться. Если бы мы хотели, мы могли бы явно BookSerializer
и добавить следующие строки … и DRF был бы таким же счастливым.
1
2
|
title = serializers.Field(source=’title’)
isbn = serializers.Field(source=’isbn’)
|
Метод serializers.field
позволяет вам указывать на существующее свойство модели, source
поле, и позволяет явно назвать его как-то еще при возврате его конечному пользователю. Но как насчет serializers.SerializerMethodField
? Это позволяет вам создать собственное свойство, которое не связано напрямую с моделью, содержимое которой является результатом вызова метода. В нашем случае мы собираемся вернуть URL, который содержит список мест, куда вы могли бы пойти, чтобы купить книгу. Давайте добавим этот пользовательский метод сейчас.
Сразу после строки документации BookSerializer
добавьте следующую строку:
1
|
search_url = serializers.SerializerMethodField(‘get_search_url’)
|
Затем после class Meta
определения класса BookSerializer
добавьте следующие строки:
1
2
|
def get_search_url(self, obj):
return «http://www.isbnsearch.org/isbn/{}».format(obj.isbn)
|
Затем, наконец, нам нужно добавить наше новое свойство в список полей. Изменить это:
1
|
fields = (‘id’, ‘title’, ‘isbn’)
|
к этому:
1
|
fields = (‘id’, ‘title’, ‘isbn’, ‘search_url’)
|
Перезагрузите /authors/
конечную точку, и теперь вы должны увидеть URL, возвращающийся вместе с другой информацией о книге.
Добавление конечной точки автора
У нас уже есть список авторов, но было бы неплохо, чтобы у каждого автора была своя собственная страница … точно так же, как MySpace, верно? Добавим конечную точку API для просмотра одного автора. Откройте urls.py
и добавьте следующую строку после маршрута author-list
:
1
|
url(r’^authors/(?P<pk>[\d]+)/$’, views.AuthorInstanceView.as_view(), name=’author-instance’),
|
Затем откройте views.py
и добавьте следующие строки после класса AuthorView
:
1
2
3
4
5
6
7
|
class AuthorInstanceView(generics.RetrieveAPIView):
«»»
Returns a single author.
Also allows updating and deleting
«»»
model = Author
serializer_class = AuthorSerializer
|
Щелкните по одному из имен авторов на странице индекса, и вы увидите загрузку страницы экземпляра автора.
Рефакторинг на победу!
Сейчас самое время провести небольшой рефакторинг. Поскольку Django предлагает опцию именования ваших маршрутов, мы можем ссылаться на маршрут под этим именем. Это избавляет нас от необходимости создавать URL вручную. Откройте templates/index.html
и поменяйте местами следующий фрагмент:
1
|
<a href=»/authors/{{author.id}}/»>{{author.first_name}} {{author.last_name}}</a>
|
с этой линией
1
|
<a href=»{% url ‘author-instance’ author.id %}»>{{author.first_name}} {{author.last_name}}</a>
|
Сохранение данных: пусть DRF работает на вас!
До сих пор наше приложение было только для чтения. Пришло время начать сохранять некоторые данные. Откройте templates/index.html
и добавьте следующие строки под заголовком Authors:
1
2
3
4
5
|
<form action=»{% url ‘author-list’ %}» method=»post»>
<input type=»text» name=»first_name» />
<input type=»text» name=»last_name» />
<input type=»submit» value=»Add Author» />
</form>
|
DRF не то, ЧТО волшебное … или это?
Откройте views.py
, измените класс, который AuthorView
расширяет с generics.ListAPIView
на generics.ListCreateAPIView
. Затем попробуйте еще раз. Boom! Вы автор! А ваш учитель физкультуры в четвертом классе сказал, что вы никогда ничего не достигнете. Но что он знал, ему приходится целый день обходить потные носки. Вернитесь на главную страницу автора, чтобы увидеть ваше имя в огнях.
Что сейчас произошло? Используемое нами представление API по умолчанию разрешало только запросы GET
к конечной точке авторов. Изменив его на ListCreateAPIView, мы сообщили DRF, что хотим также разрешить запросы POST
. Это делает все остальное для нас. Мы могли бы так же легко определить наш собственный метод post
в AuthorView
и сделать там некоторые дополнительные вещи. Это может выглядеть так:
1
2
|
def post(self, *args, **kwargs):
import pdb;
|
Имейте в виду, что, хотя DRF обеспечивает целостность базы данных на основе свойств модели, мы не устанавливаем какой-либо вид безопасности для доступа к этой форме или ее использования. Углубление в области безопасности, входа в систему и управления разрешениями выходит за рамки этой статьи, но достаточно сказать, что DRF имеет функциональность, позволяющую получить доступ к представлениям, с которыми вы работали, и настроить их довольно просто.
Заканчивать
Теперь вы узнали довольно много о Django Rest Framework: как реализовать API для просмотра в Интернете, который может возвращать вам JSON, как настроить сериализаторы для составления и преобразования ваших данных и как использовать представления на основе классов для абстрагирования стандартный код.
У DRF есть нечто большее, чем несколько битов, которые мы смогли охватить, но я надеюсь, что вы найдете это полезным для вашего следующего применения.