LinkedIn YouTube Facebook
Szukaj

Wstecz
Artykuły

Aplikacja Django korzystająca z API DRF – get()

Dziś zapraszamy na temat nieco mniej elektroniczny, a bardziej programistyczny. Dominik Bednarski zaprezentuje, w jaki sposób we frameworku sieciowym Django, z wykorzystaniem REST API można korzystać z funkcji get(). Pokaże też praktyczny przykład aplikacji pobierającej i wyświetlającej dane z sieci.

Więcej artykułów na Blogu IntHou

Wyobraźmy sobie – opowiada Dominik – że skończyliśmy prace nad naszym API lub też API jest stworzone w takim stopniu, że może być wykorzystane przez zewnętrzne aplikacje. W związku z powyższym kolejnym krokiem, jaki warto poznać, jest korzystanie z REST API stworzonego przy pomocy Django Rest Framework, poprzez zwykłą aplikację w Django. Warto w tym miejscu zaznaczyć, że przy takiej architekturze mamy w pełni oddzieloną warstwę przechowywania danych od warstwy interfejsu użytkownika.

Aplikacja Django korzystająca z API DRF – get()

W celu uproszczenia zagadnienia, gdzie aplikacja będzie korzystała z REST API, postanowiłem, aby obydwie części należały do tego samego projektu, w związku z czym, nie musimy tworzyć nowego projektu Django od nowa.

Jeżeli chcecie dowiedzieć się więcej na temat szablonów, to zachęcam do zapoznania się z pozostałymi wpisami o Django, które znajdują się na blogu inthou.pl.

W pierwszej kolejności stwórzmy szablon html o nazwie base.html.

<!doctype html>
<html lang="en">

  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
    <link rel="shortcut icon" href="#" />
    <title>REST API APP!</title>
  </head>
  <body>
    <div class="d-flex flex-column flex-md-row align-items-center p-3 px-md-4 mb-3 bg-white border-bottom shadow-sm">
      <h5 class="my-0 mr-md-auto font-weight-normal">REST API APP</h5>
    </div>

    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
    {% block content %}{% endblock %}
  </body>
</html>

W drugim kroku utworzymy kolejny plik html o nazwie home.html, który będzie rozszerzał plik base.html. W pliku tym będę zamieszczał wyniki pracy. Taka struktura szablonów ma celu oddzielenie części kodu, która będzie się zmieniała od części kodu, która jest stała. 

{% extends 'restapiapp/base.html' %}

{% block content %}

<div class="container">

</div>

{% endblock %}

Teraz stwórzmy prostą funkcję widoku, która będzie renderowała szablon home.html. i wykorzystywała do tego dane ze słownika context.

def home(request):

context = {}

return render(request, 'restapiapp/home.html', context)

Następnie stwórzmy ścieżkę, która połączy adres URL z funkcją nowo stworzonego widoku. 

urlpatterns = [

path('admin/', admin.site.urls),

# API

path('api/authors/', views.AuthorList.as_view()),

path('api/books/', views.BookList.as_view()),

path('api/borrows/', views.BorrowList.as_view()),

path('api/borrows/<int:pk>/', views.BorrowRetrieveDestroy.as_view()),

path('api/borrows/<int:pk>/return/', views.BorrowReturnBookUpdate.as_view()),

path('api/borrows/<int:pk>/edit/', views.BorrowRetrieveUpdate.as_view()),

path('api/user/create', views.UserCreate.as_view()),

path('api/user/login', views.UserTokenList.as_view()),

path('api/activate/<int:pk>/<str:s>', views.UserAccountActivation.as_view()),

# DRF

path('api-auth/', include('rest_framework.urls')),

# APP

path('', views.home, name='home'), # new

]

Na chwilę obecną może sprawdzić, czy strona ładuje się poprawnie.

Gdy wszystko do tej pory działa poprawnie, wówczas możemy przejść do właściwej części tego zadania. W pierwszej kolejności do pliku zawierającego widoki views.py zaimportujmy moduł requests.

import requests

