Skip to content

Commit

Permalink
Uzuepłnienia scenariusza Czat (wer. rozszerzona).
Browse files Browse the repository at this point in the history
  • Loading branch information
xinulsw committed Apr 20, 2015
1 parent 2a7dae2 commit b66742b
Show file tree
Hide file tree
Showing 7 changed files with 185 additions and 77 deletions.
110 changes: 37 additions & 73 deletions docs/python/czat/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ Po wpisaniu w przeglądarce adresu *127.0.0.1:8000* zobaczymy stronę powitalną
Domyślnie serwer nasłuchuje na porcie ``8000``, można go jednak uruchomić
na innyn, jeżeli domyślny byłby zajęty. Wystarczy, że do polecenia dodamy
np.: ``127.0.0.1:8080``.

W systemach Linux możemy kliknąć w terminalu prawym klawiszem adres ``http://127.0.0.1:8000/``
i wybrać polecenie "Otwórz link", aby szybko otworzyć domyślną przeglądarkę.
Lokalny serwer deweloperski zatrzymujemy za pomocą skrótu :kbd:`Ctrl+C`.

Jeden projekt może zawierać wiele aplikacji zapisywanych w osobnych podkatalogach katalogu projektu.

Rozpoczynamy od modyfikacji ustawień projektu, tak aby korzystał z polskiej wersji językowej
Expand Down Expand Up @@ -146,7 +146,7 @@ Podajemy te dane po wydaniu w katalogu projektu w terminalu polecenia:
poleceniem ``.tables``. Możemy również zobaczyć jakie instrukcje SQL-a
zostały użyte do utworzenia naszej tabeli: ``.schema czat_wiadomosc``.
Z interpretera wychodzimy poleceniem ``.quit``.

.. figure:: img/czat03ter.png

Panel administracyjny
Expand Down Expand Up @@ -272,7 +272,7 @@ podany tekst. W pliku :file:`views.py` umieszczamy:
Warto zapamiętać, że każdą funkcję, formularz czy widok udostępniane
przez Django, których chcemy użyć, musimy najpierw zaimportować za pomocą
klauzuli typu ``from <skąd> import <co>``.

Widok :file:`index()` łączymy z adresem URL strony głównej (/) w pliku :file:`urls.py`:

