Django: utilizzo avanzato e nuove funzionalità

Loading...

Flash Player 9 (or above) is needed to view presentations.
We have detected that you do not have it on your computer. To install it, go here.

0 comments

Post a comment

    Post a comment
    Embed Video
    Edit your comment Cancel

    Notes on slide 1

    Theme created by Sakari Koivunen and Henrik Omma Released under the LGPL license.

    1 Favorite

    Django: utilizzo avanzato e nuove funzionalità - Presentation Transcript

    1. Django Utilizzo avanzato e nuove funzionalità
    2. Perchè utilizzare django?
      • Tempi di sviluppo ridotti
      • Scalabilità e performance
      • Ottima documentazione, comunità attiva e partecipe
      • Motore di templating semplice e adatto ai designer di pagine HTML
      • URL puliti e SEO-friendly
      • Python powered!
    3. Perchè utilizzare la versione trunk?
      • 1 anno dall'ultima release stabile (0.9.6)‏
      • Supporto unicode
      • Cambiamenti dell' API
      • Nuove funzionalità
    4. Utilizzo della versione trunk
      • Installazione da sorgenti
      • $ cd /path/to/packages
      • $ svn co http://code.djangoproject.com/svn/django/trunk Django
      • $ python setup.py install
      • Utilizzo senza installazione
      • $ export PATH=$PATH:/path/to/Django/bin
      • $ export PYTHONPATH=$PYTHONPATH:/path/to/packages/Django
    5. Supporto unicode: gestione delle stringhe
      • Django assume che tutte le bytestring siano in UTF-8 , in caso contrario l'eccezione UnicodeDecodeError verrà sollevata
      • La variabile di configurazione DEFAULT_CHARSET viene utilizzata solo per il rendering dei template e dei messaggi e-mail
      • Le stringhe di traduzione “lazy” possono essere convertite direttamente in stringhe unicode
          • http://www.djangoproject.com/documentation/i18n/#lazy-translation
    6. Supporto unicode: funzioni di conversione
      • django.utils.encoding.smart_unicode
        • Converte una qualsiasi stringa in unicode
      • django.utils.encoding.force_unicode
        • Identica a smart_unicode, con la differenza che non preserva le stringhe di traduzione “lazy”, forzandone la traduzione e la conversione in unicode
    7. Supporto unicode: URI e IRI
      • Gli URL di tipo URI utilizzano solo caratteri ASCII.
      • La funzione iri_to_uri permette di costruire URL di tipo IRI (RFC 3987)‏
          • http://www.ietf.org/rfc/rfc3987.txt
      • >>> from django.utils.encoding import iri_to_uri
      • >>> iri_to_uri(u'/locations/Rennes-le-Château')‏
      • '/locations/Rennes-le-Ch%C3%A2teau'
    8. Supporto unicode: database
      • Assicurarsi che il proprio database sia configurato per utilizzare l'encoding appropriato ( UTF-8, UTF-16 ) ‏
      • Il database backend si occuperà di convertire automaticamente le stringhe unicode nell'encoding utilizzato dal database, e viceversa
      • È possibile passare stringhe unicode e bytestring UTF-8 ai metodi utilizzati per filtrare gli oggetti QuerySet
      • >>> Place.objects.filter(name__contains=u'Château')‏
    9. Supporto unicode: modelli
      • Le stringhe ottenute dai campi testuali dei modelli sono sempre di tipo unicode
      • Nel caso il vostro modello contenga un metodo __str__() può essere necessario implementare anche il metodo __unicode__()‏
      • Se necessario, utilizzare la funzione iri_to_uri() nel metodo get_absolute_url()‏
    10. Supporto unicode: template
      • I template possono essere salvati sul filesystem utilizzando un charset diverso da UTF-8 , in tal caso è necessario definire la variabile di configurazione FILE_CHARSET
      • È consigliato l'utilizzo delle funzione force_unicode nella creazione di template tag
    11. Escape automatico dei template
      • Qualsiasi variabile inserita nel contesto di un template viene convertita automaticamente utilizzando django.utils.html.escape
      • È stata introdotta con lo scopo di prevenire attacchi di tipo XSS (Cross-site scripting)‏
      • Non è possibile disabilitare tale funzionalità globalmente
    12. Escape automatico dei template
      • È possibile disabilitare l'escape automatico direttamente nei template {% autoescape off %} ... {{ entry.body }} ... {% endautoescape %} {{ entry.body|safe }}
    13. Escape automatico dei template
      • È inoltre possibile disabilitare l'escape automatico nei template filter @register.filter def safefilter(value): # do something with value... return value safefilter.is_safe = True
      • template.Context accetta l'argomento autoescape template.Context({'foo': bar}, autoescape=False)‏
    14. Modelli
      • La classe LazyDate() è stata rimossa. È possibile utilizzare una funzione per l'argomento default from datetime import datetime from django.db import models from django.contrib.auth.models import User class Place(models.Model): name = models.CharField(max_length=100) description = models.TextField(blank=True) created = models.DateField(default=datetime.now) location = models.ForeignKey(Location)‏ author = models.ForeignKey(User)‏
      • L'utilizzo dell'attributo maxlength è deprecato ed è stato sostituito da max_length
    15. Modelli
      • I campi di tipo FloatField utilizzavano float per rappresentare numeri decimali a precisione fissa
      • È stato introdotto il campo DecimalField , che utilizza il tipo di dato decimal.Decimal per mantenere la precisione latitude = models.DecimalField(max_digits=8, decimal_places=6)‏
      • FloatField non accetta più gli argomenti precedentemente utilizzati
    16. Modelli
      • È stato recentemente aggiunto il supporto all'ereditarietà delle classi Model class Place(models.Model): name = models.CharField(max_length=100) description = models.TextField(blank=True) created = models.DateField(default=datetime.now) location = models.ForeignKey(Location) author = models.ForeignKey(User) class Restaurant(Place): has_bistecca_fiorentina = models.BooleanField()‏
      • http://www.djangoproject.com/documentation/model-api/#model-inheritance http://code.djangoproject.com/wiki/QuerysetRefactorBranch
    17. URL patterns
      • È ora possibile utilizzare la funzione url() per assegnare un nome a un determinato URL pattern from django.conf.urls.defaults import * urlpatterns = patterns('pycon2.places.views', url(r'^add/$', 'place_add', name='place_add'), url(r'^(?P<place_id>d+)/edit/$', 'place_edit', name='place_edit'), url(r'^(?P<place_id>d+)/delete/$','place_delete', name='place_delete') )‏
    18. URL patterns: permalink
      • Utilizzo nel metodo get_absolute_url() di un modello: from django.db.models import permalink def get_absolute_url(self): return ('place_detail', [str(self.id)]) get_absolute_url = permalink(get_absolute_url)‏
    19. URL patterns: url template tag
      • <a href=”{% url place_add %}”>Add place</a> <a href=”{% url place_edit place.id %}”>Edit {{ place }}</a> <a href=”{% url place_delete place.id %}”>Delete {{ place }}</a>
    20. MEDIA_URL context processor
      • La variabile di configurazione MEDIA_URL è ora disponibile per poter essere utilizzata nei template <img src=”{{ MEDIA_URL }}img/logo.jpg” alt=”logo” title=”logo” />
    21. URL patterns: urlresolvers
      • >>> from django.core.urlresolvers import reverse >>> reverse('place_add') '/places/add/' >>> reverse('place_edit', args=[1]) '/places/1/edit/' >>> reverse('place_delete', args=[1]) '/places/1/delete/'
    22. newforms
      • Introdotta nella release 0.9.6 con lo scopo di sostituire la vecchia libreria di gestione dei form
      • Permette di semplificare la creazione dei form, la validazione dei dati ricevuti, l'utilizzo e la creazione di widget HTML personalizzati
      • django.forms è stata copiata in django.oldforms
      • Nella prossima release stabile django.newforms verrà rinominata in django.forms
    23. newforms
      • Form
        • Contiene i campi, riceve i dati, si occupa della loro validazione e del rendering in HTML
      • Field
        • Rappresenta un campo e si occupa della sua validazione
      • Widget
        • Rendering di un campo in HTML
    24. newforms
        • # pycon2.contacts.forms
        • from django import newforms as forms
        • class ContactForm(forms.Form):
        • name = forms.CharField(required=False, max_length=50)‏ email = forms.EmailField()‏ comment = forms.CharField(widget=forms.Textarea)‏
        • Gli argomenti max_length e required vengono utilizzati per la validazione del campo “name”
        • L'argomento widget viene utilizzato per definire il tipo di widget utilizzato per l'output HTML
    25. newforms
      • I dati ricevuti vengono passati come primo argomento del costruttore della classe
      • È possibile verificare la validità dei dati ricevuti utilizzando il metodo is_valid()‏
      • L'attributo errors è un dizionario contenente gli errori di validazione
      • Nella release 0.9.6 i dati del form, normalizzati a seconda dei tipi di campo, erano disponibili nell'attributo clean_data , che è stato rinominato in cleaned_data
    26. newforms
      • >>> form = ContactForm() >>> form.is_bound False >>> form = ContactForm({'email': 'foo@bar.com '}) >>> form.is_bound True >>> form.is_valid() False >>> form.errors {'comment': [u'This field is required.']}
    27. newforms
      • Per gestire gli upload è possibile passare request.FILES come secondo argomento nel costruttore della classe
      • Il metodo is_multipart() ritorna True se la classe contiene campi di tipo FileField
      • È possibile accedere al nome e al contenuto del file attraverso cleaned_data form.cleaned_data['fieldname'].content form.cleaned_data['fieldname'].filename
    28. newforms: esempio di utilizzo
        • from django.template import RequestContext
        • from django.template.loader import render_to_string
        • from django.shortcuts import render_to_response
        • from django.core.mail import mail_admins
        • from pycon2.contacts.forms import ContactForm
        • def contact(request, template='contacts/contact.html', email_template='contacts/contact_email.txt'):
        • if request.method == 'POST':
        • form = ContactForm(request.POST)‏
        • if form.is_valid():
        • message = render_to_string(email_template,
        • form.cleaned_data)‏
        • mail_admins('contact request', message)‏
        • else:
        • form = ContactForm()‏
        • return render_to_response(template, {'form': form}, context_instance=RequestContext(request))‏
    29. Field e Widget personalizzati: CaptchaField
        • # pycon2.contacts.forms
        • from django import newforms as forms
        • from pycon2.utils.captcha.fields import CaptchaField
        • class ContactForm(forms.Form):
        • name = forms.CharField(required=False, max_length=50)‏
        • email = forms.EmailField()‏
        • comment = forms.CharField(widget=forms.Textarea)‏
        • captcha = CaptchaField()‏
    30. CaptchaWidget
        • # pycon2.utils.captcha.fields
        • from django.newforms.util import flatatt
        • from django.utils.safestring import mark_safe
        • CAPTCHA_IMAGE = '''<div class=”captcha”><img src=”%s” alt=”captcha” /></div>'''
        • class CaptchaWidget(forms.TextInput):
        • def render(self, name, value, attrs=None):
        • captcha_url = reverse('captcha')‏
        • image = CAPTCHA_IMAGE % captcha_url
        • if value is None: value = ''
        • final_attrs = self.build_attrs(attrs, type=self.input_type, name=name)‏
        • attrs = flatatt(final_attrs)‏
        • if value != '':
        • final_attrs['value'] = force_unicode(value)‏
        • return mark_safe(u'%s<input%s />' % (image, attrs))‏
    31. CaptchaWidget: funzioni utilizzate
      • django.newforms.util.flatatt
        • Converte un dizionario in una stringa contenente gli attributi utilizzabili in un elemento HTML. I valori del dizionario vengono convertiti utilizzando la funzione django.utils.html.escape
      • django.utils.safestring.mark_safe
        • Funzione utilizzata per definire che la stringa passata come argomento è sicura per poter essere utilizzata nell'output HTML
    32. CaptchaField
        • # pycon2.utils.captcha.fields
        • from django.utils.translation import ugettext as _
        • from pycon2.utils.captcha.middleware import
        • get_current_captcha
        • class CaptchaField(forms.CharField):
        • widget = CaptchaWidget
        • def clean(self, value):
        • captcha = get_current_captcha()‏
        • if not captcha:
        • raise forms.ValidationError(_('You must enable cookies.'))‏
        • if value != captcha:
        • raise forms.ValidationError(_('Incorrect! Try again.'))‏
        • return value
    33. Captcha middleware
        • # pycon2.utils.captcha.middleware
        • try:
        • from threading import local
        • except ImportError:
        • from django.utils._threading_local import local
        • _thread_locals = local()‏
        • def get_current_captcha():
        • return getattr(_thread_locals, 'captcha', None)‏
        • class CaptchaMiddleware(object):
        • def process_request(self, request):
        • captcha = None session = getattr(request, 'session', None) if session: captcha = session.get('captcha')‏
        • _thread_locals.captcha = captcha
    34. Captcha view
        • # pycon2.utils.captcha.view
        • import Captcha
        • import cStringIO
        • from Captcha.Visual.Tests import PseudoGimpy
        • from django.http import HttpResponse
        • def captcha(request): ''' Visualizza un immagine captcha utilizzando PyCaptcha
        • '''
        • g = PseudoGimpy()‏
        • s = cStringIO.StringIO()‏
        • i = g.render()‏
        • i.save(s, 'JPEG')‏
        • request.session['captcha'] = g.solutions[0]
        • return HttpResponse(s.getvalue(), 'image/jpeg')‏
    35. Form preview
      • Viene fornita un'applicazione per poter visualizzare l'anteprima di una classe form
        • Il form viene visualizzato in formato HTML su una pagina web
        • I dati del form vengono validati
          • Se il form non è valido, viene visualizzato con gli errori di validazione
          • Se il form è valido, viene visualizzato per conferma
        • I dati del form di conferma vengono ricevuti da un hook definito dall'utente
    36. Form preview # pycon2.contacts.preview import pprint from django.http import HttpResponse from django.contrib.formtools.preview import FormPreview from pycon2.contacts.forms import ContactForm class ContactFormPreview(FormPreview): def done(self, request, cleaned_data): # do something with cleaned_data... output = pprint.pformat(cleaned_data)‏ return HttpResponse(output, mimetype='text/plain')‏ contact = ContactFormPreview(ContactForm)‏
    37. Form preview
      • Per visualizzare l'anteprima è sufficiente aggiungere un pattern nella propria configurazione degli URL ('^preview/contact/$', 'pycon2.contacts.preview.contact'),
    38. Form wizard
      • È stata introdotta un applicazione che permette di creare form suddivisi su più pagine
      • L'applicazione si occupa di mantenere lo stato dei dati inseriti nei form fra una pagina e l'altra
      • Le istanze delle classi form vengono passate al metodo done()‏
      • È possibile specificare i template da utilizzare definendo il metodo get_template()‏
    39. Form wizard # pycon2.contacts.forms from django import newforms as forms from django.http import HttpResponseRedirect from django.contrib.formtools.wizard import FormWizard from django.core.urlresolvers import reverse class PollOne(forms.Form): name = forms.CharField()‏ email = forms.EmailField() job_position = forms.CharField()‏ LANGUAGE_CHOICES = ( ('python', 'Python'), ('ruby', 'Ruby'), ('perl', 'Perl'), ('php', 'PHP'), ) class PollTwo(forms.Form): languages = forms.MultipleChoiceField(choices=LANGUAGE_CHOICES)‏ preferred_language = forms.ChoiceField(choices=LANGUAGE_CHOICES)‏
    40. Form wizard # pycon2.contacts.forms class PollWizard(FormWizard): def done(self, request, form_list): form_data = [form.cleaned_data for form in form_list] # do something with form_data return HttpResponseRedirect(reverse('poll_done')) def get_template(self, step): '''Override default template “forms/wizard.html”''' return ['contacts/poll_%s.html' % step, 'contacts/poll.html'] # pycon2.contacts.urls from django.conf.urls.defaults import * from pycon2.contacts.forms import PollOne, PollTwo, PollWizard urlpatterns = patterns('', url(r'^poll/$', PollWizard([PollOne, PollTwo]), name='poll'), url(r'^poll/done/$', 'django.views.generic.simple.direct_to_template', {'template': 'contacts/poll_done.html'}, name='poll_done') )‏
    41. Form wizard {# templates/contacts/poll.html #} {% extends 'base_site.html' %} {% block title %} Poll - step {{ step }} of {{ step_count }} {% endblock %} {% block content %} <form action='.' method='POST'> <input type=&quot;hidden&quot; name=&quot;{{ step_field }}&quot; value=&quot;{{ step0 }}&quot; /> {{ form.as_p }} {{ previous_fields|safe }} <p> <input type=&quot;submit&quot; value=&quot;Submit&quot; /> </p> </form> {% endblock %}
    42. ModelForm
      • Permette di creare una classe Form da un modello
      • Sostituisce le funzioni deprecate form_for_model() e form_for_instance()
      • Permette di modificare con facilità i campi generati automaticamente
    43. ModelForm
      • # pycon2.places.forms
      • from django import newforms as forms
      • from pycon2.places.models import Place
      • class PlaceForm(forms.ModelForm):
      • class Meta:
      • model = Place
      • exclude = ('created', 'author')
      • La classe interna Meta viene utilizzata per definire
        • il modello da utilizzare
        • i campi da escludere
    44. ModelForm
      • Il costruttore della classe accetta l'argomento instance per definire l'istanza del modello da utilizzare
      • Il metodo save() ritorna l'istanza del modello
        • accetta il parametro commit : se il suo valore è False il metodo restituisce un istanza non salvata
        • in tal caso il metodo save_m2m() deve essere utilizzato per poter salvare i dati delle relazioni many-to-many
    45. ModelForm: esempio di utilizzo # pycon2.places.views @login_required def place_add(request, template='places/place_add.html'): if request.method == 'POST': form = PlaceForm(request.POST)‏ if form.is_valid(): place = form.save(commit=False)‏ place.author = request.user place.save()‏ return HttpResponseRedirect(place.get_absolute_url())‏ else: form = PlaceForm()‏ return render_to_response(template, {'form': form}, context_instance=RequestContext(request))‏
    46. ModelForm: esempio di utilizzo # pycon2.places.views @login_required def place_edit(request, place_id, template='places/place_edit.html'): place = get_object_or_404(Place, pk=place_id)‏ if request.method == 'POST': form = PlaceForm(request.POST, instance=place)‏ if form.is_valid(): form.save()‏ return HttpResponseRedirect(place.get_absolute_url())‏ else: form = PlaceForm(instance=place)‏ return render_to_response(template, {'form': form, 'place': place}, context_instance=RequestContext(request))‏
    47. newforms-admin
      • Utilizza la libreria newforms , eliminando le dipendenze con oldforms
      • Disaccoppia le funzionalità dell'interfaccia di amministrazione dai modelli
      • Permette di personalizzare alcuni aspetti dell'interfaccia di amministrazione, fra cui:
        • Definire widget personalizzati per i campi e modificarne gli attributi
        • Modificare i permessi sui singoli oggetti
    48. newforms-admin: installazione
      • Scaricare il branch e modificare la variabile d'ambiente PYTHONPATH http://code.djangoproject.com/svn/django/branches/newforms-admin/
      • Modificare la propria configurazione degli URL from django.conf.urls.defaults import * from django.contrib import admin urlpatterns = patterns('', (r'^admin/(.*)', admin.site.root), )‏
    49. newforms-admin: esempio di utilizzo # pycon2.places.models from django.contrib import admin class Place(models.Model): name = models.CharField(max_length=100) description = models.TextField(blank=True) created = models.DateField(default=datetime.now) location = models.ForeignKey(Location)‏ author = models.ForeignKey(User)‏ class Location(models.Model): name = models.CharField(max_length=100)‏ latitude = models.DecimalField(max_digits=8, decimal_places=6)‏ longitude = models.DecimalField(max_digits=8, decimal_places=6) # register models into admin site admin.site.register(Place) admin.site.register(Location)‏
    50. newforms-admin: esempio di utilizzo class PlaceOptions(admin.ModelAdmin): list_display = ('name', 'location', 'author') search_fields = ('name', 'description') def has_change_permission(self, request, obj=None): if obj: if request.user != obj.author: return False return super(PlaceOptions, self).has_change_permission(request, obj) class PlaceInline(admin.TabularInline)‏ model = Place extra = 5 class LocationOptions(admin.ModelAdmin): inlines = [PlaceInline] # register models into admin site admin.site.register(Place, PlaceOptions) admin.site.register(Location, LocationOptions)‏
    51. Contenttypes
      • Applicazione basata sul modello ContentType , che contiene i seguenti campi
        • app_label (nome dell'applicazione)‏
        • model (nome del modello)‏
        • name ( verbose_name di un modello)‏
      • Permette di creare delle relazioni generiche fra l' istanza di un modello e diverse altre istanze
      • Viene utilizzata in diverse applicazioni fra cui django.contrib.comments, django-tagging, django-voting etc.
    52. Contenttypes
        • >>> from django.contrib.contenttypes.models import ContentType
        • >>> place_type = ContentType.objects.get(app_label='places',
        • model='place')‏
        • >>> place_type
        • <ContentType: place>
        • >>> place_type.model_class()‏
        • <class 'pycon2.places.models.Place'>
        • >>> from pycon2.places.models import Location
        • >>> ContentType.objects.get_for_model(Location)‏
        • <ContentType: location>
    53. Contenttypes: ObjectCounter
        • # pycon2.counter.models
        • from django.db import models
        • from django.contrib.contenttypes.models import ContentType
        • from django.contrib.contenttypes import generic
        • from django.contrib.auth.models import User
        • from pycon2.counter.managers import ObjectCounterManager
        • class ObjectCounter(models.Model):
        • content_type = models.ForeignKey(ContentType)‏
        • object_id = models.PositiveIntegerField()‏
        • content_object = generic.GenericForeignKey('content_type', 'object_id')‏
        • visited = models.DateTimeField(auto_now_add=True)‏
        • user = models.ForeignKey(User, blank=True, null=True)‏
        • objects = ObjectCounterManager()
        • def __unicode__(self):
        • return u'%s: %d' % (self.content_type.name, self.object_id)‏
    54. Contenttypes: ObjectCounterManager
        • # pycon2.counter.managers
        • from django.db import models, connection
        • from django.contrib.contenttypes.models import ContentType
        • class ObjectCounterManager(models.Manager):
        • def count_object(self, obj, user=None):
        • counter = self.model()‏
        • counter.content_object = obj
        • if user: counter.user = user
        • counter.save()‏
        • def most_visited_for_model(self, model, num=10):
        • '''Inspired by http://www.djangosnippets.org/snippets/108/'''
        • content_type = ContentType.objects.get_for_model(model)‏
        • primary_table = model._meta.db_table
        • secondary_table = self.model()._meta.db_table
        • query = &quot;&quot;&quot;SELECT p.id AS obj_id, COUNT(*) AS score
        • FROM %s p INNER JOIN %s s ON (p.id = s.object_id)‏
        • WHERE s.content_type_id = %%s GROUP BY obj_id
        • ORDER BY score DESC&quot;&quot;&quot; % (primary_table, secondary_table)‏
        • cursor = connection.cursor()‏
        • cursor.execute(query, [content_type.id])‏
        • object_ids = [row[0] for row in cursor.fetchall()[:num]]
        • object_dict = model._default_manager.in_bulk(object_ids)‏
        • return [object_dict[object_id] for object_id in object_ids]
    55. Contenttypes: utilizzo di ObjectCounter
        • >>> from django.db import models
        • >>> from pycon2.counter.models import ObjectCounter
        • >>> from pycon2.members.models import Profile
        • >>> profile1 = Profile.objects.get(pk=1)‏
        • >>> profile2 = Profile.objects.get(pk=2)‏
        • >>> profile3 = Profile.objects.get(pk=3)‏
        • >>> ObjectCounter.objects.count_object(profile1)‏
        • >>> ObjectCounter.objects.count_object(profile1)‏
        • >>> ObjectCounter.objects.count_object(profile1)‏
        • >>> ObjectCounter.objects.count_object(profile2)‏
        • >>> ObjectCounter.objects.count_object(profile2)‏
        • >>> ObjectCounter.objects.count_object(profile3)‏
        • >>> ObjectCounter.objects.most_visited_for_model(Profile)‏
        • [<Profile: foo>, <Profile: bar>, <Profile: baz>]
    56. Signals
      • Django utilizza il dispatching di eventi per la gestione di determinate funzionalità
      • È possibile collegare le proprie funzioni ai segnali utilizzati internamente dal framework
      • Tali funzionalità sono offerte da PyDispatcher, che è stato incluso a partire dalla versione 0.9.5
    57. Signals
      • I seguenti segnali sono utilizzati internamente nei modelli e sono definiti in django.db.models.signals
        • pre_init
        • post_init
        • pre_save
        • pre_delete
        • post_delete
        • post_syncdb
    58. Signals: utilizzo di esempio
      • È possibile estendere il modello django.contrib.auth.models.User utilizzando un proprio modello attraverso la variabile di configurazione AUTH_PROFILE_MODULE AUTH_PROFILE_MODULE = 'members.Profile'
      • L'istanza del modello definito in AUTH_PROFILE_MODULE non viene creata automaticamente nel momento in cui un istanza di User viene salvata
    59. Signals: utilizzo di esempio
      • Possiamo creare l'istanza del modello nella nostra view che si occupa della registrazione dei modelli
      • E se l'utente viene creato da un amministratore attraverso l'interfaccia di amministrazione?
    60. Signals: utilizzo d'esempio # pycon2.members.models from django.db import models from django.contrib.auth.models import User from django.dispatch import dispatcher from django.db.models import signals class Profile(models.Model): user = models.ForeignKey(User)‏ photo = models.ImageField(upload_to='pics', blank=True)‏ bio = models.TextField(blank=True)‏ def create_profile(sender, instance, signal, *args, **kwargs): if kwargs.get('created'): try: instance.get_profile()‏ except Profile.DoesNotExist: profile = Profile(user=instance)‏ profile.save()‏ dispatcher.connect(create_profile, signal=signals.post_save, sender=User)‏
        • Massimo Scamarcia [email_address]
        • http://skam.webfactional.com/
      Grazie! http://creativecommons.org/licenses/by-nd/2.5/it/

    + skamskam, 2 years ago

    custom

    2457 views, 1 favs, 0 embeds more stats

    Django è uno dei framework web più apprezzati e u more

    More info about this document

    © All Rights Reserved

    Go to text version

    • Total Views 2457
      • 2457 on SlideShare
      • 0 from embeds
    • Comments 0
    • Favorites 1
    • Downloads 21
    Most viewed embeds

    more

    All embeds

    less

    Flagged as inappropriate Flag as inappropriate
    Flag as inappropriate

    Select your reason for flagging this presentation as inappropriate. If needed, use the feedback form to let us know more details.

    Cancel
    File a copyright complaint
    Having problems? Go to our helpdesk?

    Categories