Serwer WWW na przykªadzie Django formularze, widoki, sesje, u»ytkownicy 19 marca 2014
URLe Formularze Widoki generyczne klasowe Ciasteczka Sesje U»ytkownicy
Routing from django.conf.urls import patterns urlpatterns = patterns('', (r'^articles/2003/$', 'news.views.special_case_2003'), (r'^articles/(\d{4})/$', 'news.views.year_archive'), (r'^articles/(\d{4})/(\d{2})/$', 'news.views.month_archive'), (r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'), )
Nazwane grupy urlpatterns = patterns('', (r'^articles/2003/$', 'news.views.special_case_2003'), (r'^articles/(?p<year>\d{4})/$', 'news.views.year_archive'), (r'^articles/(?p<year>\d{4})/(?p<month>\d{2})/$', 'news.views.month_archive'), (r'^articles/(?p<year>\d{4})/(?p<month>\d{2})/' '(?P<day>\d{2})/$', 'news.views.article_detail'), )
Prex from django.conf.urls import patterns urlpatterns = patterns('news.views', (r'^articles/(\d{4})/$', 'year_archive'), (r'^articles/(\d{4})/(\d{2})/$', 'month_archive'), (r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'article_detail') ) urlpatterns = patterns('myapp.views', (r'^$', 'app_index'), (r'^(?p<year>\d{4})/(?p<month>[a-z]{3})/$', 'month_display'), ) urlpatterns += patterns('weblog.views', (r'^tag/(?p<tag>\w+)/$', 'tag'), )
Doª czanie from django.conf.urls import patterns, include urlpatterns = patterns('', #... snip... (r'^comments/', include('django.contrib.comments.urls')), (r'^community/', include('django_website.aggregator.urls')), (r'^contact/', include('django_website.contact.urls')), (r'^r/', include('django.conf.urls.shortcut')), #... snip... )
Wywoªywanie funkcji from mysite.views import archive, about, contact urlpatterns = patterns('', (r'^archive/$', archive), (r'^about/$', about), (r'^contact/$', contact), ) from mysite import views urlpatterns = patterns('', (r'^archive/$', views.archive), (r'^about/$', views.about), (r'^contact/$', views.contact), )
Wywoªywanie metod from mysite.views import ClassBasedView urlpatterns = patterns('', (r'^myview/$', ClassBasedView.as_view()), )
Odwracanie URL szablony url funkcje django.core.urlresolvers.reverse() i django.core.urlresolvers.reverse_lazy() metoda get_absolute_url() funkcja resolve()
Odwracanie URLi przykªad from django.conf.urls import patterns, url urlpatterns = patterns('', #... url(r'^articles/(\d{4})/$', 'news.views.year_archive'), #... ) ====== W szablonie: <a href="{% url 'news.views.year_archive' 2012 %}"> 2012 Archive</a>
Nazwany URL urlpatterns = patterns('', url(r'^archive/(\d{4})/$', archive, name="full-archive") url(r'^archive-summary/(\d{4})/$', archive, {'summary': True}, "arch-summary"), ) ===== W szablonie: {% url 'arch-summary' 1945 %} {% url 'full-archive' 2007 %}
Najprostszy formularz def search(request): query = request.get.get('q', '') if query: qset = (Q(title icontains=query)... ) results = Book.objects.filter(qset).distinct() else: results = [] return render_to_response("books/search.html", { "results": results, "query": query })
Formularz - u»ycie <title>search{% if query %} Results{% endif %}... <h1>search</h1> <form action="." method="get"> <label for="q">search: </label> <input type="text" name="q" value="{{ query escape }}"> <input type="submit" value="search">... {% if query %} <h2>results for "{{ query escape }}":</h2> {% if results %} <ul> {% for book in results %} <li>{{ book escape }}</l1> {% endfor %}
Idealny formularz W formularzu wprowadza si dane, które s opisane (np. <label>) Dane s werykowane W przypadku bª du u»ytkownik mo»e poprawi dane Formularz wy±wietla si wielokrotnie, a» wszystkie dane s poprawne
forms.py from django import newforms as forms TOPIC_CHOICES = ( ('general', 'General enquiry'), ('bug', 'Bug report'), ('suggestion', 'Suggestion'), ) class ContactForm(forms.Form): topic = forms.choicefield(choices=topic_choices) message = forms.charfield() sender = forms.emailfield(required=false)
Widok from forms import ContactForm def contact(request): form = ContactForm() return render_to_response('contact.html', {'form': form}
Szablon <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <html lang="en"> <head> <title>contact us</title></head> <body> <h1>contact us</h1> <form action="." method="post"> {% csrf_token %} <table> {{ form.as_table }} </table> <p><input type="submit" value="submit"></p> </form> </body> </html>
Jak to wygl da
forms.py from django import newforms as forms TOPIC_CHOICES = ( ('general', 'General enquiry'), ('bug', 'Bug report'), ('suggestion', 'Suggestion'), ) class ContactformForm(forms.Form): topic = forms.choicefield(choices=topic_choices) message = forms.charfield(widget = forms.textarea()) sender = forms.emailfield(required=false)
Jak to wygl da
Walidacja def contact(request): if request.method == 'POST': form = ContactForm(request.POST) else: form = ContactForm() return render_to_response('contact.html', {'form': form}
Zachowanie 1 def contact(request): if request.method == 'POST': form = ContactForm(request.POST) if form.is_valid(): topic = form.clean_data['topic'] message = form.clean_data['message'] sender = form.clean_data.get('sender', 'noreply@example.com')
Zachowanie 2 send_mail( 'Feedback from your site, topic: %s' % topic, message, sender, ['administrator@example.com'] ) return HttpResponseRedirect('/contact/thanks/') else: form = ContactForm() return render_to_response('contact.html', {'form': form}
Wªasna walidacja class ContactForm(forms.Form): topic = forms.choicefield(choices=topic_choices) message = forms.charfield(widget=forms.textarea()) sender = forms.emailfield(required=false) def clean_message(self): message = self.clean_data.get('message', '') num_words = len(message.split()) if num_words < 4: raise forms.validationerror("not enough words!") return message
Inne wykorzystanie formularzy from models import Publisher from django.newforms import form_for_model PublisherForm = form_for_model(publisher) ==== def add_publisher(request): if request.method == 'POST': form = PublisherForm(request.POST) if form.is_valid(): form.save() return HttpResponseRedirect('/add_publisher/than
TemplateView from django.conf.urls import patterns from django.views.generic import TemplateView urlpatterns = patterns('', (r'^about/', TemplateView.as_view(template_name="about.h )
TemplateView podklasa # some_app/views.py from django.views.generic import TemplateView class AboutView(TemplateView): template_name = "about.html" # urls.py from some_app.views import AboutView urlpatterns = patterns('', (r'^about/', AboutView.as_view()), )
Obsªuga ró»nych metod Stara: from django.http import HttpResponse def my_view(request): if request.method == 'GET': # <view logic> return HttpResponse('result') ====== Nowa: from django.http import HttpResponse from django.views.generic.base import View class MyView(View): def get(self, request): # <view logic> return HttpResponse('result')
Nadpisywanie zmiennych klasowych class GreetingView(View): greeting = "Good Day" def get(self, request): return HttpResponse(self.greeting) === podklasa === class MorningGreetingView(GreetingView): greeting = "Morning to ya" === urle === urlpatterns = patterns('', (r'^about/', MyView.as_view(greeting="G'day")), )
ListView #widok class PublisherList(ListView): model = Publisher #url urlpatterns = patterns('', url(r'^publishers/$', PublisherList.as_view()), ) #szablon {% block content %} <h2>publishers</h2> <ul> {% for publisher in object_list %} <li>{{ publisher.name }}</li> {% endfor %} </ul> {% endblock %}
ListView modykacja kontekstu class PublisherDetail(DetailView): model = Publisher def get_context_data(self, **kwargs): # Call the base implementation first to get a contex context = super(publisherdetail, self).get_context_d # Add in a QuerySet of all the books context['book_list'] = Book.objects.all() return context
Jakie s widoki View TemplateView RedirectView DetailView ListView FormView CreateView UpdateView DeleteView
Odczytywanie ciasteczek def show_color(request): if "favorite_color" in request.cookies: return HttpResponse("Your favorite color is %s" % \ request.cookies["favorite_color"]) else: return HttpResponse("You don't have a favorite color
Ustawianie ciasteczek def set_color(request): if "favorite_color" in request.get: response = HttpResponse("Your favorite color is now request.get["favorite_color"]) response.set_cookie("favorite_color", request.get["favorite_color"]) return response else: return HttpResponse("You didn't give a favorite colo
Werykacja ciasteczek def login(request): if request.method == 'POST': if request.session.test_cookie_worked(): request.session.delete_test_cookie() return HttpResponse("You're logged in.") else: return HttpResponse("Please enable cookies and t request.session.set_test_cookie() return render_to_response('foo/login_form.html')
Atrybuty ciasteczek max_age czas wa»no±ci w sekundach expires data wa»no±ci w formacie "Wdy, DD-Mth-YY HH:MM:SS GMT" path ±cie»ka domain domena wa»no±ci np..mimuw.edu.pl secure czy wolno przekazywa ciastko tylko po HTTPS
Sesje # Ustawianie: request.session["fav_color"] = "blue" # Odczyt fav_color = request.session["fav_color"] # Kasowanie del request.session["fav_color"] # Sprawdzanie if "fav_color" in request.session:...
Jak dziaªaj sesje S cz ±ci aplikacji django.contrib.sessions S zapisywane w bazie danych >>> from django.contrib.sessions.models import Session >>> s = Session.objects.get(pk='2b1189a188b44ad18c35e113ac6c >>> s.expire_date datetime.datetime(2005, 8, 20, 13, 35, 12)
Kiedy sesje s modykowane # Sesja jest modyfikowana request.session['foo'] = 'bar' # Sesja jest modyfikowana del request.session['foo'] # Sesja jest modyfikowana request.session['foo'] = {} # Sesja NIE jest modyfikowana bo zmienia si # request.session['foo'] a nie request.session. request.session['foo']['bar'] = 'baz'
Techniczne szczegóªy W sesji mo»na zapisa wszystko, co da si zapicklowa. Sesje przechowywane s w tabeli django_session. Dane odczytywane s na» danie Ciasteczko jest ustawiane tylko w przypadku takiej konieczno±ci. Sesje s oparte w caªo±ci na ciasteczkach, w przeciwie«stwie do PHP i JSP.
U»ytkownicy Users u»ytkownicy strony Permissions logiczne (tak/nie) uprawnienia do poszczególnych czynno±ci Groups nadawanie uprawnie«caªej grupie osób Messages wiadomo±ci dla u»ytkowników Proles rozszerzanie obiektów opisuj cych u»ytkowników
Jak dziaªaja mechanizm uprawnie«aplikacja django.contrib.auth if request.user.is_authenticated(): # Do something for authenticated users. else: # Do something for anonymous users.
U»ytkownik 1 username nazwa 30 znaków rst_name, last_name opcjonalne 30 znaków Email opcjonalny Password wymagane, przechowywany hash is_sta dost p do admin is_active aktywny, czy mo»e si logowa is_superuser ma wszystkie uprawnienia last_login kiedy si logowaª date_joined kiedy zaªo»one konto
U»ytkownik 2 is_authenticated() czy si zalogowaª is_anonymous() czy nie jest anonimowy get_full_name() imie, spacja, nazwisko set_password(passwd) ustawia hasªo check_password(passwd) sprawdza get_group_permissions() uprawnienia wynikaj ce z grup get_all_permissions() wszystkie uprawnienia. has_perm(perm) sprawdza uprawnienie
U»ytkownik 3 has_perms(perm_list) sprawdza wszystkie uprawnienia has_module_perms(app_label) sprawdza jakiekolwiek uprawnienie w aplikacji get_and_delete_messages() wiadomo±ci dla u»ytkownika email_user(subj, msg) wysyªa email get_prole() dodatkowe pola
Grupy i uprawnienia myuser.groups = group_list # ustawia myuser.groups.add(group1, group2,...) # dodaje myuser.groups.remove(group1, group2,...) # usuwa myuser.groups.clear() # usuwa z wszystkich grup # Uprawnienia podobnie myuser.permissions = permission_list myuser.permissions.add(permission1, permission2,...) myuser.permissions.remove(permission1, permission2,...) myuser.permissions.clear()
Logowanie from django.contrib import auth def login(request): username = request.post['username'] password = request.post['password'] user = auth.authenticate(username=username, password=password) if user is not None and user.is_active: auth.login(request, user) return HttpResponseRedirect("/account/loggedin/") else: return HttpResponseRedirect("/account/invalid/")
Wylogowanie from django.contrib import auth def logout(request): auth.logout(request) return HttpResponseRedirect("/account/loggedout/")
Szablon logowania {% block content %} {% if form.errors %} <p class="error">sorry, that's not a valid username or password</p> {% endif %} <form action='.' method='post'> <label for="username">user name:</label> <input type="text" name="username" value="" id="username <label for="password">password:</label> <input type="password" name="password" value="" id="password"> <input type="submit" value="login" /> <input type="hidden" name="next" value="{{ next escape }}" /
Co z niezalogowanym from django.http import HttpResponseRedirect def my_view(request): if not request.user.is_authenticated(): return HttpResponseRedirect('/login/?next=%s' % request.path) #... ==== from django.contrib.auth.decorators import login_required @login_required def my_view(request): #...