.. raw:: html
Expand Down Expand Up @@ -319,6 +319,20 @@ Następnie tworzymy szablon, czyli plik :file:`~/czat/czat/templates/czat/index.
.. literalinclude:: index_z2.html
:linenos:

W pliku :file:`views.py` zmieniamy instrukcje odpowiedzi:

.. raw:: html

<div class="code_no">Kod nr <script>var code_no = code_no || 1; document.write(code_no++);</script></div>

.. highlight:: python
.. literalinclude:: views_z2.py
:linenos:

Do zwrócenia szablonu, używamy funkcji ``render()``, której jako pierwszy argument
podajemy parametr ``request``, a jako drugi nazwę szablonu uwzględniającą
katalog nadrzędny.

Po wpisaniu adresu *127.0.0.1:8000/* zobaczymy tekst, który umieściliśmy w szablonie:

.. figure:: img/czat11.png
Expand Down Expand Up @@ -457,8 +471,8 @@ widok ``loguj()`` i ``wyloguj()`` w pliku :file:`views.py`:
.. highlight:: python
.. literalinclude:: views_z4.py
:linenos:
:lineno-start: 36
:lines: 36-
:lineno-start: 37
:lines: 37-

Podobnie jak w przypadku rejestrowania użytkowników, korzystamy z wbudowanego w Django
formularza logowania ``AuthenticationForm``. Dzięki temu nie musimy
Expand Down Expand Up @@ -513,7 +527,7 @@ wygląda tak:
np. ``loguj()``. Tego typu operacja generuje żądanie typu :term:`GET`,
w odpowiedzi na które zwracany jest szablon (np. :file:`loguj.html`)
wyświetlający przekazny do niego formularz (np. ``AuthenticationForm``).

Po wypełnieniu formularza użytkownik wciska odpowiedni przycisk, który
inicjuje żądanietypu :term:`POST`, a więc przesyłanie danych na serwer.
Widoki ``rejestruj()`` i ``loguj()`` wychwytują i przetwarzają takie żądania,
Expand Down Expand Up @@ -589,52 +603,28 @@ zarejestrowanego już użytkownika i wysłać pusty lub niekompletny formularz.
Dodawanie i wyświetlanie wiadomości
***********************************

Chcemy, by zalogowani użytkownicy mogli przeglądać wiadomości od innych użytkowników i dodawać własne. Utworzymy widok ``messages()``, który wyświetli wszystkie wiadomości (żądanie GET) i ewentualnie zapisze nową wiadomość nadesłaną przez użytkownika (żądanie POST). Widok skorzysta z nowego szablonu :file:`messages.html` i powiązany zostanie z adresem */messages*. Zaczynamy od zmian w :file:`views.py`.
Chcemy, by zalogowani użytkownicy mogli przeglądać wiadomości od innych użytkowników
i dodawać własne. Pierwszy sposób to utworzenie widoku ``wiadomosci()`` do
wyświetlania (żądania GET) i dodawania wiadomości (żądania POST), który
zwracał będzie szablon :file:`wiadomosci.html`. Widok ten powiążemy
z adresem */wiadomosci*. Do pliku :file:`views.py` dodajemy importy
i kod funkcji:

.. raw:: html

<div class="code_no">Kod nr <script>var code_no = code_no || 1; document.write(code_no++);</script></div>

.. code-block:: python
.. highlight:: python
.. literalinclude:: views_z6.py
:linenos:
:lineno-start: 57
:lines: 57-

# -*- coding: utf 8 -*-
# chatter/chatter/views.py
# dodajemy nowe importy
from chatter.models import Message
from django.utils import timezone
from django.contrib.auth.decorators import login_required
# pozostale widoki
# dekorator, ktory "chroni" nasz widok przed dostepem przez osoby niezalogowane, jezeli uzytkownik niezalogowany
# bedzie probowal odwiedzic ten widok, to zostanie przekierowany na strone logowania
@login_required(login_url='/login')
def messages(request):
"""Widok wiadomosci."""
error = None
# zadanie POST oznacza, ze ktos probuje dodac nowa wiadomosc w systemie
if request.method == 'POST':
text = request.POST.get('text', '') # pobieramy tresc przeslanej wiadomosci
# sprawdzamy, czy nie jest ona dluzsza od 250 znakow:
# – jezeli jest dluzsza, to zwracamy blad, jezeli jest krotsza lub rowna, to zapisujemy ja w systemie
if not 0 < len(text) <= 250:
error = u'Wiadomość nie może być pusta i musi mieć co najwyżej 250 znaków'
else:
# ustawiamy dane dla modelu Message
msg = Message(text=text, pub_date=timezone.now(), user=request.user)
msg.save() # zapisujemy nowa widomosc
return redirect(reverse('messages')) # przekierowujemy na strone wiadomosci
user = request.user # informacje o aktualnie zalogowanym uzytkowniku
messages = Message.objects.all() # pobieramy wszystkie wiadomosci
# ustawiamy zmienne przekazywane do szablonu
context = {'user': user, 'messages': messages, 'error': error}
# renderujemy templatke wiadomosci
return render(request, 'chatter/messages.html', context)
Widać powyżej, że treść przesłanej wiadomości odczytujemy ze słownika
``request.POST`` za pomocą metody ``get('tekst', '')``. Jej pierwszy argument
odpowiada nazwie pola formularza użytej w szablonie, które chcemy odczytać.
Drugi argument oznacza wartość domyślną, która zostanie użyta, jeśli
pole będzie niedostępne.

Teraz tworzymy nowy szablon :file:`messages.html` w katalogu :file:`templates/chatter/`.

Expand Down Expand Up @@ -676,32 +666,6 @@ JAK TO DZIAŁA: W widoku ``messages()``, podobnie jak w widoku ``login()``, mamy
POST zawiera z kolei treść nowej wiadomości, której długość sprawdzamy i jeżeli wszystko jest w porządku, tworzymy nową wiadomość (instancję klasy *Message*, czyli obiekt ``msg``) i zapisujemy ją w bazie danych (wywołujemy metodę obiektu: ``msg.save()``).



Wylogowywanie użytkowników
****************************

Django ma wbudowaną również funkcję wylogowującą. Utworzymy zatem nowy widok ``my_logut()`` i powiążemy go z adresem :file:`/logout`. Do pliku :file:`views.py` dodajemy:

.. raw:: html

<div class="code_no">Kod nr <script>var code_no = code_no || 1; document.write(code_no++);</script></div>

.. code-block:: python
def my_logout(request):
"""Wylogowywanie uzytkownika z systemu"""
logout(request)
# przekierowujemy na strone glowna
return redirect(reverse('index'))
Zadania dodatkowe
==================

Powiąż widok ``my_logut`` z adresem *logout/* dopisując regułę w odpowiednim pliku. Powiązanie nazwij "logout".
Wylogowywanie nie wymaga osobnego szablonu, dodaj jednak link wylogowujący do 1) szablonu :file:`index.html` po linku "Zobacz wiadomości" oraz do 2) szablonu :file:`messages.html` po nagłówku ``<h1>``.

.. figure:: img/chatter3.png

Materiały
***************

Expand Down
32 changes: 32 additions & 0 deletions docs/python/czat/urls_z6.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
# czat/czat/urls.py

from django.conf.urls import patterns, include, url
from django.contrib import admin
from czat import views # importujemy zdefiniowane w pliku views.py widoki

admin.autodiscover() # potrzebne tylko w Django 1.6

from django.views.generic.edit import CreateView
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
from django.core.urlresolvers import reverse_lazy

urlpatterns = patterns('',
url(r'^$', views.index, name='index'),
#url(r'^rejestruj/', views.rejestruj, name='rejestruj'),
#url(r'^loguj/', views.loguj, name='loguj'),
#url(r'^wyloguj/', views.wyloguj, name='wyloguj'),
url(r'^rejestruj/', CreateView.as_view(
template_name='czat/rejestruj.html',
form_class=UserCreationForm,
success_url='/'), name='rejestruj'),
url(r'^loguj/', 'django.contrib.auth.views.login',
{'template_name': 'czat/loguj.html'},
name='loguj'),
url(r'^wyloguj/', 'django.contrib.auth.views.logout',
{'next_page': reverse_lazy('index')},
name='wyloguj'),
url(r'^wiadomosci/', views.wiadomosci, name='wiadomosci'),

url(r'^admin/', include(admin.site.urls)),
)
2 changes: 1 addition & 1 deletion docs/python/czat/views_z2.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# czat/czat/views.py

from django.http import HttpResponse
#from django.http import HttpResponse
from django.shortcuts import render

def index(request):
Expand Down
3 changes: 2 additions & 1 deletion docs/python/czat/views_z3.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# czat/czat/views.py

from django.http import HttpResponse
#from django.http import HttpResponse
from django.shortcuts import render

def index(request):
Expand All @@ -13,6 +13,7 @@ def index(request):
from django.shortcuts import redirect
from django.core.urlresolvers import reverse
from django.contrib.auth import authenticate, login, logout
from django.contrib import messages

def rejestruj(request):
"""Rejestracja nowego użytkownika."""
Expand Down
5 changes: 3 additions & 2 deletions docs/python/czat/views_z4.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# czat/czat/views.py

from django.http import HttpResponse
#from django.http import HttpResponse
from django.shortcuts import render

def index(request):
Expand All @@ -12,7 +12,8 @@ def index(request):

from django.shortcuts import redirect
from django.core.urlresolvers import reverse
from django.contrib.auth import authenticate, login, logut
from django.contrib.auth import authenticate, login, logout
from django.contrib import messages

def rejestruj(request):
"""Rejestracja nowego użytkownika."""
Expand Down
79 changes: 79 additions & 0 deletions docs/python/czat/views_z6.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# -*- coding: utf-8 -*-
# czat/czat/views.py

#from django.http import HttpResponse
from django.shortcuts import render

def index(request):
"""Strona główna aplikacji."""
#return HttpResponse("Witaj w aplikacji Czat!")
kontekst = {'user': request.user}
return render(request, 'czat/index.html', kontekst)

from django.shortcuts import redirect
from django.core.urlresolvers import reverse
from django.contrib.auth import authenticate, login, logout
from django.contrib import messages

def rejestruj(request):
"""Rejestracja nowego użytkownika."""
from django.contrib.auth.forms import UserCreationForm

if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
messages.success(request, "Zostałeś zarejestrowany.")
user = authenticate(
username=form.data['username'],
password=form.data['password1'])
login(request, user)
messages.success(request, "Zostałeś zalogowany.")
return redirect(reverse('index'))

kontekst = {'form': UserCreationForm()}
return render(request, 'czat/rejestruj.html', kontekst)

def loguj(request):
"""Logowanie użytkownika"""
from django.contrib.auth.forms import AuthenticationForm

if request.method == 'POST':
form = AuthenticationForm(request, request.POST)
if form.is_valid():
login(request, form.get_user())
messages.success(request, "Zostałeś zalogowany!")
return redirect(reverse('index'))

kontekst = {'form': AuthenticationForm()}
return render(request, 'czat/loguj.html', kontekst)

def wyloguj(request):
"""Wylogowanie użytkownika"""
logout(request)
messages.info(request, "Zostałeś wylogowany!")
return redirect(reverse('index'))

from czat.models import Wiadomosc
from django.utils import timezone
from django.contrib.auth.decorators import login_required

@login_required(login_url='/loguj')
def wiadomosci(request):
"""Dodawanie i wyświetlanie wiadomości"""

if request.method == 'POST':
tekst = request.POST.get('tekst', '')
if not 0 < len(tekst) <= 250:
messages.error(request,
"Wiadomość nie może być pusta, może mieć maks. 250 znaków!")
else:
wiadomosc = Wiadomosc(tekst=tekst,
data_pub=timezone.now(),
autor=request.user)
wiadomosc.save()
return redirect(reverse('wiadomosci'))

wiadomosci = Wiadomosc.objects.all()
kontekst = {'user': request.user, 'wiadomosci': wiadomosci}
return render(request, 'czat/wiadomosci.html', kontekst)
31 changes: 31 additions & 0 deletions docs/python/czat/wiadomosci_z6.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<!-- czat/czat/templates/czat/wiadomosci.html -->
<html>
<body>
<h1>Wiadomości</h1>

{% if messages %}
<ul>
{% for komunikat in messages %}
<li>{{ komunikat|capfirst }}</li>
{% endfor %}
</ul>
{% endif %}

<h2>Dodaj wiadomość</h2>
<form method="POST">
{% csrf_token %}
<input type="text" name="tekst" />
<button type="submit">Zapisz</button>
</form>

<h2>Lista wiadomości:</h2>
<ol>
{% for wiadomosc in wiadomosci %}
<li>
<strong>{{ wiadomosc.autor.username }}</strong> ({{ wiadomosc.data_pub }}):
<br /> {{ wiadomosc.tekst }}
</li>
{% endfor %}
</ol>
</body>
</html>

0 comments on commit b66742b

Please sign in to comment.