Wróć do katalogu
Season 44 15 Odcinki 1h 1m 2026

GeoDjango and PostGIS

v6.0 — Edycja 2026. Kompleksowy kurs audio na temat budowania przestrzennych aplikacji internetowych przy użyciu GeoDjango i PostGIS. Nagrany w 2026 roku, obejmujący GeoDjango w wersji 6.0.

Analiza geoprzestrzenna Przestrzenne aplikacje internetowe Bazy danych
GeoDjango and PostGIS
Teraz odtwarzane
Click play to start
0:00
0:00
1
Potęga przestrzennych frameworków internetowych
W tym odcinku przedstawiamy GeoDjango i PostGIS jako potężne połączenie do budowania geograficznych aplikacji internetowych. Dowiesz się, dlaczego tradycyjne bazy danych mają trudności z danymi przestrzennymi i jak rozszerzenia przestrzenne rozwiązują ten problem.
3m 55s
2
PostGIS: Geometry kontra Geography
Ten odcinek omawia typy danych w PostGIS, skupiając się w szczególności na różnicy między typami Geometry i Geography. Dowiesz się, kiedy stosować matematykę kartezjańską na płaszczyźnie, a kiedy obliczenia dla sferycznego modelu Ziemi.
4m 01s
3
Konfiguracja środowiska przestrzennego
Ten odcinek obejmuje początkową konfigurację projektu GeoDjango i PostGIS. Dowiesz się, jak włączyć rozszerzenie PostGIS i skonfigurować ustawienia Django, aby połączyć się z przestrzennym backendem.
4m 02s
4
Układy odniesienia współrzędnych i SRID
Ten odcinek szczegółowo omawia układy odniesienia współrzędnych (Coordinate Reference Systems) i SRID. Dowiesz się, czym jest WGS84 i dlaczego prawidłowe odwzorowanie danych na mapie jest kluczowe dla dokładnych pomiarów odległości.
4m 14s
5
Projektowanie modeli geograficznych
Ten odcinek pokazuje, jak projektować modele geograficzne w GeoDjango. Dowiesz się, jak definiować atrybuty PointField i MultiPolygonField, aby przechowywać dane przestrzenne w aplikacji Django.
3m 43s
6
API GDAL i OGR
Ten odcinek wprowadza wrapper API GDAL i OGR wewnątrz GeoDjango. Dowiesz się, jak badać i odczytywać zewnętrzne pliki wektorowe, takie jak Shapefile, natywnie w Pythonie przed ich zaimportowaniem.
3m 46s
7
Importowanie danych przestrzennych za pomocą LayerMapping
Ten odcinek dotyczy automatyzacji importu danych przestrzennych. Dowiesz się, jak używać narzędzia LayerMapping, aby bez wysiłku mapować zewnętrzne dane z plików Shapefile bezpośrednio do modeli GeoDjango.
4m 01s
8
API GEOS: Pythonowa geometria
Ten odcinek skupia się na API GEOS do manipulacji geometrią w stylu Pythona. Dowiesz się, jak wykonywać operacje topologiczne, takie jak sumy i przecięcia, w pamięci, bez odpytywania bazy danych.
3m 54s
9
Opanowanie przestrzennych lookupów
Ten odcinek wyjaśnia geograficzne lookupy w Django ORM. Dowiesz się, jak używać filtrów przestrzennych do znajdowania relacji, takich jak to, które punkty zawierają się w określonych granicach.
4m 19s
10
Wydajne zapytania o odległość
Ten odcinek porusza temat wydajnych zapytań o bliskość i odległość. Dowiesz się, jak używać lookupów odległości i obiektu odległości geograficznej, aby skutecznie znajdować pobliskie lokalizacje.
4m 41s
11
Geograficzne funkcje bazy danych
Ten odcinek omawia przestrzenne funkcje bazy danych dostępne przez GeoDjango. Dowiesz się, jak obliczać pola powierzchni, wyodrębniać centroidy i generować GeoJSON bezpośrednio w warstwie bazy danych.
3m 54s
12
Dane rastrowe w PostGIS
Ten odcinek wprowadza rastry PostGIS i pola RasterFields w GeoDjango. Dowiesz się, jak przechowywać i odpytywać ciągłe dane przestrzenne, takie jak modele wysokościowe czy mapy temperatur.
4m 02s
13
Geolokalizacja z GeoIP2
Ten odcinek omawia geolokalizację opartą na IP przy użyciu modułu GeoIP2 w GeoDjango. Dowiesz się, jak mapować adresy IP użytkowników na miasta i kraje przy użyciu zestawów danych MaxMind.
4m 08s
14
Testowanie aplikacji przestrzennych
Ten odcinek skupia się na testowaniu aplikacji przestrzennych w GeoDjango. Dowiesz się, jak skonfigurować zestaw testów, obsługiwać szablonowe bazy danych PostGIS i ustawiać uprawnienia użytkowników.
4m 08s
15
Wdrażanie aplikacji GeoDjango
Ten odcinek podsumowuje serię, omawiając kwestie związane z wdrażaniem aplikacji GeoDjango. Dowiesz się o bezpieczeństwie wątków w GDAL i o tym, jak skonfigurować procesy WSGI, aby zapobiec awariom.
4m 13s

Odcinki

1

Potęga przestrzennych frameworków internetowych

3m 55s

W tym odcinku przedstawiamy GeoDjango i PostGIS jako potężne połączenie do budowania geograficznych aplikacji internetowych. Dowiesz się, dlaczego tradycyjne bazy danych mają trudności z danymi przestrzennymi i jak rozszerzenia przestrzenne rozwiązują ten problem.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. GeoDjango i PostGIS, odcinek 1 z 15. Czy próbowałeś kiedyś obliczyć odległość między dwoma punktami szerokości i długości geograficznej za pomocą zwykłego SQL query? Zazwyczaj kończy się to pisaniem wielkiego, podatnego na błędy bloku trygonometrii, tylko po to, żeby sprawdzić, która kawiarnia jest najbliżej. Standardowe bazy danych po prostu nie rozumieją fizycznej przestrzeni. Wypełnienie tej luki w danych to dokładnie to, o czym powiemy dzisiaj w odcinku The Power of Spatial Web Frameworks. Ludzie często myślą, że przechowywanie danych geograficznych to po prostu dodanie dwóch kolumn typu decimal do tabeli w bazie danych – jednej na szerokość i drugiej na długość geograficzną. To powszechne nieporozumienie. Jeśli budujesz system wyznaczania tras dostaw jedzenia i musisz znaleźć restaurację najbliżej klienta, standardowa baza danych potraktuje te współrzędne jako zwykłe liczby floating-point. Nie wie, że Ziemia jest kulą. Nie potrafi wydajnie obliczać granic, przecięć ani rzeczywistych odległości. Musisz zaciągnąć tysiące rekordów do pamięci aplikacji i policzyć to wszystko samodzielnie. I tu do akcji wkracza przestrzenna baza danych. PostGIS to przestrzenne rozszerzenie dla bazy PostgreSQL. Zmienia ono same podstawy tego, jak przechowywane są dane. Zamiast dwóch osobnych kolumn liczbowych, przechowujesz pojedynczy obiekt typu geometry lub geography. Przestrzenna baza danych natywnie rozumie matematykę fizycznego świata. Wie, czym jest punkt, linia i polygon. Jeśli chcesz znaleźć wszystkie restauracje w promieniu dwóch kilometrów od użytkownika, PostGIS używa specjalistycznych indeksów przestrzennych, żeby natychmiast znaleźć odpowiedź już na poziomie bazy danych. Ale mądra baza danych to tylko połowa sukcesu. Nadal musisz połączyć tę przestrzenną logikę ze swoją aplikacją webową. I tu dochodzimy do GeoDjango. GeoDjango to światowej klasy framework geograficzny wbudowany bezpośrednio w Django. Działa jako pomost między przestrzenną bazą danych a logiką twojej aplikacji. GeoDjango rozszerza standardowy Object-Relational Mapper z Django, dzięki czemu potrafi on zrozumieć geometrię PostGIS. Pracujesz z danymi geograficznymi dokładnie tak samo, jak ze zwykłymi modelami bazy danych. Zamiast pisać surowe, przestrzenne SQL queries, używasz Pythona. Możesz filtrować wyniki z bazy danych na podstawie relacji przestrzennych, na przykład sprawdzając, czy polygon strefy dostaw restauracji zawiera konkretny punkt z adresem użytkownika. GeoDjango tłumaczy twój kod w Pythonie na odpowiednie PostGIS queries. Zawiera nawet map widgets dla panelu administracyjnego Django, dzięki czemu możesz wizualnie tworzyć i modyfikować dane geograficzne out of the box. Razem, PostGIS i GeoDjango tworzą niesamowicie potężny stack. PostGIS bierze na siebie ciężkie obliczenia matematyczne w warstwie storage, a GeoDjango zapewnia czysty interfejs w Pythonie, żeby serwować te dane twoim użytkownikom. Przestajesz walczyć ze skomplikowaną trygonometrią i zaczynasz budować prawdziwe features oparte na lokalizacji. Oto kluczowy wniosek. Prawdziwa moc przestrzennego frameworka to nie tylko rysowanie linii na webowej mapie. To całkowite przeniesienie złożonej matematyki przestrzennej z twojego kodu aplikacji do silnika bazy danych, zbudowanego specjalnie po to, by rozumieć geometrię. Jeśli te deep dives są dla ciebie przydatne, możesz wesprzeć nasz podcast, wyszukując DevStoriesEU w serwisie Patreon. To wszystko na dziś. Dzięki za wysłuchanie — idź zbudować coś fajnego.
2

