24 lutego 2023
Praca z danymi relacyjnymi w Django: ForeignKey, OneToOneField i ManyToManyField
24 lutego 2023
W tym wpisie skupimy się na kluczowym aspekcie tworzenia aplikacji internetowyc - pracy z danymi relacyjnymi. Django oferuje potężne narzędzia do zarządzania takimi danymi, co ułatwia modelowanie złożonych struktur danych i zależności między nimi.
Dane relacyjne odnoszą się do struktury danych, w której dane są zorganizowane w formie tabel (zwanych modelami w Django), a relacje między danymi są reprezentowane za pomocą powiązań między tymi tabelami. Django obsługuje trzy główne typy relacji: "ForeignKey
", "OneToOneField
" i "ManyToManyField
".
W tym wpisie zbadamy te trzy typy relacji, zrozumiemy jak je implementować w modelach Django i dowiemy się, jak manipulować danymi relacyjnymi za pomocą ORM
Django. Przedstawimy to na przykładzie modelowania zależności między krajami, ich stolicami i innymi miastami. Zaczynajmy!
Rodzaje relacji między modelami
W Django relacje między modelami są reprezentowane za pomocą specjalnych pól, które definiują typ relacji między encjami. Mamy do czynienia z trzema głównymi typami relacji: jeden do wielu, jeden do jednego i wiele do wielu. Te relacje są reprezentowane w Django odpowiednio za pomocą ForeignKey, OneToOneField i ManyToManyField.
ForeignKey
Pole OneToOneField reprezentuje relację jeden do jednego między dwoma modelami. W tej relacji jedna instancja modelu może być powiązana tylko z jedną instancją innego modelu. Na przykład, kraj może mieć tylko jedną stolicę, a stolica może należeć tylko do jednego kraju. Aby utworzyć relację OneToOneField, definiujesz pole OneToOneField w jednym z modeli.
OneToOneField
Pole OneToOneField reprezentuje relację jeden do jednego między dwoma modelami. W tej relacji jedna instancja modelu może być powiązana tylko z jedną instancją innego modelu. Na przykład, kraj może mieć tylko jedną stolicę, a stolica może należeć tylko do jednego kraju. Aby utworzyć relację OneToOneField, definiujesz pole OneToOneField w jednym z modeli.
ManyToManyField
Pole ManyToManyField reprezentuje relację wiele do wielu między dwoma modelami. W tej relacji jedna instancja modelu może być powiązana z wieloma instancjami innego modelu, i na odwrót. Na przykład, studenci i kursy mogą mieć relację wiele do wielu, gdzie student może zapisać się na wiele kursów, a kurs może mieć wielu studentów. Aby utworzyć relację ManyToManyField, definiujesz pole ManyToManyField w jednym z modeli.
W kolejnej sekcji skonfigurujemy przykład z użyciem krajów, stolic i miast, aby pokazać, jak implementować te relacje w Django.
Przykład relacji między modelami: Kraje, Stolice i Miasta
Aby zademonstrować użycie ForeignKey, OneToOneField i ManyToManyField w Django, stworzymy prostą aplikację zarządzającą krajami, stolicami i miastami. Relacje między tymi modelami są następujące:
1. Kraj może mieć wiele miast (one-to-many
)
2. Kraj ma jedną stolicę (one-to-one
)
3. Miasto może mieć wiele atrakcji turystycznych, a atrakcja turystyczna może być odwiedzana przez turystów z wielu miast (many-to-many
)
W tym przykładzie użyjemy modelu Country
do reprezentowania krajów, modelu Capital
do reprezentowania stolic i modelu City
do reprezentowania innych miast. Stworzymy również model TouristAttraction
do reprezentowania atrakcji turystycznych i ich relacji z miastami.
W kolejnych sekcjach przejdziemy przez proces implementacji tych modeli w Django i pokażemy, jak korzystać z ORM Django do interakcji z nimi.
Implementacja modeli w Django
Aby zacząć, musimy zdefiniować nasze modele w Django. Modele w Django to specjalne klasy Pythona, które reprezentują tabele w bazie danych. Atrybuty tych klas odpowiadają kolumnom w tabelach.
Tworzenie modelu Country
Zacznijmy od utworzenia modelu Country
. Każdy kraj będzie miał nazwę, która jest unikalna.
from django.db import models
class Country(models.Model):
name = models.CharField(max_length=100, unique=True)
def __str__(self):
return self.name
Tworzenie modelu Capital
Następnie utworzymy model Capital
. Każda stolica będzie miała nazwę i będzie powiązana z jednym krajem przez relację OneToOneField.
class Capital(models.Model):
name = models.CharField(max_length=100, unique=True)
country = models.OneToOneField(Country, on_delete=models.CASCADE)
def __str__(self):
return self.name
Tworzenie modelu City
Następnie utworzymy model City
. Każde miasto będzie miało nazwę i będzie powiązane z jednym krajem przez relację ForeignKey.
class City(models.Model):
name = models.CharField(max_length=100)
country = models.ForeignKey(Country, on_delete=models.CASCADE)
def __str__(self):
return self.name
Tworzenie modelu TouristAttraction
Na koniec utworzymy model TouristAttraction
. Każda atrakcja turystyczna będzie miała nazwę i będzie powiązana z wieloma miastami przez relację ManyToManyField.
class TouristAttraction(models.Model):
name = models.CharField(max_length=100)
cities = models.ManyToManyField(City)
def __str__(self):
return self.name
Teraz, gdy nasze modele są gotowe, możemy użyć ORM Django do tworzenia, odpytywania, aktualizowania i usuwania powiązanych danych.
Korzystanie z ORM Django do interakcji z modelami
ORM Django pozwala na interakcję z modelami w sposób Pythonowy, bez pisania skomplikowanych zapytań SQL. W tej sekcji pokażemy, jak tworzyć instancje naszych modeli, odpytywać powiązane dane, aktualizować powiązane dane i usuwać powiązane dane.
Zanim zaczniemy, wejdźmy do powłoki Django, aby wykonać kod interaktywnie. Aby to zrobić, uruchom następujące polecenie w terminalu:
python manage.py shell
Po wejściu do powłoki Django możesz zaimportować swoje modele i zacząć z nimi pracować.
Tworzenie Modeli
Aby tworzyć instancje naszych modeli, możemy skorzystać z metody create dostarczanej przez menedżer modelu. Na przykład możemy stworzyć kraj, stolicę i miasto w ten sposób:
from myapp.models import Country, Capital, City
country = Country.objects.create(name="Exampleland")
capital = Capital.objects.create(name="Example City", country=country)
city = City.objects.create(name="Another City", country=country)
Tworzenie Queryset
Możemy korzystać z ORM Django do odpytywania powiązanych danych. Na przykład możemy uzyskać wszystkie miasta powiązane z krajem w ten sposób:
cities = City.objects.filter(country=country)
Możemy aktualizować powiązane dane, aktualizując pola powiązanych instancji i wywołując na nich metodę save. Na przykład możemy zaktualizować nazwę miasta w ten sposób:
capital = Capital.objects.get(country=country)
Aktualizacja powiązanych danych
We can update related data by updating the fields of the related instances and calling the save method on them. For example, we can update the name of a city like this:
country_1 = country.objects.get(capital=Berlin)
country_1.name = "New Name"
country_1.save()
Usuwanie powiązanych danych
Możemy usuwać powiązane dane, wywołując na powiązanych instancjach metodę delete. Na przykład możemy usunąć miasto w ten sposób:
country1.delete()
Zauważ, że metoda delete usunie również wszelkie powiązane instancje z relacją ForeignKey lub OneToOneField, które mają ustawione on_delete=models.CASCADE
.
W następnej sekcji pokażemy, jak wyświetlać powiązane dane w szablonach Django przy użyciu frameworka CSS Bootstrap.
Wyświetlanie powiązanych danych w szablonach
Teraz, gdy mamy nasze modele i dane ustawione, wyświetlmy powiązane dane w szablonach Django. W tej sekcji pokażemy, jak tworzyć szablony do wyświetlania danych o kraju, stolicy i miastach, a także jak korzystać z frameworka CSS Bootstrap
do stylizacji.
Korzystanie z Bootstrap do stylizacji
Aby użyć Bootstrap w naszych szablonach, najpierw musimy dołączyć pliki CSS i JavaScript Bootstrap do szablonu base.html
. Możesz pobrać pliki i dołączyć je lokalnie lub skorzystać z CDN. Dla uproszczenia skorzystamy z opcji CDN. Dodaj następujące linie do sekcji head i body pliku base.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Country, Capital, and City Data</title>
<!-- Add Bootstrap CSS -->
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
{% block content %}{% endblock %}
<!-- Add Bootstrap JS and jQuery -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.3/dist/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>
Tworzenie szablonów do wyświetlania danych
Teraz, gdy mamy ustawiony framework Bootstrap, stwórzmy szablony do wyświetlania naszych danych. Stworzymy szablon do wyświetlania listy krajów i ich stolic, a także inny szablon do wyświetlania miast i atrakcji turystycznych dla konkretnego kraju.
Stwórz szablon o nazwie country_list.html
i dodaj do niego następujący kod:
{% extends "base.html" %}
{% block content %}
<h1>Countries and Capitals</h1>
<table class="table table-striped">
<thead>
<tr>
<th>Country</th>
<th>Capital</th>
</tr>
</thead>
<tbody>
{% for country in countries %}
<tr>
<td>{{ country.name }}</td>
<td>{{ country.capital.name }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
Stwórz szablon o nazwie country_detail.html
i dodaj do niego następujący kod:
{% extends "base.html" %}
{% block content %}
<h1>{{ country.name }}</h1>
<h2>Cities</h2>
<ul>
{% for city in country.city_set.all %}
<li>{{ city.name }}</li>
{% endfor %}
</ul>
{% endblock %}
W swoich views
możesz teraz renderować te szablony i przekazywać do nich potrzebne dane. Na przykład możesz stworzyć widok do wyświetlania listy krajów i ich stolic tak jak to:
from django.shortcuts import render
from .models import Country
def country_list(request):
countries = Country.objects.all()
return render(request, 'country_list.html', {'countries': countries})
A możesz stworzyć widok do wyświetlania szczegółów konkretnego kraju tak jak to:
from django.shortcuts import render, get_object_or_404
from .models import Country
def country_detail(request, country_id):
country = get_object_or_404(Country, pk=country_id)
return render(request, 'country_detail.html', {'country': country})
Aby wyświetlić atrakcje turystyczne dla każdego miasta, zmodyfikuj szablon country_detail.html
w następujący sposób:
{% extends "base.html" %}
{% block content %}
<h1>{{ country.name }}</h1>
<h2>Cities</h2>
<ul>
{% for city in country.city_set.all %}
<li>
{{ city.name }}
<ul>
<strong>Tourist Attractions:</strong>
{% for attraction in city.touristattraction_set.all %}
<li>{{ attraction.name }}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
{% endblock %}
Teraz masz szablony do wyświetlania listy krajów ze swoimi stolicami, a także szczegółowy widok konkretnego kraju z jego miastami i atrakcjami turystycznymi. Szablony korzystają z frameworka CSS Bootstrap do stylizacji.
Podsumowanie
W tym wpisie omówiliśmy, jak pracować z danymi relacyjnymi w Django, omawiając relacje ForeignKey, OneToOneField i ManyToManyField. Ustawiliśmy również przykład z krajami, stolicami i miastami, aby pokazać, jak implementować te relacje w modelach Django.
Następnie użyliśmy ORM Django do tworzenia, zapytań, aktualizacji i usuwania powiązanych danych. Dodatkowo pokazaliśmy, jak wyświetlać te powiązane dane w szablonach Django, używając do stylizacji frameworka CSS Bootstrap.
Rozumiejąc i wykorzystując potężne funkcje Django do pracy z danymi relacyjnymi, możesz tworzyć bardziej złożone i efektywne aplikacje internetowe. Kontynuując budowę swoich projektów Django, pamiętaj, aby wykorzystać potężne narzędzia i techniki wbudowane omówione w tym poście do skutecznego zarządzania relacjami między twoimi modelami.