Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Django

 Django

#WIP

Henoc Díaz

November 04, 2015
Tweet

More Decks by Henoc Díaz

Other Decks in Programming

Transcript

  1. Cómo funcionan? Se forman a través de expresiones regulares, por

    ejemplo: ^students/$ Si tuvieramos un dominio ejemplo.com, correspondería a: ejemplo.com/students/ @henocdz
  2. Forms Nos permiten tener de una manera más estructurada la

    entrada de información por parte del usuario y/o servicios externos. @henocdz
  3. Cómo crear un formulario? from django import forms # Para

    este caso en particular, # es buena idea importar todo el módulo class StudentForm(forms.Form): # Al igual que para modelos, # definimos los campos como atributos de clase nombre = forms.CharField() apellidos = forms.CharField() edad = forms.IntegerField() website = forms.URLField() @henocdz
  4. Cómo instanciar un formulario sin datos # app/views.py from django.shortcuts

    from app.forms import StudentForm def form_view(request): student_form = StudentForm() return render(request, 'app/form.html', {'form': student_form}) @henocdz
  5. Cómo mostrarlo en un template? <!-- Consideremos que desde la

    vista envíamos la variable form--> <h1> Opcion 1: </h1> <form method="POST"> <!-- Podemos utilizar alguno de estos tres métodos --> {{ form.as_p }} {{ form.as_table }} {{ form.as_ul }} </form> Esto nos mostrará todos los campos @henocdz
  6. Como alternativa, podemos iterar o acceder manualmente a todos los

    campos que tiene el formulario y renderearlos en el template a nuestro gusto <!-- Consideremos que desde la vista envíamos la variable form--> <h1> Opcion 2: </h1> <form method="POST"> {{ form.non_field_errors }} {% for campo in form %} {{ campo.label_tag }} <!-- <label /> --> {{ campo.errors }} <!-- <ul /> --> {{ campo }} <!-- <input|select|checkbox /> --> {% endfor %} </form> @henocdz
  7. <!-- Consideremos que desde la vista envíamos la variable form-->

    <h1> Opcion 3: </h1> <form method="POST"> {{ form.non_field_errors }} {{ form.apellidos.label_tag }} <!-- <label /> --> {{ form.apellidos.errors }} <!-- <ul /> --> {{ form.apellidos }} <!-- <input|select|checkbox /> --> {{ form.nombre.label_tag }} <!-- <label /> --> {{ form.nombre.errors }} <!-- <ul /> --> {{ form.nombre }} <!-- <input|select|checkbox /> --> </form> @henocdz
  8. Formulario con datos ligados def form_view(request): if request.method == 'POST':

    student_form = StudentForm(request.POST) if student_form.is_valid(): # form.is_valid(): nos dirá si los datos ingresados # cumplen con el formato correcto # Investigar: Messages framework return redirect('/') else: student_form = StudentForm() return render(request, 'app/form.html', {'form': student_form}) @henocdz
  9. Widgets Modifican el tipo de input/select/checkbox/etc que se mostrará en

    HTML así como la manera en que recolectará los datos. Por ejemplo: @henocdz
  10. from django import forms class StudentForm(forms.Form): GENERO_CHOICES = ( (0,

    'Masculino'), (1, 'Femenino') ) # ... genero = forms.IntegerField( widget=forms.SelectInput(choices=GENERO_CHOICES) ) website = forms.URLField() @henocdz
  11. Lo anterior mostraría esto en HTML <form> ... <select id="id_genero">

    <option value="0">Masculino</option> <option value="1">Femenino</option> </select> </form> @henocdz
  12. class StudentForm(forms.Form): # ... username = forms.CharField() password = forms.CharField(widget=forms.PasswordInput())

    website = forms.CharField() def clean_website(self): website = self.cleaned_data['website'] if len(website) < 5: raise forms.ValidationError('Longitud de website inválida') def clean(self): # ... if not self.cleaned_data['password'] and not self.cleaned_data['username']: raise forms.ValidationError('Debes indicar password y nombre de usuario') @henocdz
  13. Model Forms Podemos crear formularios a partir de un modelo

    e incluir o excluir los campos que queramos. # Con este modelo... from django.db import models class Student(models.Model): username = models.CharField(max_length=40) password = models.CharField(max_length=30) registro = models.DateTimeField(auto_now_add=True) @henocdz
  14. # Podemos crear este formulario from django import forms from

    app.models import Student class StudentForm(forms.ModelForm): class Meta: # Esta clase es importante # Aquí _configuramos_ nuestro formulario model = Student exclude = ['registro'] @henocdz
  15. # O algo más sofisticado con Widgets from django import

    forms from app.models import Student class StudentForm(forms.ModelForm): class Meta: # Esta clase es importante # Aquí _configuramos_ nuestro formulario model = Student fields = ['username', 'password'] widgets = { 'password': forms.PasswordInput() } @henocdz
  16. Class Based Views Nos permiten organizar la lógica de vistas

    de mejor manera, además evitar duplicidad de código. @henocdz
  17. Sesiones en Django Por default, el framework guarda información relacionada

    a la sesiones en el lado del servidor dentro de una tabla de la base de datos y al cliente solo le envía un ID de sesión para después poder extraer la información nuevamente. Más sobre el tema: https:/ /docs.djangoproject.com/en/dev/topics/ http/sessions/ @henocdz
  18. Cómo manipular las sesiones Podemos crear o extraer sesiones como

    si fuese un diccionario, aunque en realidad es un modelo que se se puede comportar como diccionario con el poder de __magic__ methods Primero, veamos como leer todo lo que tenemos en la sesión: def my_view(request): print(request.session.items()) @henocdz
  19. Crear un nuevo valor en la sesión def my_view(request): request.session['is_jedi']

    = False return HttpResponse('...') Extraer valor de una sesión def my_view(request): is_jedi = request.session.get('is_jedi', True) # Alternativa NO recomendada: # request.session['is_jedi'] return HttpResponse() @henocdz
  20. ¿Qué sesiones crear? Dependerá de cada aplicación. Y ... ¿cómo

    hago persistente el login de un usuario? @henocdz
  21. Sistema de usuarios de Django Django incluye por default un

    sistema de usuarios bastante genérico, podemos encontrarlo en: from django.contrib.auth.models import User Y después podemos... @henocdz
  22. Autenticarlos from django.contrib.auth import authenticate def my_view(request): user = authenticate(username='eme',

    password='123456') if not user: return HttpResponse('No existe el usuario') Aunque esto no significa que el usuario esté logeado y este login persista, para eso... @henocdz
  23. def authenticate(**credentials): for backend, backend_path in _get_backends(return_tuples=True): try: inspect.getcallargs(backend.authenticate, **credentials)

    except TypeError: # This backend doesn't accept these credentials as arguments. Try the next one. continue try: user = backend.authenticate(**credentials) except PermissionDenied: # This backend says to stop in our tracks - this user should not be allowed in at all. return None if user is None: continue # Annotate the user object with the path of the backend. user.backend = backend_path return user # The credentials supplied are invalid to all backends, fire signal user_login_failed.send(sender=__name__, credentials=_clean_credentials(credentials)) @henocdz
  24. ¿ Qué es un backend? Una clase que tiene dos

    métodos básicos authenticate y get_user, los cuales definen de donde extraer el usuario que se va a logear, así: from django.contrib.auth.backends import ModelBackend class LeadBackend(ModelBackend): def authenticate(self, username=None, auth_lead=False): if not username or not auth_lead: return None return get_object_or_None(ClientUser, email=username) def get_user(self, user_pk): """Returns ClientUser based on their PK""" return get_object_or_None(ClientUser, pk=user_pk) @henocdz
  25. ¿Cómo sabe Django con que Backends probar? Toma los que

    estén definidos en AUTHENTICATION_BACKENDS dentro de settings.py que por default es: ... AUTHENTICATION_BACKENDS = ( 'django.contrib.auth.backends.ModelBackend', ) ... @henocdz
  26. Para agregar más solo debes escribir una clase similar a

    la anterior y especificar aquí qué backends utilizar. Más info: https:/ /docs.djangoproject.com/en/dev/topics/auth/ customizing/#authentication-backends @henocdz
  27. Sistema de usuarios extendido ¿No les ha pasado que tienen

    distintos tipos de usuarios pero estos comparten ciertos atributos en común y algunos son muy particulares según el tipo de usuario? Podemos simplificar esto, pero antes Modelos Abstractos @henocdz
  28. Modelos abstractos Para este tipo de modelos no se crea

    una tabla en la base de datos, como estamos acostumbrados, únicamente nos sirven como base (herencia) para otros modelos y los atributos que tenga, se crearán en la tabla del modelo que utiliza al modelo abstracto @henocdz
  29. Por ejemplo from django.db import models class Usuario(models.Model): nombre =

    models.CharField(max_length=100) password models.CharField(max_length=30) class Meta: # Aquí es donde la magia ocurre abstract = True @henocdz
  30. Primero necesitamos un modelo base: from django.contrib.auth.models import AbstractBaseUser as

    DjAbstractBaseUser, PermissionsMixin class BaseUser(DjAbstractBaseUser, PermissionsMixin): def __str__(self): return "{}".format(self.pk) @henocdz
  31. Después un modelo abstracto que defina los campos en común

    class AsistiaAbstractBaseUser(BaseUser): """Defines common attributes among Asistia User Types""" email = models.EmailField(unique=True, db_index=True) # NOQA is_admin = models.BooleanField(default=False) is_active = models.BooleanField(default=False) last_edit_date = models.DateTimeField(auto_now=True) objects = UserManager() USERNAME_FIELD = 'email' REQUIRED_FIELDS = ['first_name', 'surname'] class Meta: # This model should not be create in the database abstract = True @property def is_staff(self): """Returns if the user can access to Django Admin site""" return self.is_admin @henocdz
  32. ¿UserManager? Contiene las funciones a utilizar para crear un usuario,

    por ejemplo con el comando python manage.py createsuperuser @henocdz
  33. from django.contrib.auth.models import BaseUserManager class UserManager(BaseUserManager): def create_user(self, email, **kwargs):

    if not email: raise ValueError('Users must have an email') user = self.model( email=self.normalize_email(email), ... **kwargs ) password = kwargs.pop('password', None) user.set_password(password) return user def create_superuser(self, *args, **kwargs): user = self.create_user(*args, **kwargs) user.is_admin = True user.is_active = True user.is_superuser = True return user @henocdz
  34. Y después en cada tipo de usuario que tengamos, debemos

    heredar de el modelo abstracto class DefaultUser(AbstractBaseUser): """ Generic User Type - The one used in AUTH_USER_MODEL for Django Settings """ pass @henocdz
  35. Y lo más importante, decirle a Django que Modelo de

    usuario utilizar por default para python manage.py createsuperuser entre otras cosas. # En nuestro settings.py AUTH_USER_MODEL = 'users.DefaultUser' @henocdz