Статьи

Руководство для начинающих по Django Rest Framework

Итак, вы учитесь использовать 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, я сэкономил некоторое время, создав репозиторий, содержащий приложение, в котором мы будем работать. Это простое приложение с книжной полкой, которое позволит нам хранить списки авторов и книг. Загрузите репозиторий-компаньон для этой статьи в каталог по вашему выбору, затем запустите pip install -r requirements.txt чтобы установить все зависимости. Не забудьте убедиться, что вы активировали виртуальную среду, которую мы создали на последнем шаге. После завершения установки вы сможете набрать fab runserver чтобы запустить локальный веб-сервер и открыть веб-браузер, указывающий на http://127.0.0.1:8000/ . Если вы видите список авторов на экране, тогда вы можете идти.

Если в какой-то момент вы не получаете ожидаемых результатов, попробуйте переключить ветку вашего локального репозитория на final, чтобы увидеть результаты: git checkout final .

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 .

Сначала откройте 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 действительно!

Сериализатор умен … когда мы указываем, какую модель он должен сериализовать во внутреннем метаклассе, он знает все об этой модели … свойства, длины, значения по умолчанию и так далее. Обратите внимание, что мы не определяем ни одно из свойств, найденных в модели непосредственно в сериализаторе, мы только указываем, какие поля должны быть возвращены 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>

До сих пор наше приложение было только для чтения. Пришло время начать сохранять некоторые данные. Откройте 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 есть нечто большее, чем несколько битов, которые мы смогли охватить, но я надеюсь, что вы найдете это полезным для вашего следующего применения.