PostGIS: Geometry kontra Geography

4m 01s

Ten odcinek omawia typy danych w PostGIS, skupiając się w szczególności na różnicy między typami Geometry i Geography. Dowiesz się, kiedy stosować matematykę kartezjańską na płaszczyźnie, a kiedy obliczenia dla sferycznego modelu Ziemi.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. GeoDjango i PostGIS, odcinek 2 z 15. Najkrótsza droga między dwoma punktami na Ziemi nie jest linią prostą, lecz krzywą. Jeśli twoja baza danych traktuje długość i szerokość geograficzną jak zwykłą siatkę X i Y, twoje zapytania o odległość będą całkowicie błędne. Aby to naprawić, musisz zrozumieć różnicę między typami danych Geometry i Geography w PostGIS. Domyślnie przestrzenne bazy danych działają na płaskiej, dwuwymiarowej płaszczyźnie. To jest typ Geometry. Wykorzystuje on standardową matematykę kartezjańską. Jeśli chcesz znaleźć odległość między dwoma punktami, baza danych w zasadzie rysuje prostą linię i stosuje twierdzenie Pitagorasa. To podejście jest niezwykle szybkie i bardzo precyzyjne w przypadku danych lokalnych. Jeśli mapujesz kwartał miasta, wytyczasz ściany budynku albo śledzisz dokładne granice małego parku, krzywizna Ziemi jest pomijalna. Płaska mapa działa idealnie. Developerzy często zakładają, że mogą używać typu Geometry do wszystkiego. Przechowują globalne współrzędne GPS, czyli stopnie długości i szerokości geograficznej, w płaskiej kolumnie Geometry. Kiedy proszą bazę danych o obliczenie odległości, zwraca ona bezsensowną liczbę w stopniach, a nie w metrach czy milach. Aby uzyskać rzeczywiste odległości przy użyciu typu Geometry na dużych obszarach, musisz ciągle tłumaczyć swoje dane na konkretne, lokalne projekcje map. Właśnie dlatego PostGIS udostępnia typ Geography. Typ Geography modeluje Ziemię jako kulę. Mówiąc dokładniej, natywnie wykorzystuje system odniesienia przestrzennego WGS84. Kiedy przechowujesz współrzędne w kolumnie Geography, baza danych rozumie, że powierzchnia jest zakrzywiona. Kiedy pytasz ją o odległość, nie rysuje płaskiej linii. Oblicza trasę po ortodromie. Pomyśl o mierzeniu trasy lotu z Nowego Jorku do Londynu. Jeśli użyjesz typu Geometry na standardowej, płaskiej mapie bez projekcji, baza danych obliczy prostą linię przecinającą bezpośrednio siatkę. Jeśli użyjesz typu Geography, baza danych obliczy prawdziwą, najkrótszą odległość po krzywiźnie Ziemi, wyznaczając ortodromę nad Atlantykiem. Co lepsze, typ Geography automatycznie zwraca tę odległość w metrach. Całkowicie omijasz potrzebę samodzielnego zarządzania skomplikowanymi projekcjami map. Oto kluczowy wniosek. Możesz dojść do wniosku, że Geography to lepszy typ i powinien całkowicie zastąpić Geometry. To nieprawda. Obliczanie odległości na sferze wymaga zaawansowanej trygonometrii. Wymaga to znacznie więcej mocy obliczeniowej niż matematyka na płaszczyźnie, przez co operacje na typach Geography są wolniejsze. Co więcej, PostGIS obsługuje znacznie mniej funkcji przestrzennych dla typu Geography niż dla Geometry. Wiele zaawansowanych operacji geometrycznych po prostu nie przekłada się na matematykę sferyczną. Twój wybór zależy całkowicie od fizycznego zasięgu twoich danych. Używaj typu Geography, kiedy twoja aplikacja przechowuje punkty globalnie i potrzebuje dokładnych odległości bez narzutu na zarządzanie projekcjami. Używaj typu Geometry, kiedy twoje dane są ograniczone do konkretnego, lokalnego regionu, albo kiedy potrzebujesz absolutnie maksymalnej wydajności i pełnego zestawu funkcji przestrzennych. Typ, który wybierzesz, definiuje kształt świata, w którym żyje twoja baza danych. Dzięki za spędzenie ze mną tych kilku minut. Do następnego razu, trzymaj się.
3

Konfiguracja środowiska przestrzennego

4m 02s

Ten odcinek obejmuje początkową konfigurację projektu GeoDjango i PostGIS. Dowiesz się, jak włączyć rozszerzenie PostGIS i skonfigurować ustawienia Django, aby połączyć się z przestrzennym backendem.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. GeoDjango i PostGIS, odcinek 3 z 15. Przekształcenie standardowej bazy danych w silnik przestrzenny wymaga dokładnie trzech słów SQL, ale jeśli wykonasz je w niewłaściwym kontekście, twoja aplikacja Django wywali się już przy pierwszej migracji. Dzisiaj skupimy się wyłącznie na konfiguracji środowiska przestrzennego. Zaczynamy od warstwy bazy danych. Masz już uruchomiony PostgreSQL i utworzyłeś pustą bazę danych dla swojego nowego projektu. Na tym etapie ta baza danych jest całkowicie standardowa. Rozumie tylko tekst, integery, daty i standardowe typy relacyjne. Nie ma pojęcia, czym są współrzędne czy granice geograficzne. Aby to zmienić, musisz włączyć PostGIS. Ludzie często potykają się w tym miejscu, zakładając, że instalacja pakietów PostGIS na serwerze automatycznie sprawi, że każda baza danych będzie obsługiwać dane przestrzenne. Wcale tak nie jest. Rozszerzenie przestrzenne musi zostać utworzone wewnątrz konkretnej bazy danych, z której będzie korzystał twój projekt. Musisz połączyć się bezpośrednio z tą nową bazą danych za pomocą klienta bazy danych lub z linii komend. Po połączeniu, odpalasz komendę tworzącą rozszerzenie o nazwie postgis. Te trzy słowa SQL natychmiast przekształcają środowisko. PostgreSQL wykonuje tę komendę, ładując do twojego schematu setki funkcji przestrzennych i specjalistycznych typów danych. Generuje również kluczową tabelę systemową, która przechowuje przestrzenne układy odniesienia. Dostarczają one wzorów matematycznych niezbędnych do rzutowania globalnych współrzędnych na płaski ekran. Mając przygotowaną bazę danych, przechodzisz do swojego projektu w Django. Bootstrapujesz standardowy projekt i tworzysz nową apkę. Nazwijmy tę apkę world. Teraz otwórz plik settings. Aby spiąć Django z PostGIS-em, potrzebne są dwie konkretne modyfikacje. Najpierw znajdź tablicę installed apps. Musisz dodać moduł o nazwie django dot contrib dot gis. Ten moduł to rdzeń GeoDjango. Ładuje on pythonowe wrappery dla bazowych bibliotek geograficznych, dostarczając pola przestrzenne i lookupy do geograficznej bazy danych, których użyjesz później do pisania zapytań. Do tej listy dopisujesz też swoją nową apkę world, żeby Django wiedziało, że ma śledzić jej modele. A oto kluczowa sprawa. Druga modyfikacja ma miejsce w słowniku konfiguracji bazy danych. Django kieruje cały ruch do bazy danych przez backend silnika. Jeśli zostawisz engine ustawiony na domyślny backend PostgreSQL, Django potraktuje twoją przestrzenną bazę danych jak standardową relacyjną bazę danych. Nie będzie wiedziało, jak zserializować kształt geograficzny ani bezpiecznie sparsować zapytania o bounding box. Musisz jawnie ustawić engine na backend GeoDjango PostGIS. Zmieniasz wartość engine na django dot contrib dot gis dot db dot backends dot postgis. Reszta słownika połączenia pozostaje identyczna. Nadal podajesz nazwę bazy danych, użytkownika, hasło, host i port dokładnie tak, jak w przypadku standardowej konfiguracji. Kiedy odpalasz początkowe migracje, ten nowy backend przejmuje stery. Łączy się z PostgreSQL i natychmiast sprawdza obecność rozszerzenia PostGIS. Jeśli zapomniałeś utworzyć rozszerzenie w bazie danych, backend wyłapie brakujące typy przestrzenne i rzuci błędem. Jeśli rozszerzenie jest obecne, połączenie kończy się sukcesem. Masz teraz kompletny przestrzenny pipeline. Prawdziwa moc tej konkretnej konfiguracji polega na tym, że po podpięciu backendu postgis, ogromna złożoność zapytań do przestrzennej bazy danych zostaje całkowicie ukryta za dobrze znanym maperem obiektowo-relacyjnym Django. To wszystko w tym odcinku. Dzięki za wysłuchanie i buduj dalej!
4

