Slide 1

Slide 1 text

Django! carlos de las Heras sánchez [email protected]

Slide 2

Slide 2 text

Django es un framework para el desarrollo de aplicaciones web en lenguaje python https://github.com/django https://www.djangoproject.com/

Slide 3

Slide 3 text

¿Aplicaciones WEB? ¿No son páginas web? ¿Framework? ¿qué es un Framework? ¿Hay otros Frameworks?

Slide 4

Slide 4 text

ClientE Servidor Petición HTTP a una URL HTML Petición / Respuesta Django base de datos Plantilla Renderizada Petición Respuesta 1. 2. 3.

Slide 5

Slide 5 text

Model cómo son las cosas view cómo se procesan Template cómo se representan https://www.slideshare.net/jamescasey/introduction-to-django Arquitectura MVT

Slide 6

Slide 6 text

Plantillas {% extends "base.html" %}

My first name is {{ first_name }}.

My last name is {{ last_name }}.

templates/example_template.html ... templates/base.html Herencia / extensión de plantillas

Slide 7

Slide 7 text

Vistas Son funciones que… 1. toman una petición 2. renderizan una plantilla con un contexto 3. y devuelven una respuesta def example_view(request): context = {'first_name': 'John', 'last_name': 'Doe'} return render(request, 'example_template.html', context)

Slide 8

Slide 8 text

Urls from django.conf.urls import url from . import views urlpatterns = [ url(r'^example/$', views.example_view) ]

Slide 9

Slide 9 text

ORM Object-Relational Mapping # settings.py DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': 'mydatabase', } } ORM ORM sqlite3 postgres

Slide 10

Slide 10 text

Modelos class Band(models.Model): """A model of a rock band.""" name = models.CharField(max_length=200) can_rock = models.BooleanField(default=True) class Member(models.Model): """A model of a rock band member.""" name = models.CharField("Member's name", max_length=200) instrument = models.CharField(max_length=50) band = models.ForeignKey("Band")

Slide 11

Slide 11 text

Admin # admin.py from django.contrib import admin from bands.models import Band, Member admin.site.register(Band) admin.site.register(Member)

Slide 12

Slide 12 text

Recursos Útiles https://www.djangoproject.com/ https://tutorial.djangogirls.org/es/

Slide 13

Slide 13 text

DjangoCon

Slide 14

Slide 14 text

¡Todos somos Bienvenidos!

Slide 15

Slide 15 text

Django’s watching my back(end) @DjangoCon2017

Slide 16

Slide 16 text

Remember… the year 2003

Slide 17

Slide 17 text

Django, The new Kid in the Block: What did it aim to solve?

Slide 18

Slide 18 text

“A weird(er) Internet” The year 2017

Slide 19

Slide 19 text

Client Server Client Server HTTP Request form POST HTTP Request AJAX “Traditional” Lifecycle SPA Lifecycle HTML HTML HTML { JSON } Refresh

Slide 20

Slide 20 text

Downloads and Requests time “Eager” Loading “Lazy” Loading “With Refresh” Loading time time SPA Django

Slide 21

Slide 21 text

Websockets Client Server HTTP Websockets vs. Ajax… - Lower overhead - Full duplex

Slide 22

Slide 22 text

a newer Paradigm... A new set of problems!

Slide 23

Slide 23 text

So... Why not API / SPA all the way as a Proof of concept?

Slide 24

Slide 24 text

valoohome.com

Slide 25

Slide 25 text

“Requirements” Real Estate App Mobile First. Posible Native App. Consumes diverse APIs User login Registration with email verification Bleeding edge Django (1.11) Angular2 + Material2 HTTPS everywhere

Slide 26

Slide 26 text

Structure Client Server HTTP Request aJAX Angular2 app { JSON } Google API Appraisal API (Flask) Cadastre API / /api Django nginx

Slide 27

Slide 27 text

The Toolbox # Django REST Framework djangorestframework==3.4.7 Djangorestframework-jwt==1.8.0 # Django CORS Django-cors-headers==1.2.2 # Authentication and Registration django-allauth==0.29.0 Django-rest-auth==0.9.1 THIRD_PARTY_APPS = ( ... 'rest_framework', 'rest_framework.authtoken', 'corsheaders', 'allauth', 'allauth.account', 'rest_auth', 'rest_auth.registration', )

Slide 28

Slide 28 text

Some Considerations ● Use HTTPS everywhere! ● API design that minimizes calls from front-end. ● API endpoints start with /api/ ● “Forms” are not really forms. ● Services. ● Handle all possible exceptions!

Slide 29

Slide 29 text

Authentication and Permissions (I) # Django REST Framework # ---------------------------------------------------------------------- REST_FRAMEWORK = { 'DEFAULT_RENDERER_CLASSES': ( 'rest_framework.renderers.JSONRenderer', ), 'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.IsAuthenticated', ), 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', ), 'TEST_REQUEST_DEFAULT_FORMAT': 'json' }

Slide 30

Slide 30 text

Authentication and Permissions (II) # django-rest-auth # ------------------------------------------------------------------- REST_SESSION_LOGIN = False REST_USE_JWT = True REST_AUTH_SERIALIZERS = { 'USER_DETAILS_SERIALIZER': 'path.to.custom.UserDetailsSerializer' 'LOGIN_SERIALIZER': 'path.to.custom.LoginSerializer', 'TOKEN_SERIALIZER': 'path.to.custom.TokenSerializer', ... }

Slide 31

Slide 31 text

Authentication and Permissions (III) @api_view(['POST']) @permission_classes((AllowAny,)) def example_function_based_view(request): ... class ExampleClassBasedView(generics.RetrieveAPIView): permission_classes = (AllowAny,) ...

Slide 32

Slide 32 text

