Django dostarcza ci bogate API do operowania na danych umieszczonych w bazie danych. Po stworzeniu modeli możesz przystąpić do tworzenia widoków operujących na danych - dodawanie, pobieranie, edycja i inne operacje. Niniejszy artykuł będzie bazował na takim oto modelu blogów:
class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()
def __unicode__(self):
return self.name
class Author(models.Model):
name = models.CharField(max_length=50)
email = models.URLField()
def __unicode__(self):
return self.name
class Entry(models.Model):
blog = models.ForeignKey(Blog)
headline = models.CharField(max_length=255)
body_text = models.TextField()
pub_date = models.DateTimeField()
authors = models.ManyToManyField(Author)
def __unicode__(self):
return self.headline
Ulokowanego w
mysite/blog/models.py (założenia do przykładu).
By dodać wpis do bazy danych wystarczy podać dane i wywołać save():
from mysite.blog.models import Blog
b = Blog(name='Blog Andrzeja', tagline='Najnowsze wieści z pola')
b.save()
Jeżeli tabela ma pole AutoField (zwiększające swą wartość, AUTO INCREMENT/SERIAL) to można pobrać id wpisu ale dopiero po jego zapisaniu, gdyż numer ID jest "obliczany" przez bazę a nie przez Django.
b2 = Blog(name='BlogSer', tagline='Przemyślenia o serze')
b2.id # zwraca None - brak id jeszcze
b2.save()
b2.id # tutaj dostaniemy id.
Zapisywanie zmian wygląda podobnie. W powyższym przykładzie
b2 odnosi się do zapisanego obiektu. By zmienić dane wystarczy:
b2.name = 'Serowo'
b2.save()
- Jeżeli klucz główny obiektu (primary key) ma wartość liczbową to Django wykonuje SELECT by sprawdzić czy rekord istnieje.
- Jeżeli rekord o podanym kluczu istnieje Django wykonuje UPDATE
- Jeżeli obiekt nie ma zdefiniowanego klucza lub rekord nie istnieje to django wykonuje INSERT
Pobieranie danych wygląda nieco inaczej. Stosuje się do niego menadżera metody. By pobrać wszystkie wiersze wystarczy:
all_entries = MODEL.objects.all()
all_entries = Blog.objects.all()
Gdzie "MODEL" to nazwa wybranego przez nas modelu. Otrzymamy listę zawierającą rekordy z bazy danych.
By pobrać określone rekordy możemy skorzystać z filter() lub exclude():
Entry.objects.filter(pub_date__year=2006)
Co pobierze rekordy, których pola pub_date zawierają rok 2006
Filtry można zagnieżdżać w taki sposób:
Entry.objects.filter(
headline__startswith='What').exclude(
pub_date__gte=datetime.now()).filter(
pub_date__gte=datetime(2005, 1, 1))
Otrzymamy rekordy w których "headline" zaczyna się od "What" opublikowane (pub_date) między styczniem 2005 a dniem dzisiejszym.
Otrzymany wynik (obiekt QuerySet) można dalej zmieniać a otrzymane na nowo wyniki są nowym obiektem QuerySet niezależnym od wyniku-rodzica:
q1 = Entry.objects.filter(headline__startswith="What")
q2 = q1.exclude(pub_date__gte=datetime.now())
q3 = q1.filter(pub_date__gte=datetime.now())
Obiekty QuerySets nie pobierają danych z bazy przy ich definiowaniu. Dopiero pewne operacje wykonują narzucone zapytanie. Owe czynniki to:
- Iterowanie: przy pierwszym przejściu zapytanie jest wykonywane
for e in Entry.objects.all():
print e.headline
- cięcie tablicy - użycie Pythonowej składni do cięcia tablic z parametrem step spowoduje wykonanie zapytania
- repl i len - notka - len nie powinno być stosowane do obliczania ilości wyników. Znacznie wydajniejszy jest SELECT COUNT
- list - wykonanie list() na QuerySet spowoduje wykonanie zapytania i wczytania wszystkiego do pamięci.
Ograniczanie ilości pobieranych wierszy jest proste:
Entry.objects.all()[:5] # LIMIT 5
Entry.objects.all()[5:10] # OFFSET 5 LIMIT 5
Entry.objects.all()[:10:2] # wykona zapytanie, zwróci co 2 rekord z pierwszych 10
Entry.objects.order_by('headline')[0] # jeden wiersz
Sortowanie wyników określone może być w modelu lecz także w zapytaniu można narzucić określone sortowanie:
Entry.objects.filter(pub_date__year=2005).order_by('-pub_date', 'headline')
Za pomocą .distinct() można pobrać niepowtarzalne wiersze (SELECT DISTINCT).
.value() natomiast zwraca ValuesQuerySet i pozwala określić z jakich pól pobierać dane. Oprócz tego ValuesQuerySet jest listą słowników
Blog.objects.values('id', 'name')
Zwróci wszystkie wpisy z bazy danych ale ograniczone do pól "id" i "name".
dates(field, kind, order='ASC')
Zwraca listę niepowtarzalnych dat z pól typu DateField lub DateTimeField.
field to nazwa takiego pola,
kind to jedno z trzech: year", "month" lub "day" - odpowiednio zwrócą one unikalne lata, unikalne miesiąc/rok i unikalne dzień/miesiąc/rok.
order określa kolejność (ASC lub DESC)
select_related() zwraca QuerySet, który dodatkowo podąża za wszystkimi ForeignKey:
e = Entry.objects.select_related().get(id=5)
b = e.blog
Co jest znacznie szybsze niż pobieranie danych "po kolei".
extra(select=None, where=None, params=None, tables=None)
Pozwala na dodanie własnego kodu SQL w pewnych miejscach zapytania. Należy stosować tylko w ostateczności.
count() zliczy ilość wierszy jaka byłaby zwrócona (SELECT COUNT)
delete() kasuje określone wpisy.
Możemy również tworzyć zapytania z LIKE i ILIKE, odpowiednio:
Entry.objects.get(headline__contains='Lennon')
Entry.objects.get(headline__icontains='Lennon')
Oprócz "contains" czy "icontains" mamy do dyspozycji:
- gt - większe niż
- gte - większe lub równe niż
- lt - mniejsze niż
- lte - mniejsze lub równe
- in - wartość z możliwych z listy: Entry.objects.filter(id__in=[1, 3, 4])
- startswith - zaczyna się od
- istartswith - to samo, nie uwzględnia rozmiaru liter
- endswith i iendswith - kończy się na, drugi nie uwzględnia wielkości liter
- range - wartość z przedziału Entry.objects.filter(pub_date__range=(start_date, end_date))
- year - dla pól daty, określa rok jaki muszą spełniać
- month, day - odpowiednio miesiąc i dzień
- Dodane: 14.07.2008 przez riklaunim