Układy odniesienia współrzędnych i SRID

4m 14s

Ten odcinek szczegółowo omawia układy odniesienia współrzędnych (Coordinate Reference Systems) i SRID. Dowiesz się, czym jest WGS84 i dlaczego prawidłowe odwzorowanie danych na mapie jest kluczowe dla dokładnych pomiarów odległości.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. GeoDjango i PostGIS, odcinek 4 z 15. Spróbuj zmierzyć obrys budynku za pomocą szerokości i długości geograficznej, a twoje liczby będą całkowicie bezużyteczne. To dlatego, że szerokość i długość geograficzna to po prostu kąty mierzone od środka Ziemi, a nie fizyczne odległości. Aby zamienić te kąty na użyteczne miary, takie jak metry czy stopy, potrzebujesz Coordinate Reference System i SRID. Współrzędne takie jak 48 stopni na północ i 2 stopnie na wschód to po prostu para surowych liczb. Bez kontekstu twoja baza danych nie wie, jak zmapować te liczby na fizyczny świat. Ten kontekst pochodzi z Spatial Reference System Identifier, powszechnie nazywanego SRID. SRID to po prostu integer, który łączy twoje surowe współrzędne z konkretnym matematycznym modelem Ziemi. Domyślnie pola geometryczne w GeoDjango używają SRID o wartości 4326. Ten integer reprezentuje układ współrzędnych WGS84. To standardowy model używany przez satelity GPS i większość webowych bibliotek do map. Przechowuje dane w stopniach szerokości i długości geograficznej. WGS84 świetnie nadaje się do namierzania lokalizacji w dowolnym miejscu na kuli ziemskiej. Jest to jednak system geograficzny, co oznacza, że modeluje Ziemię jako bryłę trójwymiarową. I tu pojawia się kluczowa kwestia. Nie możesz dokładnie obliczać płaskich odległości ani powierzchni używając stopni. Fizyczna odległość między dwiema liniami długości geograficznej kurczy się, gdy przesuwasz się od równika w stronę biegunów. Jeśli spróbujesz znaleźć wszystkie kawiarnie w promieniu 500 metrów od danego punktu używając SRID 4326, baza danych musi w locie wykonywać ciężką matematykę sferyczną, co jest wolne i często nieprecyzyjne. Aby to rozwiązać, używasz rzutowanych układów współrzędnych. Rzutowany układ matematycznie spłaszcza konkretny fragment zakrzywionej Ziemi na dwuwymiarowej siatce. Kiedy obszar jest już spłaszczony, współrzędne zmieniają się z kątów na standardowe jednostki długości, takie jak metry czy stopy. Dzięki temu obliczenia odległości są szybkie i dokładne przy użyciu podstawowej geometrii. Twój wybór SRID zależy całkowicie od skali twojej aplikacji. Jeśli budujesz globalny system śledzenia lotów, przechowujesz swoje dane używając WGS84 i SRID 4326. Twoje punkty obejmują cały świat, więc potrzebujesz globalnego systemu, nawet jeśli obliczenia odległości są nieco bardziej skomplikowane. Jeśli budujesz lokalną aplikację do planowania przestrzennego, żeby mierzyć dokładne granice działek, użycie WGS84 to błąd. Zamiast tego przypisujesz lokalny rzutowany układ współrzędnych do swojego pola przestrzennego. Na przykład możesz użyć konkretnego układu współrzędnych State Plane z jego własnym, unikalnym SRID. Te lokalne systemy są mocno skrojone na miarę. Minimalizują zniekształcenia, które powstają, gdy spłaszczasz kulę, ale tylko dla tej konkretnej strefy geograficznej. Kiedy konfigurujesz swoje modele w GeoDjango, definiujesz SRID bezpośrednio na polu przestrzennym. Jeśli nic nie zrobisz, domyślną wartością jest 4326. Jeśli chcesz zlokalizowanej projekcji w metrach, przekazujesz ten konkretny integer do definicji pola. GeoDjango traktuje wtedy całą geometrię w tej kolumnie zgodnie z tym konkretnym modelem matematycznym. Odpowiedni SRID gwarantuje, że twoje obliczenia odległości nie będą się zniekształcać, gdy twoje dane będą oddalać się od równika. Dzięki za wysłuchanie. Do usłyszenia następnym razem!
5

Projektowanie modeli geograficznych

3m 43s

Ten odcinek pokazuje, jak projektować modele geograficzne w GeoDjango. Dowiesz się, jak definiować atrybuty PointField i MultiPolygonField, aby przechowywać dane przestrzenne w aplikacji Django.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. GeoDjango i PostGIS, odcinek 5 z 15. Chcesz dodać dane o lokalizacji do swojej aplikacji, więc możesz pomyśleć o dodaniu do bazy danych dwóch prostych pól typu float dla szerokości i długości geograficznej. Ale takie podejście całkowicie odcina cię od zaawansowanych zapytań przestrzennych, obliczania dystansu i przecięć geometrycznych. Żeby odblokować te możliwości, potrzebujesz odpowiednich typów przestrzennych, co prowadzi nas do projektowania modeli geograficznych. Przejście ze standardowych modeli Django na modele GeoDjango wymaga tylko drobnej zmiany w twoich importach. Zamiast korzystać ze standardowych modeli bazy danych Django, importujesz modele z geograficznego modułu contrib. Ten dedykowany moduł działa jako drop-in replacement. Daje ci dostęp do wszystkich standardowych typów pól w Django, takich jak character i integer, jednocześnie płynnie wprowadzając typy przestrzenne do dokładnie tej samej definicji klasy. Weźmy scenariusz, w którym budujesz model WorldBorder do przechowywania danych o krajach. Definiujesz klasę modelu tak samo jak każdą inną. Przypisujesz pole typu character dla nazwy kraju, pole typu integer dla populacji i pole typu float dla całkowitej powierzchni. Żeby obsłużyć samą geometrię mapy, dodajesz pole geograficzne bezpośrednio obok pozostałych. Dla kraju użyjesz MultiPolygonField. O ile PointField idealnie nadaje się do przechowywania pojedynczej pary współrzędnych, na przykład dla stolicy, o tyle MultiPolygonField może reprezentować złożone granice państwowe, w tym kraje z wieloma oddzielonymi od siebie obszarami lądowymi lub wyspami. Kiedy podpinasz to pole przestrzenne do swojego modelu, pod spodem definiujesz układ współrzędnych. Każde pole geograficzne opiera się na identyfikatorze układu odniesienia przestrzennego, znanym jako SRID. SRID mówi bazie danych, jak rzutować surowe współrzędne na rzeczywisty kształt Ziemi. Jeśli nie ustawisz tej wartości jawnie, GeoDjango automatycznie przyjmie domyślny SRID 4326. Ten konkretny integer odnosi się do standardu WGS84, który jest dokładnie tym samym układem współrzędnych, jakiego używa standardowy sprzęt GPS. Jeśli twoje dane źródłowe opierają się na innej lokalnej projekcji, po prostu przekazujesz docelowy integer do parametru SRID bezpośrednio w definicji pola. I tu robi się ciekawie. Deweloperzy znający Django ORM wiedzą, że żeby kolumna była szybka do odpytania, musisz jawnie przekazać flagę database index do definicji pola. Ponieważ zapytania przestrzenne są z natury ciężkie, mógłbyś założyć, że musisz ręcznie skonfigurować specjalistyczne indeksy dla swoich kolumn z geometrią. Wcale nie musisz. Pola geograficzne w GeoDjango działają inaczej. Zawierają specjalny parametr do spatial indexing, który domyślnie jest ustawiony na true. Kiedy odpalasz migracje, GeoDjango automatycznie mówi bazie danych pod spodem, żeby zbudowała specjalistyczny spatial index. Dostajesz wysokowydajne zapytania typu bounding box i wyszukiwania przecięć geograficznych prosto z pudełka, przy zerowej dodatkowej konfiguracji. Prawdziwą siłą projektowania modeli w ten sposób jest to, że całkowicie odczarowuje to dane przestrzenne. Ogromny, złożony polygon reprezentujący kontynent staje się po prostu kolejnym property na twoim obiekcie w Pythonie, gotowym do zapisania i odpytania obok zwykłej liczby populacji. To wszystko na dziś. Dzięki za wysłuchanie — idź zbudować coś fajnego.
6

API GDAL i OGR

3m 46s

