Poprzedni wykład     Lista wykładów    

Administrowanie stroną cd, rezerwowanie noclegów

Zarządzanie użytkownikami Rezerwowanie noclegów Źródła opisywanego programu

Zarządzanie użytkownikami

Rozbudujemy plik admin.html dodając wyświetlanie listy użytkowników, oraz linki pozwalające edytować dane użytkownika, usuwać użytkowników i wysyłać maile. W odróżnieniu od listy apartamentów i typów cen, lista użytkowników może być bardzo długa. Stronę zaprojektujemy tak, by jednorazowo wyświetlać najwyżej 10 użytkowników. Dokładniej, funkcję admin_page napiszemy tak, by przekazywała do funkcji renderującej tylko 10 użytkowników.
Ostateczna wersja funkcji admin_page:
def admin_page(request):
    template = get_template("admin.html")
    apartments = Apartment.objects.all()
    types = TypCeny.objects.all()
    users = User.objects.order_by('username')
    if request.method == 'POST' and request.POST.has_key('first'):
        first = int(request.POST['first'])
        if request.POST.has_key('back'):
            first = first - 10
        if request.POST.has_key('forward'):
            first = first + 10            
    else:
        first = 0
    variables = RequestContext(request,{'apartments':apartments,'types':types,'users':users[first:first+10],'number_of_users':len(users),'first':first,'end':(first+10>=len(users))})                
    output = template.render(variables)            
    return HttpResponse(output)
Metoda User.objects.order_by('username') zwraca listę wszystkich użytkowników uporządkowana wg wartości pola username, do funkcji renderującej przekazywany jest tylko 10-elementowy fragment tej listy ('users':users[first:first+10]), przekazywana jest również informacja czy jest to początkowy fragment (klucz 'first' w słowniku) i czy jest to końcowy fragment (klucz 'end'). Wartość klucza 'first' jest numeryczna, wartośc klucza klucz 'end' jest logiczna. Ta różnica nie ma to znaczenia ze względu na niejawne konwersje int => bool.

Fragment pliku admin.html odpowiedzialny za wyświetlanie użytkowników i (warunkowe) umieszczenie przycisków Wcześniejsi i Następni:

<h2>Zarejestrowani użytkownicy ({{number_of_users}})</h2>
<ul>
  {% if first %}<form style="display:inline;" method="post" action="/admin/">{% csrf_token %}<button type="submit" value="">Wcześniejsi<br><img src="/media/back.gif" width="16px"></button>
  <input type="hidden" name="back"><input type="hidden" name="first" value="{{first}}"></form>{% endif %}
  <hr width="50%" align="left">
  {% for user in users %}
  <li style="list-style-type:none;width:50%;">
    <form style="display:inline;"><input type="checkbox" disabled {% if user.is_superuser %}checked="checked"{% endif %}></form>
    {{user.username}}    {{user.email}}    <div id="nav"><a href="/save_user/{{user.id}}">Edycja</a>
    {% if not user.is_superuser %}    <a href="/delete_user/{{user.id}}">Usunięcie</a>{% endif %}
    {% if user.email %} <a href="/send_mail/?id={{user.id}}">Wysłanie maila</a>{% endif %}</div>
  </li>
  {% endfor %}
  <hr width="50%" align="left">
  {% if not end %}<form style="display:inline;" method="post" action=".">{% csrf_token %}<button type="submit" value="">Następni<br><img src="/media/forward.gif" width="16px"></button>
  <input type="hidden" name="forward"><input type="hidden" name="first" value="{{first}}"></form>{% endif %}
</ul>
Niemożliwe jest usunięcie administratora, wysłanie maila jest możliwe tylko wtedy gdy użytkownik podał adres pocztowy.
Edytowanie i usuwanie użytkowników przebiega niemal identycznie jak edytowanie i usuwanie typów cen. Usuwanie jest kaskadowe, tzn. usunięcie użytkownika usuwa wszystkie jego rezerwacje. Przed usunięciem użytkownika wyświetlany jest formularz potwierdzający:

Interesujący jest fragment funkcji delete_user_page ustalający ilu rezerwacji (począwszy od dnia dzisiejszego) dokonał usuwany uzytkownik.
@permission_required('user.is_superuser',"/login/")    
def delete_user_page(request,args):
    if request.method == 'POST':
	    ...
    else:
        id = args
        user = User.objects.get(id=id)
        day = date.today()
        number_of_bookings = Booking.objects.filter(who=user,date__gte=day).count()
        template = get_template("edition/user_delete.html")
        variables = RequestContext(request,{'user':user,'bookings':number_of_bookings})
        output = template.render(variables)
        return HttpResponse(output)
Pogrubiony wiersz odpowiada takiemu zapytaniu SQL:
SELECT COUNT(*) FROM Booking WHERE who = user AND date >= day
Przy budowaniu filtru możemy sie posługiwać zmienionymi nazwami kolumn, zmiana polega na dopisaniu podwójnego znaku podkreślenia ('__') oraz pewnego słowa kluczowego. Pełną liste słów kluczowych można znaleźć tutaj (gte = greater than or equal to).

Trochę dokładniej opiszemy wysyłanie maila.


Spis treści

Rezerwowanie noclegów

Każda osoba odwiedzająca stronę widzi przy każdym apartamencie taka informację (pod warunkiem, że administrator strony umieścił na serwerze zdjęcie apartamentu lub jakieś podobne):
Linki Cennik i Aktualne rezerwacje wyświetlają to samo co na stronie adminstratora, z tą różnicą, że zwykły użytkownik (zalogowany lub anonimowy) nie może edytować cennika.

Zaczniemy od utworzenia nowej tabeli Booking. Wpierw opisujemy tabelę w pliku models.py:

class Booking(models.Model):
    apartment = models.ForeignKey(Apartment)
    who = models.ForeignKey(User)
    date = models.DateField(db_index=True)
    def __str__(self):
        return "Data: "+self.date.strftime('%d.%m.%y')+" Id rezerwującego: "+str(self.who_id)+" Id apartamentu: "+str(self.apartment_id)
a potem otwieramy konsolę i wpisujemy polecenia:
python manage.py syncdb               #utworzona zostanie nowa tabela
python manage.py sqlindexes bookings  #w tabeli zostaną utworzone indeksy
Parametr db_index=True powoduje, że zostanie utworzony indeks na pole date. Pozostałe czynności są dosyć standardowe. Zalogowany użytkownik, który chce rezerwować noclegi jest kierowany na stronę booking.html.

Jeżeli we wskazanym okresie wybrany apartament jest wolny, użytkownik widzi potwierdzenie udanej rezerwacji.
W przeciwnym razie kierowany jest na stronę booking_correction.html
z informacją o wolnych apartamentach w pobliżu wskazanego wykresu. Użytkownik może teraz zmienić apartament lub okres. Szczegółów tego przekierowania nie będę juz omawiał.

Źródła opisywanego programu


Wystarczy teraz wpisać w przeglądarce adres localhost:8000.
Przed wysyłaniem maili z programu należy wypełnić wiersze 152 - 155 w pliku settings.py. Podczas tworzenia superusera program spytał o adres mailowy. Należy teraz podać parametry tego serwera pocztowego, który został wymieniony w aresie mailowym.

Spis treści
Poprzedni wykład     Lista wykładów