Do słownika context dodajmy nowy klucz ‘authors‘ i przypiszmy do niego wynik następującej funkcji requests.get(‘http://127.0.0.1:8000/api/authors/’).json(). Pod tym linkiem znajdziecie więcej informacji o module requests

def home(request):

context = {}

context['authors'] = requests.get('http://127.0.0.1:8000/api/authors/').json()

return render(request, 'restapiapp/home.html', context)

Następnie, aby zobaczyć wynik naszego zapytania, w szablonie home.html wywołajmy zmienną authors.

{% extends 'restapiapp/base.html' %}

{% block content %}

<div class="container">

{{ authors }}

</div>

{% endblock %}

Sprawdźmy jak prezentuje się nasza strona.

Jak możemy zobaczyć, dane prezentowane są w formacie json

Teraz pójdziemy o krok dalej i wykonamy kolejne zapytanie do serwera API, aby otrzymać listę książek. Listę tę przypiszemy do klucza w słowniku o nazwie books.

def home(request):

context = {}

context['authors'] = requests.get('http://127.0.0.1:8000/api/authors/').json()

context['books'] = requests.get('http://127.0.0.1:8000/api/books/').json()

return render(request, 'restapiapp/home.html', context)

Zmodyfikujmy teraz szablon i wyświetlmy zawartość zmiennej books

{% extends 'restapiapp/base.html' %}

{% block content %}

<div class="container">

{{ authors }}

<br><br><br><br>

{{ books }}

</div>

{% endblock %}

Sprawdźmy wynik naszej pracy.

Obecnie nie posiadamy już ograniczenia w postaci danych zwracanych tylko z jednego zapytania do API. Oznacza to, że widoki stron / aplikacji mogą zawierać dane z wielu różnych zapytań.

Teraz możecie zadawać sobie pytanie, jak dostać się do konkretnych danych w ciągu w formacie json. Jeżeli mamy zwracaną listę, to do konkretnych elementów wystarczy, gdy po kropce po prostu dodamy liczbę. W ten sposób ograniczymy się do jednego zestawu danych (można powiedzieć – jednego rekordu).

{% extends 'restapiapp/base.html' %}

{% block content %}

<div class="container">

{{ authors }}

<br><br><br><br>

{{ books }}

<br><br>

{{ books.0 }}

</div>

{% endblock %}

Sprawdźmy, jak teraz wygląda strona.

Efekt jest coraz lepszy, lecz co zrobić, aby wydobyć jedynie tytuł. W tym celu ponownie musimy zastosować kropkę i wpisać interesujący nas klucz. W tym przypadku będzie to title.

{% extends 'restapiapp/base.html’ %}

{% block content %}

<div class=”container”>

{{ authors }}

<br><br><br><br>

{{ books }}

<br><br>

{{ books.0 }}

<br><br>

{{ books.0.title }}

</div>

{% endblock %}

Ponownie sprawdźmy efekt tej modyfikacji:

Obecnie wiemy jak poruszać się po otrzymanych zbiorach danych. Sprawdźmy teraz, co się stanie, jak będziemy chcieli pobrać listę pozycji wypożyczonych borrows

def home(request):

context = {}

context['authors'] = requests.get('http://127.0.0.1:8000/api/authors/').json()

context['books'] = requests.get('http://127.0.0.1:8000/api/books/').json()

context['borrows'] = requests.get('http://127.0.0.1:8000/api/borrows/').json()

return render(request, 'restapiapp/home.html', context)

Zmodyfikujmy odpowiednio plik home.html

{% extends 'restapiapp/base.html' %}

{% block content %}

<div class="container">

{{ authors }}

<br><br><br><br>

{{ books }}

<br><br>

{{ books.0 }}

<br><br>

{{ books.0.title }}

<br><br><br><br>

{{ borrows }}

</div>

{% endblock %}

I sprawdźmy, co się stanie: 

W tej chwili otrzymaliśmy informację, że nie jesteśmy uwierzytelnieni. Uwierzytelnianie może odbywać się na dwa sposoby. Możemy dodać do aplikacji system logowania, lecz tę funkcjonalność już pokazywałem w poprzednich wpisach a z drugiej strony, gdy stworzymy oddzielną aplikację to metoda logowania, będzie bezużyteczna.

Do dalszej części artykułu autor zaprasza na blog InThou

Dominik Bednarski jest absolwentem Politechniki Warszawskiej, gdzie studiował elektrotechnikę na wydziale elektrycznym ze specjalnością Elektronika Przemysłowa. Jego hobby to m.in. programowanie w C, C++ oraz Pythonie. W swojej karierze zawodowej pracował nad: algorytmem poziomu naładowania ogniw litowo-jonowych, algorytmem sterowania 6 osiowym ramieniem robota, algorytmem sterowania platformą mobilną, rozwiązaniem do rejestrowania czas pracy narzędzi maszyn na tagu RFID. Obecnie Dominik pracuje jako tester automatyzujący w firmie Sii dla klienta z branży motoryzacyjnej.