Ten odcinek wprowadza wrapper API GDAL i OGR wewnątrz GeoDjango. Dowiesz się, jak badać i odczytywać zewnętrzne pliki wektorowe, takie jak Shapefile, natywnie w Pythonie przed ich zaimportowaniem.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. GeoDjango i PostGIS, odcinek 6 z 15. Dostajesz ogromny plik przestrzenny — ESRI Shapefile lub GeoJSON — i musisz wiedzieć, jakie zawiera atrybuty. Twoim pierwszym odruchem może być instalacja ciężkiego desktopowego programu GIS, żeby tylko zajrzeć do środka. Wcale nie musisz. GeoDjango potrafi czytać te pliki natywnie, prosto w shellu Pythona, korzystając z API GDAL i OGR. Jeśli systemy informacji geograficznej to zestaw narzędzi, to Geospatial Data Abstraction Library jest uniwersalnym tłumaczem. Technicznie rzecz biorąc, GDAL obsługuje dane rastrowe, takie jak zdjęcia satelitarne, podczas gdy OGR obsługuje dane wektorowe, takie jak punkty, linie i poligony. GeoDjango dostarcza pythonowy wrapper na bibliotekę OGR, dając ci bezpośredni sposób na inspekcję niemal każdego formatu pliku wektorowego na świecie. Załóżmy, że pobrałeś plik shapefile zawierający granice wszystkich państw na świecie. Zanim napiszesz skrypt do wczytania tych danych, musisz dokładnie wiedzieć, jak są ustrukturyzowane. Zaczynasz od zaimportowania obiektu DataSource z modułu GDAL w GeoDjango. Tworzysz nowy DataSource, przekazując mu ścieżkę do twojego pliku shapefile. Ten obiekt reprezentuje teraz cały twój pobrany przestrzenny dataset. DataSource organizuje swoje informacje przestrzenne w warstwy. Możesz zapytać DataSource o liczbę jego warstw. ESRI Shapefile tradycyjnie zawiera tylko jedną warstwę, ale formaty takie jak GeoPackages mogą zawierać ich dziesiątki. Pobierasz tę pierwszą warstwę za pomocą jej indeksu, dokładnie tak samo, jak wyciągasz element ze standardowej listy w Pythonie. Oto kluczowa kwestia. To właśnie w obiekcie warstwy odbywa się właściwa introspekcja. Działa on jako kontener na pojedyncze rekordy przestrzenne, które API nazywa features. Możesz poprosić warstwę o zwrócenie całkowitej liczby jej features. W przypadku naszego pliku z granicami świata, ta liczba powinna z grubsza odpowiadać liczbie państw na Ziemi. Możesz również zapytać warstwę o jej typ geometrii. To potwierdza, czy dane składają się z punktów, linii czy poligonów. Dla granic państw, typ zazwyczaj zwróci wartość MultiPolygon. Następnie musisz wiedzieć, jakie metadane są dołączone do tych kształtów. Możesz zapytać warstwę o jej fields. Zwróci to listę stringów reprezentujących nazwy kolumn atrybutów. Możesz tam zobaczyć nazwy odpowiadające wewnętrznemu kodowi kraju, zwyczajowej nazwie i liczbie ludności. Możesz nawet zejść o jeden poziom głębiej. Uzyskując dostęp do pojedynczego feature z warstwy za pomocą jego indeksu, możesz zbadać pojedynczy kraj. Możesz zapytać ten konkretny feature o wartość jego pola ze zwyczajową nazwą. Możesz również uzyskać dostęp do obiektu geometrii tego feature'a i poprosić go o zwrócenie współrzędnych jako Well-Known Text lub GeoJSON. Właśnie zmapowałeś dokładnie, jakie kształty zawiera plik, nazwy jego atrybutów i strukturę jego rekordów. Zrobiłeś to wszystko wyłącznie z poziomu Pythona, bez pisania skryptu importującego do bazy danych ani polegania na zewnętrznym oprogramowaniu do wizualizacji. Wrapper GDAL zamienia twój standardowy shell Pythona w narzędzie do eksploracji danych przestrzennych, pozwalając ci zwalidować obce pliki, zanim pojedynczy rekord dotknie twojej bazy danych. To wszystko w tym odcinku. Dzięki za wysłuchanie i twórz dalej!
7

Importowanie danych przestrzennych za pomocą LayerMapping

4m 01s

Ten odcinek dotyczy automatyzacji importu danych przestrzennych. Dowiesz się, jak używać narzędzia LayerMapping, aby bez wysiłku mapować zewnętrzne dane z plików Shapefile bezpośrednio do modeli GeoDjango.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. GeoDjango i PostGIS, odcinek 7 z 15. Ręczny import tysięcy poligonów geograficznych i ich metadanych mógłby zająć całe dni. Twoje pliki źródłowe mają nieczytelne nazwy kolumn i niedopasowane typy, ale twoja baza danych wymaga ścisłej struktury. Rozwiązaniem jest narzędzie LayerMapping z GeoDjango, które obsługuje cały ten proces importu za pomocą dokładnie jednego słownika. Pracując z danymi przestrzennymi, często otrzymujesz pliki wektorowe, takie jak ESRI Shapefiles. Pliki te zawierają zarówno geometryczne kształty lokalizacji, jak i przypisane do nich atrybuty. Jednak zewnętrzne pliki rzadko pasują do schema twojej bazy danych. Shapefile może mieć kolumnę z populacją zapisaną w skrócie jako POP2005, a kod kraju jako ISO2. Twój czysty model Django, nazwijmy go WorldBorder, ma jasno nazwane i ściśle typowane pola dokładnie dla tych atrybutów. Możesz mieć pokusę, żeby użyć ręcznych importów SQL lub narzędzi bazodanowych takich jak pgAdmin, aby wrzucić te dane do PostGIS. LayerMapping to zupełnie inne podejście. To narzędzie, którego używasz z poziomu skryptu w Pythonie. Żyje bezpośrednio w twoim projekcie Django, łącząc zewnętrzne pliki przestrzenne prosto z twoim ORM-em. Oto kluczowa sprawa. Rdzeniem LayerMapping jest prosty słownik w Pythonie. Kluczami tego słownika są nazwy pól twojego czystego modelu Django. Wartościami są surowe stringi z nazwami atrybutów w twoim pliku źródłowym. Na przykład, twój słownik mapuje pole name z modelu Django na atrybut NAME z pliku Shapefile. Mapuje pole populacji twojego modelu na POP2005, a pole kodu ISO na ISO2. Mapujesz również pole geometrii w twoim modelu na typ geometrii pliku Shapefile, który zazwyczaj jest reprezentowany przez string taki jak MULTIPOLYGON. Aby to zautomatyzować, piszesz krótki plik w Pythonie, zazwyczaj nazywany load script. Wewnątrz tego skryptu importujesz twój model WorldBorder i narzędzie LayerMapping. Definiujesz twój słownik mapujący. Następnie tworzysz nową instancję LayerMapping. Przekazujesz do tej instancji trzy obowiązkowe rzeczy. Po pierwsze, twój model Django. Po drugie, ścieżkę do źródłowego pliku Shapefile. Po trzecie, słownik mapujący, który właśnie utworzyłeś. Możesz również podać opcjonalne argumenty, aby kontrolować zachowanie podczas importu. Jeśli twoje dane źródłowe są już dokładnie w tym samym układzie odniesienia przestrzennego, jakiego oczekuje twoja baza danych, możesz powiedzieć narzędziu, aby nie wykonywało transformacji współrzędnych. To pomija niepotrzebne obliczenia i przyspiesza import. Na koniec wywołujesz metodę save na twojej instancji LayerMapping. Kiedy wykonasz ten skrypt, narzędzie przejmuje pełną kontrolę. Otwiera Shapefile, iteruje po każdym pojedynczym obiekcie geograficznym i używa twojego słownika do dopasowania nieuporządkowanych atrybutów pliku do twoich ścisłych pól modelu. Automatycznie tłumaczy surową geometrię na format zrozumiały dla PostGIS i zapisuje rekordy w twojej bazie danych. Możesz poinstruować metodę save, aby rzuciła wyjątek przy pierwszym napotkanym błędzie, lub możesz pozwolić jej działać i po prostu logować wszystkie problematyczne obiekty w twoim terminalu. Najważniejszym wnioskiem jest to, że LayerMapping całkowicie oddziela sztywną strukturę zewnętrznych plików przestrzennych od czystego designu twojej bazy danych, pozwalając ci na import ogromnych zbiorów danych za pomocą zaledwie kilku linijek w Pythonie. Zanim skończymy, jeśli podoba ci się podcast i chcesz pomóc w jego kontynuacji, możesz nas wesprzeć, wyszukując DevStoriesEU na platformie Patreon. To wszystko w tym odcinku. Dzięki za wysłuchanie i buduj dalej!
8

API GEOS: Pythonowa geometria

3m 54s