JWT (I) JWT – JSON Web Tokens ● JSON-based open standard (RFC 7519) ● Access tokens for a number of claims: In my case, just “logged in” ● Stateless authentication mechanism. No session. ● JSON Web Token stored locally. Signed, so it can be decoded. ● Authorization header using the Bearer or JWT schema Authorization: JWT

Slide 33

Slide 33 text

JWT (II) eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImNhaGVyc2FuQGdtYWlsLmNvb SIsIm9yaWdfaWF0IjoxNDg5MjQyODUwLCJlbWFpbCI6ImNhaGVyc2FuQGdtYWlsLmNvbSIsImV4cCI 6MTQ4OTI1NzI1MCwidXNlcl9pZCI6ImU3Yzg0OGQyLWYzM2UtNDNjNS05M2ZlLTFlMGQ1MDhhMzEyN iJ9.R5fNmHMBuvsscvrxRiAzEpEGAeEJQCSgr2VnniGSeUw { “email”: "[email protected]", “exp”: 1489257531, “orig_iat”: 1489243131, “user_id”: "e7c848d2-f33e-43c5-93fe-1e0d508a3126", “username”: "[email protected]" }

Slide 34

Slide 34 text

JWT (III) # JWT Token configuration -------------------------------------------------------------------- JWT_AUTH = { 'JWT_EXPIRATION_DELTA': datetime.timedelta(hours=4), 'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(hours=12), 'JWT_LEEWAY': datetime.timedelta(seconds=30), 'JWT_ALLOW_REFRESH': True, } https://github.com/GetBlimp/django-rest-framework-jwt

Slide 35

Slide 35 text

“Logging In” (I) 1. Front makes a request to Login url 2. Token is sent back to the front 3. Token is stored in browser’s local storage Backend from rest_auth.views import LoginView from rest_framework_jwt.views import refresh_jwt_token urlpatterns = [ url(r'^api/get-token/', LoginView.as_view()), url(r'^api/refresh-token/', refresh_jwt_token) ]

Slide 36

Slide 36 text

“Logging In” (II) Frontend this.http .post( environment.backend_url + `/api/get-token/`, JSON.stringify({ email: email, password: password }), options) .map(r => localStorage.setItem('id_token', r.json().token))

Slide 37

Slide 37 text

Registration (I) Front-enD Server { response } Django /api/registration /api/verify-email link { response } { email, pass_1, pass_2 } { key: } https://github.com/Tivix/django-rest-auth /#/verify-email/

Slide 38

Slide 38 text

Registration (II) Settings THIRD_PARTY_APPS = ( ... 'rest_auth', 'rest_auth.registration' ) CONFIRM_EMAIL_URL = '/#/users/verify-email/' ACCOUNT_ADAPTER = 'path.to.CustomAccountAdapter' ACCOUNT_AUTHENTICATION_METHOD = 'email' ACCOUNT_EMAIL_VERIFICATION = 'mandatory' Templates templates/account/email/email_confirmation_message.txt templates/account/email/email_confirmation_subject.txt

Slide 39

Slide 39 text

Registration (III) URLs url(r'^registration/', include('rest_auth.registration.urls')), url(r'^url-for-account-confirm-email//$', APIView.as_view(), name='account_confirm_email'), url(r"^url-for-confirm-email/$", APIView.as_view(), name="account_email_verification_sent") Adapter class CustomAccountAdapter(DefaultAccountAdapter): def get_email_confirmation_url(self, request, emailconfirmation): url = settings.CONFIRM_EMAIL_URL + emailconfirmation.key ret = build_absolute_uri(request, url) return ret

Slide 40

Slide 40 text

Testing class EndpointsTestCase(TestCase): def setUp(self): self.user = User.objects.create_user(...) self.client = APIClient() payload = jwt_payload_handler(self.user) self.token = jwt_encode_handler(payload) def test_get(self): response = self.client.get( '/api/endpoint/, HTTP_AUTHORIZATION='JWT %s' % self.token )

Slide 41

Slide 41 text

CORS (I) Frontend A Server Same-origin request (always allowed) Frontend B notmywebapp.com mywebapp.com Cross-origin request (Allowed by CORS) mywebapp.com Frontend C EVILWEBAPP.com Cross-origin request (NOT allowed by CORS) Cross-Origin Resource Sharing

Slide 42

Slide 42 text

CORS (II) https://github.com/ottoyiu/django-cors-headers # While developing CORS_ORIGIN_WHITELIST = (localhost:4200’,) # Frontend Dev Server CORS_ORIGIN_ALLOW_ALL = True THIRD_PARTY_APPS = ( ... 'corsheaders', ... ) MIDDLEWARE = ( ... 'corsheaders.middleware.CorsMiddleware', ... )

Slide 43

Slide 43 text

CORS / CSRF (III) SessionAuthentication Include valid CSRF tokens for any POST, PUT, PATCH or DELETE operations Django implements Double Submit Cookie If the client sends a 'X-XSRF-TOKEN' header, then set to 'HTTP_X_XSRF_TOKEN'. Django Angular2 CSRF_HEADER_NAME HTTP_X_CSRFTOKEN X-XSRF-TOKEN CSRF_COOKIE_NAME csrftoken XSRF-TOKEN

Slide 44

Slide 44 text

To sum up...

Slide 45

Slide 45 text

Why / Where Django? ● Lots of ORM → YES ● Async → Probably no What’s cooL? ● Internationalization ● The Admin ● It’s Python ● Security ● Third-party apps

Slide 46

Slide 46 text

Django could be a way of thinking vs. A set of tools An Internet Framework vs. A web framework

Slide 47

Slide 47 text

Django will still be relevant… if we manage to leverage newer paradigms and technologies

Slide 48

Slide 48 text

Gracias!!