Ten odcinek skupia się na API GEOS do manipulacji geometrią w stylu Pythona. Dowiesz się, jak wykonywać operacje topologiczne, takie jak sumy i przecięcia, w pamięci, bez odpytywania bazy danych.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. GeoDjango i PostGIS, odcinek 8 z 15. Możesz myśleć, że za każdym razem, gdy musisz połączyć dwa poligony albo znaleźć przecięcie przestrzenne, musisz napisać query i czekać na odpowiedź z bazy danych. W rzeczywistości możesz wykonywać złożone obliczenia przestrzenne bezpośrednio w Python shellu, w ogóle nie dotykając połączenia z bazą danych. Właśnie tym zajmiemy się dzisiaj: GEOS API i pythonową geometrią. Częstym błędem w myśleniu o GeoDjango jest to, że PostGIS bierze na siebie cały ciężar operacji przestrzennych. Choć PostGIS jest niesamowicie potężny, GEOS API pozwala na wykonywanie operacji geometrycznych całkowicie w pamięci lokalnej. GEOS to skrót od Geometry Engine Open Source. To mocno zoptymalizowana biblioteka w C++, ale GeoDjango daje ci potężny wrapper w postaci obiektu GEOSGeometry. Ten obiekt pozwala ci tworzyć, manipulować i analizować geometrie czysto w Pythonie. I tu robi się ciekawie. Obiekt GEOSGeometry nie sprawia wrażenia topornego wrappera na bibliotekę w C. Zachowuje się dokładnie tak, jak natywny kontener w Pythonie. Jeśli masz LineString z dziesięcioma punktami, możesz wywołać na nim standardową pythonową funkcję length, żeby zobaczyć, że ma dziesięć współrzędnych. Możesz iterować po obiekcie Polygon za pomocą standardowego for-loopa, aby wyciągnąć jego poszczególne pierścienie, albo użyć indeksu, żeby pobrać konkretny punkt z geometrii MultiPoint. Zachowują się zupełnie jak dobrze znane listy czy tuple współrzędnych. Prawdziwa moc odblokowuje się, gdy zastosujesz operacje topologiczne. Powiedzmy, że budujesz aplikację logistyczną i masz dwie nakładające się na siebie strefy dostaw, zdefiniowane jako poligony GEOS. Musisz znaleźć dokładny obszar, w którym te dwie strefy się pokrywają. Nie musisz zapisywać tych stref do modelu i odpalać query do bazy danych. Zamiast tego, możesz wygenerować ich część wspólną natychmiast w pamięci. Najpierw tworzysz instancje dwóch obiektów GEOSGeometry, reprezentujących twoje strefy dostaw. Następnie możesz po prostu wywołać metodę intersection na pierwszym poligonie, przekazując drugi poligon jako argument. Ponieważ to API jest mocno pythonowe, możesz też po prostu użyć operatora bitwise AND. Dosłownie wpisujesz poligon pierwszy, ampersand i poligon drugi. To zwraca zupełnie nowy obiekt GEOSGeometry, reprezentujący dokładnie kształt ich części wspólnej. Masz dostęp do pełnego zestawu takich operacji przestrzennych. Jeśli musisz znaleźć obszar pokryty przez pierwszą strefę dostaw, ale leżący ściśle poza drugą, używasz metody difference, albo zwykłego pythonowego operatora minus. Jeśli chcesz połączyć je w jedną wielką strefę, używasz metody union, albo operatora bitwise OR, czyli znaku pipe. Możesz nawet generować nowe kształty z niczego. Wywołanie metody buffer na geometrii punktu z argumentem width natychmiast oblicza i zwraca poligon reprezentujący idealne koło narysowane wokół tego punktu. Ponieważ wszystko opiera się na działającym pod spodem silniku w C++, te obliczenia wykonują się niezwykle szybko. Kluczowy wniosek jest taki, że GEOS API daje ci niezależny, działający in-memory silnik przestrzenny, pozwalający na walidację geometrii, obliczanie bufferów i znajdowanie przecięć, zanim choćby jeden bajt danych dotrze do twojej bazy danych. To wszystko w tym odcinku. Do usłyszenia następnym razem!
9

Opanowanie przestrzennych lookupów

4m 19s

Ten odcinek wyjaśnia geograficzne lookupy w Django ORM. Dowiesz się, jak używać filtrów przestrzennych do znajdowania relacji, takich jak to, które punkty zawierają się w określonych granicach.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. GeoDjango i PostGIS, odcinek 9 z 15. Zapomnij o pisaniu ogromnych porównań współrzędnych. Masz lokalizację użytkownika i strefę dostawy i musisz wiedzieć, czy się pokrywają. Robienie tego matematycznie oznacza sprawdzanie setek krawędzi poligonów w logice twojej aplikacji. Zamiast tego, GeoDjango sprowadza to całkowicie do operacji na bazie danych. Dzisiaj opanujemy spatial lookups. Jeśli używałeś Django, znasz składnię z podwójnym podkreśleniem do filtrowania querysetów. Do nazwy pola dodajesz coś w stylu podwójne podkreślenie exact lub podwójne podkreślenie in. GeoDjango rozszerza dokładnie tę samą składnię, aby obsługiwać złożone relacje topologiczne PostGIS. Relacje topologiczne to po prostu reguły dotyczące sposobu, w jaki geometrie współdzielą przestrzeń. Czy się stykają? Czy się nakładają? Czy jedna jest całkowicie wewnątrz drugiej? GeoDjango daje ci dedykowane typy lookupów, aby zadawać te pytania bezpośrednio w twoich zapytaniach ORM. Najczęstszym i najbardziej wybaczającym błędy spatial lookupem jest intersects. Jeśli filtrujesz pole geometrii za pomocą podwójnego podkreślenia intersects, baza danych zwraca rekordy, w których dwie geometrie współdzielą dowolną część przestrzeni. Mogą się przecinać, stykać na granicy lub jedna może całkowicie obejmować drugą. Dopóki istnieje jakakolwiek wspólna przestrzeń, intersects zwraca true. Często potrzebujesz większej precyzji niż prosta intersekcja. Potrzebujesz ścisłych granic. Tutaj do gry wchodzą contains i within. Programiści ciągle je mylą. Oto kluczowa zasada. Różnica jest czysto kierunkowa. Jeśli geometria A zawiera geometrię B, to geometria B jest wewnątrz geometrii A. Pomyśl o pudełku i szklanej kulce. Pudełko zawiera kulkę. Kulka jest wewnątrz pudełka. Wybierasz lookup na podstawie tego, która geometria znajduje się w kolumnie bazy danych, a którą przekazujesz jako argument filtra. Weźmy konkretny scenariusz. Masz tabelę w bazie danych z domami, a każdy dom ma geometrię typu point reprezentującą jego lokalizację. Miasto właśnie opublikowało nowy poligon definiujący wyznaczoną strefę powodziową. Musisz znaleźć wszystkie domy, które idealnie mieszczą się wewnątrz tego obszaru ryzyka. Nie odpytujesz strefy powodziowej, żeby sprawdzić, co zawiera. Odpytujesz domy. Wywołujesz filter na modelu domu, odwołujesz się do pola geometrii point, dodajesz podwójne podkreślenie within i przekazujesz poligon strefy powodziowej jako wartość. Kiedy wykonujesz to zapytanie, Django tłumaczy twój lookup z podwójnym podkreśleniem na wywołanie natywnej funkcji PostGIS, a konkretnie ST_Within. Silnik bazy danych przetwarza geometrie, używając swoich zoptymalizowanych indeksów przestrzennych. Sprawdza, czy każda pojedyncza współrzędna punktu domu leży wewnątrz poligonu strefy powodziowej. Jeśli dom leży dokładnie na krawędzi poligonu, nie jest uznawany za within. Ścisłe zawieranie oznacza, że wnętrze pierwszej geometrii musi znajdować się całkowicie wewnątrz wnętrza drugiej geometrii. Jeśli odwrócisz scenariusz, powiedzmy, że odpytujesz tabelę dzielnic w bazie danych, aby znaleźć tę, która otacza konkretną lokalizację użytkownika, używasz podwójnego podkreślenia contains. Filtrujesz pole poligonu dzielnicy, dodajesz podwójne podkreślenie contains i przekazujesz point użytkownika. Pod spodem logika jest identyczna, ale kolejność argumentów przestrzennych przekazywanych do PostGIS jest zamieniona. Zrozumienie tej kierunkowej logiki zapobiega cichym błędom i pustym querysetom. Mapując operacje PostGIS bezpośrednio na keyword arguments w Django, możesz wydajnie filtrować ogromne zbiory danych przestrzennych bez pisania czystego SQL-a. Geometria, po której filtrujesz, zawsze dyktuje kierunek twojego spatial lookupu. Dzięki za wysłuchanie. Do następnego razu!
10

Wydajne zapytania o odległość

4m 41s

Ten odcinek porusza temat wydajnych zapytań o bliskość i odległość. Dowiesz się, jak używać lookupów odległości i obiektu odległości geograficznej, aby skutecznie znajdować pobliskie lokalizacje.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. GeoDjango i PostGIS, odcinek 10 z 15. Zapytania typu radius to chleb powszedni aplikacji opartych na lokalizacji. Jeśli napiszesz je źle, twoja baza danych obliczy dokładną odległość do każdego wiersza w tabeli, wymuszając potężny full scan. Jeśli napiszesz je dobrze, zajmie to milisekundy. Wydajne zapytania o odległość to różnica między aplikacją, która działa błyskawicznie, a taką, która wysypuje się pod obciążeniem. Częstym błędem programistów jest myślenie o zapytaniach przestrzennych tak samo, jak o podstawowej matematyce. Naiwne podejście polega na obliczeniu dokładnej odległości od twojego punktu docelowego do każdego innego punktu w bazie danych, a następnie odfiltrowaniu wszystkiego, co przekracza twój maksymalny promień. Nigdy nie powinieneś tego robić. Obliczanie rzeczywistych odległości na sferze jest bardzo obciążające obliczeniowo. Jeśli twoje zapytanie filtruje, najpierw obliczając odległość, baza danych nie może użyć swoich indeksów przestrzennych. Jest zmuszona do sprawdzenia każdego pojedynczego wiersza. Aby zapytania były szybkie, musisz polegać na lookupach opartych na indeksach. Zanim przyjrzymy się lookupom w bazie danych, potrzebujesz sposobu na jasne wyrażenie odległości w swoim kodzie w Pythonie. GeoDjango udostępnia obiekt Distance, zazwyczaj importowany po prostu jako wielka litera D. Inicjalizujesz go jednostką i wartością. Na przykład, przekazanie argumentu m i równa się pięć do tego obiektu tworzy pomiar dokładnie pięciu mil. Możesz użyć kilometrów, metrów, a nawet stopni. To normalizuje pomiar w Pythonie, zanim zapytanie w ogóle trafi do bazy danych. Wyobraź sobie scenariusz, w którym implementujesz funkcję znajdującą wszystkie kawiarnie w promieniu pięciu mil od obecnego pingu GPS użytkownika. Masz punkt z lokalizacją użytkownika i chcesz odpytać swój model kawiarni. Mógłbyś użyć lookupu distance less-than-or-equal. Piszesz filtr zapytania, w którym po polu lokalizacji kawiarni dajesz podwójny znak podkreślenia, słowo distance, znak podkreślenia i litery l t e. Przekazujesz do niego krotkę zawierającą punkt użytkownika i twój obiekt Distance ustawiony na pięć mil. To działa. Tłumaczy się to na funkcję bazy danych, która sprawdza, czy odległość jest mniejsza lub równa pięć mil. Ale w zależności od twojego backendu przestrzennego i konfiguracji kolumn, ten lookup może nadal wykonywać więcej pracy matematycznej niż to absolutnie konieczne, obliczając dokładne odległości przed ostatecznym porównaniem. Oto kluczowa sprawa. Rzadko musisz znać dokładną odległość, aby przefiltrować promień. Musisz tylko wiedzieć, czy obiekt znajduje się wewnątrz okręgu. I tutaj lookup dwithin staje się niezbędny. Zamiast distance less-than-or-equal, dodajesz podwójny znak podkreślenia i słowo dwithin do swojego pola lokalizacji. Przekazujesz mu dokładnie ten sam punkt użytkownika i obiekt Distance o wartości pięciu mil. Pod spodem, to kieruje bezpośrednio do funkcji PostGIS ST DWithin. Ta funkcja jest wysoce zoptymalizowana. Najpierw wykonuje szybkie sprawdzenie bounding-boxa, co idealnie wykorzystuje twoje indeksy przestrzenne. Rysuje zgrubny kwadrat wokół twojego pięciomilowego promienia i natychmiast odrzuca wszystkie punkty poza tym kwadratem, bez wykonywania żadnej skomplikowanej matematyki sferycznej. Wykonuje precyzyjne, kosztowne obliczenia tylko dla tych kilku punktów, które znajdują się blisko granicy okręgu wewnątrz tego kwadratu. Jeśli twoja tabela w bazie danych używa kolumn typu geography zamiast podstawowych kolumn geometry, PostGIS automatycznie radzi sobie z krzywizną Ziemi, jednocześnie utrzymując błyskawiczne wykorzystanie indeksów. Najcenniejszym nawykiem w programowaniu przestrzennym jest uświadomienie sobie, że sprawdzenie, czy punkt znajduje się wewnątrz kształtu, jest zawsze tańsze niż wyciąganie taśmy mierniczej, aby obliczyć dokładną odległość między nimi. Dzięki za spędzenie ze mną tych kilku minut. Do usłyszenia następnym razem, trzymaj się.
11

Geograficzne funkcje bazy danych

3m 54s

Ten odcinek omawia przestrzenne funkcje bazy danych dostępne przez GeoDjango. Dowiesz się, jak obliczać pola powierzchni, wyodrębniać centroidy i generować GeoJSON bezpośrednio w warstwie bazy danych.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. GeoDjango i PostGIS, odcinek 11 z 15. Masz bazę danych pełną ogromnych, złożonych poligonów, a twój frontend musi jedynie wyświetlić pina w środku każdego z nich. Jeśli pobierzesz te surowe poligony do Pythona, żeby obliczyć ich środek, będziesz ciągnąć przez sieć megabajty bezużytecznych współrzędnych. Rozwiązaniem jest zrzucenie tej matematyki na bazę danych za pomocą Geographic Database Functions. Są dwa sposoby na wyciągnięcie informacji przestrzennych, takich jak pole powierzchni czy punkt środkowy w GeoDjango. Pierwszy to odpytanie bazy o rekord, zaciągnięcie całej geometrii do obiektu GEOS w Pythonie i odwołanie się do property takiego jak dot area. Nie rób tego, chyba że faktycznie potrzebujesz pełnej geometrii w Pythonie. Pobieranie granicy parku narodowego może oznaczać ładowanie dziesiątek tysięcy wierzchołków do pamięci tylko po to, żeby obliczyć jedną liczbę. Drugi, znacznie wydajniejszy sposób, to zlecenie PostGIS-owi obliczenia odpowiedzi i odesłania tylko końcowego wyniku. To właśnie tutaj Geographic Database Functions, w połączeniu z metodą annotate z Django ORM, stają się niezbędne. Spójrzmy na praktyczny scenariusz. Tworzysz API, które zwraca listę parków narodowych. Dla list view, aplikacja kliencka potrzebuje tylko nazwy parku, jego całkowitej powierzchni i pojedynczej współrzędnej środka, żeby rzucić pina na mapę. Nie potrzebuje złożonego poligonu granicy. W swoim Django queryset używasz metody annotate. Każesz mu utworzyć nowy atrybut, nazwijmy go park area, i przypisujesz mu wynik funkcji Area działającej na twojej kolumnie z geometrią. Obok tworzysz kolejny atrybut o nazwie center point, przypisując mu wynik funkcji Centroid na tej samej kolumnie z geometrią. Na koniec ograniczasz wynik zapytania tylko do nazwy i twoich dwóch nowych annotations. Kiedy to zapytanie się wykonuje, PostGIS odczytuje surowe dane geometryczne z dysku. Uruchamia wysoce zoptymalizowane wewnętrzne procedury, żeby obliczyć powierzchnię i znaleźć matematyczny punkt środkowy. Następnie zwraca przez sieć dokładnie trzy rzeczy do twojej aplikacji Django: string z nazwą, liczbę dla powierzchni i pojedynczą geometrię punktową dla środka. Całkowicie omijasz koszty przepustowości sieci i pamięci związane z przesyłaniem dużego poligonu. Ta strategia ma zastosowanie do wielu operacji przestrzennych. Możesz użyć funkcji Transform wewnątrz annotation, żeby przekonwertować współrzędne z projekcji w bazie danych bezpośrednio na projekcję, której potrzebuje twoja web mapa, na przykład Web Mercator. Baza danych ogarnia matematykę, zanim Python w ogóle zobaczy dane. Możesz też użyć funkcji AsGeoJSON. To instruuje PostGIS, żeby sformatował dane przestrzenne do standardowego stringa JSON bezpośrednio w bazie danych. Kiedy Django go odbiera, jest to po prostu tekst gotowy do przekazania bezpośrednio do twojego frontendu, co całkowicie pozwala uniknąć narzutu na serializację w Pythonie. Możesz też stosować funkcje agregujące na całych querysetach. Funkcja Extent analizuje grupę geometrii i zwraca pojedynczy bounding box, który obejmuje je wszystkie. Jeśli użytkownik wyszukuje wszystkie parki w danym regionie, zwrócenie Extent daje ci dokładne współrzędne potrzebne do automatycznego zooma mapy na frontendzie, żeby idealnie dopasować ją do wszystkich wyników. Oto kluczowy wniosek. Twoja przestrzenna baza danych to wysoce wyspecjalizowany silnik obliczeniowy, a nie tylko magazyn danych. Trzymaj swoje ciężkie obliczenia przestrzenne wewnątrz PostGIS i przesyłaj przez sieć do Pythona tylko obliczone odpowiedzi. To wszystko na dzisiaj. Do usłyszenia następnym razem!
12

Dane rastrowe w PostGIS

4m 02s

Ten odcinek wprowadza rastry PostGIS i pola RasterFields w GeoDjango. Dowiesz się, jak przechowywać i odpytywać ciągłe dane przestrzenne, takie jak modele wysokościowe czy mapy temperatur.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. GeoDjango i PostGIS, odcinek 12 z 15. Kształty wektorowe świetnie sprawdzają się, gdy chcesz narysować wyraźną linię wokół granicy miasta lub zaznaczyć lokalizację użytkownika. Ale co, gdy musisz zmapować coś, co nie ma ostrych granic, na przykład zmieniającą się temperaturę na kontynencie lub wysokość całego pasma górskiego? Nie możesz narysować poligonu dla każdego pojedynczego stopnia temperatury. I tu do gry wchodzą dane rastrowe w PostGIS. Jeśli jesteś przyzwyczajony do pracy z punktami, liniami i poligonami, dane rastrowe wymagają zmiany sposobu myślenia. Dane rastrowe nie składają się z odrębnych kształtów. To ciągła siatka pikseli, dokładnie jak fotografia cyfrowa. Ale zamiast wartości dla koloru czerwonego, zielonego i niebieskiego, każdy piksel przechowuje konkretną wartość liczbową. Mogą to być opady deszczu, rodzaj gleby lub wysokość. Cała siatka jest matematycznie powiązana z rzeczywistością poprzez georeferencję. Oznacza to, że baza danych dokładnie wie, gdzie znajduje się każdy piksel na mapie. W GeoDjango obsługa tych danych opiera się głównie na dwóch komponentach: RasterField i obiekcie GDALRaster. RasterField to typ kolumny w bazie danych. Dodajesz go do swojego modelu w Django dokładnie tak samo, jak pole geometryczne. To mówi PostGIS-owi, żeby wewnętrznie przydzielił miejsce na dane siatki. Ale nie wchodzisz w interakcję bezpośrednio z surowymi bajtami w bazie. Kiedy wyciągasz raster z bazy danych, albo zanim go tam wrzucisz, używasz GDALRaster. To pythonowy wrapper na niskopoziomowe biblioteki geoprzestrzenne. Pozwala ci sprawdzić właściwości rastra, takie jak jego skala, układ współrzędnych i konkretne wartości wewnątrz jego pasm. Pasmo to po prostu pojedyncza warstwa danych w siatce. Standardowy obrazek ma trzy pasma dla kolorów, ale mapa wysokości zazwyczaj ma tylko jedno pasmo reprezentujące wysokość. Weźmy konkretny scenariusz. Budujesz aplikację dla wędrowców i masz numeryczny model terenu dla pasma górskiego. Ten model wysokości jest zazwyczaj dostarczany jako plik GeoTIFF. Najpierw definiujesz model Django dla swojego pasma górskiego i dodajesz do niego RasterField. Następnie w kodzie w Pythonie tworzysz instancję GDALRaster, przekazując jej ścieżkę do twojego pliku GeoTIFF. Django ładuje plik do pamięci jako obiekt GDALRaster. Przypisujesz ten obiekt do pola RasterField w swoim modelu góry i wywołujesz save. PostGIS bierze tę siatkę i ją zapisuje. Teraz, gdy turysta wrzuca swoją trasę GPS, możesz odpytać bazę danych, żeby dowiedzieć się, w który dokładnie piksel trafiają jego współrzędne. Wyciągasz wartość wysokości zapisaną w tym konkretnym pikselu. Kiedy odczytujesz to pole z powrotem z bazy danych, Django znowu daje ci obiekt GDALRaster. Możesz odpytać ten obiekt o jego szerokość, wysokość albo zasięg przestrzenny. Możesz uzyskać dostęp do surowych tablic z danymi pikseli bezpośrednio w Pythonie, żeby wykonać obliczenia przed wysłaniem danych na frontend twojej aplikacji. I tu jest sedno sprawy. Używasz wektorów do rzeczy, które istnieją w konkretnym miejscu, a rastrów do rzeczy, które istnieją wszędzie na danym obszarze. Łącząc oba te podejścia w PostGIS, twoja aplikacja może powiązać odrębne obiekty, takie jak szlak turystyczny, z ciągłym środowiskiem, takim jak rzeczywista wysokość gruntu pod nogami. Jeśli chcesz pomóc w tworzeniu tego podcastu, wyszukaj DevStoriesEU na Patreon — twoje wsparcie wiele dla mnie znaczy. To wszystko w tym odcinku. Dzięki za wysłuchanie i twórz dalej!
13

Geolokalizacja z GeoIP2

4m 08s

Ten odcinek omawia geolokalizację opartą na IP przy użyciu modułu GeoIP2 w GeoDjango. Dowiesz się, jak mapować adresy IP użytkowników na miasta i kraje przy użyciu zestawów danych MaxMind.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. GeoDjango i PostGIS, odcinek 13 z 15. Co jeśli musisz wiedzieć, gdzie znajduje się użytkownik, żeby zaserwować mu lokalny content, ale nie dał ci uprawnień do GPS? Odpowiedź kryje się w jego przychodzącym adresie IP. Oto geolokalizacja z GeoIP2. Żeby było jasne od samego początku, geolokalizacja po IP to nie jest precyzyjne wyszukiwanie współrzędnych, jak w przypadku API geolokalizacji w przeglądarce. To tylko przybliżenie. Sprawdzając adres IP, tak naprawdę odpytujesz statyczny zbiór danych, który mapuje przypisane bloki IP na obszary geograficzne. Prawie zawsze zwróci ci właściwy kraj i często właściwe miasto, ale nie znajdzie dokładnego adresu ulicy użytkownika. Wyobraź sobie scenariusz, w którym odwiedzający wchodzi na twoją stronę e-commerce. Chcesz go automatycznie przekierować do zlokalizowanego sklepu dla jego kraju albo domyślnie wyśrodkować mapę na jego region, bazując wyłącznie na jego przychodzącym adresie IPv4 lub IPv6. GeoDjango dostarcza obiekt GeoIP2 specjalnie do obsługi takiego wyszukiwania offline. Zanim zaczniesz pisać jakąkolwiek logikę, musisz mieć wszystko odpowiednio przygotowane. Po pierwsze, instalujesz pythonową bibliotekę geoip2 w swoim środowisku. Po drugie, potrzebujesz samych danych. GeoIP2 opiera się na datasetach od MaxMind, zazwyczaj na darmowych bazach GeoLite2 City lub Country. Pobierasz te pliki, które mają rozszerzenie mmdb, i wrzucasz je na swój serwer. Na koniec, w ustawieniach Django, definiujesz zmienną o nazwie GEOIP_PATH i wskazujesz w niej na katalog zawierający te pliki. Django oczekuje, że znajdzie w tym folderze pliki o konkretnych nazwach, takie jak GeoLite2-City dot mmdb. Kiedy setup jest już gotowy, użycie tego narzędzia wymaga zaledwie kilku kroków. Importujesz obiekt GeoIP2 z modułu django contrib gis geoip2 i tworzysz jego instancję. Wyciągasz string z przychodzącym adresem IP z nagłówków requestu i przekazujesz go do jednej z metod lookup. Jeśli potrzebujesz tylko ogólnej logiki routingu, wywołujesz metodę country. Przekazujesz do niej adres IP, a ona zwraca słownik zawierający kod i nazwę kraju. Jeśli potrzebujesz większej szczegółowości, żeby wyśrodkować mapę, zamiast tego wywołujesz metodę city. Zwraca ona bogatszy słownik, zawierający nazwę miasta, region oraz przybliżone wartości długości i szerokości geograficznej. Metoda city zawiera w sobie również dane o kraju, więc zawsze wystarczy ci tylko jedno wywołanie. Jeśli chcesz po prostu wyciągnąć współrzędne, żeby przekazać je do innej funkcji, istnieją dedykowane metody, takie jak coords, które zwracają zwykły tuple z długością i szerokością geograficzną. Musisz też zgrabnie obsługiwać błędy. Jeśli przekażesz nieprawidłowy adres IP, albo adres, którego po prostu nie ma w bazie MaxMind, GeoIP2 nie zwróci pustego słownika. Rzuci wyjątkiem GeoIP2Exception. Musisz owrapować swoje wywołania lookup w blok try i zapewnić domyślny fallback lokalizacji dla twojego sklepu, gdy wyszukiwanie się nie powiedzie. A oto kluczowa sprawa. Sam kod to w zasadzie tylko zoptymalizowany czytnik plików. Dokładność twojej geolokalizacji zależy całkowicie od świeżości bazy danych siedzącej w twoim katalogu GEOIP_PATH. Alokacje adresów IP zmieniają się nieustannie. Jeśli budujesz system routingu w oparciu o GeoIP2, musisz zautomatyzować regularne pobieranie nowych plików bazy danych, inaczej twoje zlokalizowane przekierowania będą powoli i po cichu stawać się błędne. To wszystko na dzisiaj. Do usłyszenia następnym razem!
14

Testowanie aplikacji przestrzennych

4m 08s

Ten odcinek skupia się na testowaniu aplikacji przestrzennych w GeoDjango. Dowiesz się, jak skonfigurować zestaw testów, obsługiwać szablonowe bazy danych PostGIS i ustawiać uprawnienia użytkowników.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. GeoDjango i PostGIS, odcinek 14 z 15. Testowanie aplikacji przestrzennych ma pewien haczyk: twoja zautomatyzowana testowa baza danych musi zainstalować złożone rozszerzenia przestrzenne napisane w C, zanim w ogóle uruchomi się pierwszy test. Jeśli twój zautomatyzowany pipeline od razu wywala się z błędami uprawnień, to prawdopodobnie jest właśnie ten powód. Dzisiaj zajmiemy się testowaniem aplikacji przestrzennych. Pierwszy wymóg dotyczy stricte konfiguracji. Kiedy odpalasz testy, Django tworzy równoległą testową bazę danych, żeby twoje dane produkcyjne były bezpieczne. W przypadku GeoDjango, ta testowa baza danych musi być przestrzenna. To oznacza, że twoje ustawienia bazy danych muszą jawnie używać silnika przestrzennego, takiego jak backend PostGIS dostarczany przez GeoDjango. Nie możesz użyć standardowego backendu Postgres i po prostu dodać pól przestrzennych później. To właśnie przestrzenny backend mówi test runnerowi Django, żeby poszukał i zainicjował wymagane funkcje przestrzenne. Oto kluczowa sprawa. Standardowy test runner Django tworzy świeżą bazę danych, odpala twoje migracje i zaczyna testowanie. Ale dla aplikacji GeoDjango, stworzenie świeżej bazy danych to za mało. Baza danych musi również załadować rozszerzenie PostGIS. To nie jest standardowa tabela SQL. To rozszerzenie na poziomie systemu. Domyślnie PostgreSQL ogranicza to, kto może tworzyć rozszerzenia, ze względów bezpieczeństwa. Zazwyczaj wymaga to użytkownika bazy danych z uprawnieniami superusera. I to jest dokładnie ten moment, w którym pipeline'y Continuous Integration często zawodzą. Stawiasz kontener Postgresa, przekazujesz standardowego użytkownika bazy danych i każesz Django odpalić testy. Django łączy się, próbuje zbudować testową bazę danych, próbuje odpalić komendę tworzącą rozszerzenie PostGIS i trafia na błąd permission denied. Żeby to naprawić w zautomatyzowanym pipeline, użytkownik bazy danych odpalający testy musi mieć odpowiednie uprawnienia. Najprostszym podejściem w odizolowanym, jednorazowym środowisku jest tymczasowe nadanie testowemu użytkownikowi roli superusera. Jeśli twoje polityki bezpieczeństwa zabraniają dostępu superusera nawet w tymczasowym kontenerze, musisz skonfigurować PostgreSQL tak, żeby konkretny użytkownik testowy był zaufanym właścicielem testowej bazy danych i miał jawną zgodę na utworzenie rozszerzenia PostGIS. Kiedy baza danych jest już zbudowana, GeoDjango musi wiedzieć, z czym pracuje. Różne wersje PostGIS obsługują różne funkcje przestrzenne. Podczas normalnego działania, GeoDjango odpytuje bazę danych, żeby ustalić zainstalowaną wersję PostGIS. Jednak w środowisku testowym możesz pominąć to zapytanie, definiując konkretne ustawienie o nazwie PostGIS Version. Podajesz to jako krotkę trzech liczb, reprezentujących wersje major, minor i patch. Jawne ustawienie tego może przyspieszyć inicjalizację testów i działa jako fail-safe, jeśli połączenie z bazą danych ma problemy podczas początkowego sprawdzania wersji. Odpalanie testów przestrzennych nie polega na pisaniu innych asercji. To przede wszystkim wyzwanie infrastrukturalne. Najważniejszy wniosek jest taki, że jeśli twój użytkownik testowej bazy danych nie może tworzyć rozszerzeń w locie, twoje testy nawet nie wystartują. Napraw uprawnienia swojego użytkownika testowego, żeby wykonać bootstrap PostGIS, a reszta twojego pipeline'u będzie zachowywać się dokładnie tak, jak standardowy test suite w Django. Dzięki za spędzenie ze mną tych kilku minut. Do usłyszenia następnym razem, trzymaj się.
15

Wdrażanie aplikacji GeoDjango

4m 13s

Ten odcinek podsumowuje serię, omawiając kwestie związane z wdrażaniem aplikacji GeoDjango. Dowiesz się o bezpieczeństwie wątków w GDAL i o tym, jak skonfigurować procesy WSGI, aby zapobiec awariom.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. GeoDjango i PostGIS, odcinek 15 z 15. Twoja aplikacja przestrzenna działa idealnie na laptopie. Robisz deploy na serwer produkcyjny, ruch skacze, i nagle aplikacja po cichu pada. Żadnego standardowego tracebacku z Pythona, tylko martwe procesy. Problemem jest konflikt wątków głęboko w bibliotece C. Deploy aplikacji GeoDjango wymaga uniknięcia dokładnie tej pułapki. Deploy przestrzennej aplikacji webowej jest prawie identyczny jak deploy standardowego projektu w Django. Routing, połączenia z bazą danych i architektura serwera działają na dokładnie tych samych zasadach. Ale GeoDjango kryje w sobie pewną ukrytą zmienną. Tą zmienną jest Geospatial Data Abstraction Library, powszechnie znana jako GDAL. GDAL to potężna, mocno zoptymalizowana biblioteka C, która odwala czarną robotę przy formatach danych geograficznych i transformacjach współrzędnych. Oto kluczowa kwestia: GDAL nie jest thread-safe. To wyjaśnia, dlaczego twój kod działa lokalnie, ale crashuje na serwerze. Lokalny serwer deweloperski Django obsługuje requesty sekwencyjnie. Rzadko powoduje współbieżny dostęp do biblioteki C. Produkcyjne serwery WSGI są zbudowane inaczej. Żeby wydajnie obsługiwać duży ruch, serwery takie jak Apache z mod_wsgi zazwyczaj odpalają wiele wątków w ramach jednego procesu. Python zazwyczaj polega na Global Interpreter Lock, żeby zapobiec kolizjom wątków. Jednak biblioteki C zarządzają własną pamięcią całkowicie poza kontrolą Pythona. Jeśli dwa wątki WSGI próbują jednocześnie wykonać funkcję z GDAL, uzyskują dostęp do tej samej przestrzeni w pamięci bez żadnych zabezpieczeń. Jeden wątek uszkadza dane, których używa drugi. Ponieważ dzieje się to na poziomie C, Python nie może rzucić standardowego wyjątku. Efektem jest segmentation fault. Proces serwera natychmiast pada, zabierając ze sobą wszystkie aktywne requesty użytkowników. Żeby to rozwiązać, musisz zmienić sposób, w jaki twój serwer WSGI obsługuje współbieżność. Musisz oprzeć się na procesach, a nie na wątkach. Systemy operacyjne izolują procesy od siebie, dając każdemu z nich własną, dedykowaną przestrzeń w pamięci. Jeśli robisz deploy mocno obciążonej apki geograficznej na produkcję używając Apache i mod_wsgi, ogarniasz to w konfiguracji daemona. Zamiast konfigurować małą liczbę procesów z dużą pulą wątków, ograniczasz wątki. Otwierasz plik konfiguracyjny Apache i znajdujesz dyrektywę WSGI daemon process. Obok nazwy aplikacji dodajesz parametr, który jawnie ustawia liczbę wątków na dokładnie jeden. Następnie skalujesz aplikację, zwiększając liczbę procesów, żeby obsłużyć spodziewany ruch. Ta sama logika obowiązuje, jeśli używasz serwera takiego jak Gunicorn. Musisz podpiąć go pod standardowe workery. Unikasz każdej klasy workera, która wprowadza wątki albo asynchroniczne event loopy, ponieważ nieuchronnie wywołają one te same kolizje w GDAL. Wymuszenie na twoim serwerze WSGI modelu wieloprocesowego i jednowątkowego gwarantuje, że GDAL nigdy nie wejdzie w kolizję sam ze sobą. Absolutnie najważniejszym krokiem, żeby twoja apka w GeoDjango była production-ready, jest odizolowanie bibliotek C od współbieżności opartej na wątkach. To kończy naszą całą serię o GeoDjango i PostGIS. Najlepszym sposobem na utrwalenie tych koncepcji jest przejrzenie oficjalnej dokumentacji Django i zbudowanie czegoś w praktyce. Jeśli masz pomysły na to, jaką technologię powinniśmy omówić jako następną, wejdź na devstories dot eu i zaproponuj temat. Dzięki za słuchanie. Trzymajcie się wszyscy.