Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.
Vue.js con Django
¿tiene sentido? @javierabadia
@VueJSMadrid
¿Tiene sentido una SPA con backend?
• Autenticación
• Persistencia
• Proceso de Datos
• Acceso a almacenes
de datos extern...
¿por qué Django frente a Node.js?
La experiencia ‘óptima’ de desarrollo
• Trabajar de forma unificada
(mismo IDE)
• Desarrollo en el backend
• debugging
• b...
La estructura clásica de Django
Vistas
Templates
Modelos
ORM
Autenticación
Middleware
Formularios
Administración
HTML
Ejemplo: Catálogo de GIFs para IoT
http://localhost:8000/ http://localhost:8000/detail/323
DEMO
Arquitectura de una SPA de Vue.js
$ vue init webpack-simple frontend
$ cd frontend
$ yarn
$ npm run dev
localhost:8080
El puente entre Django y Webpack
$ cd frontend
$ npm install --save-dev webpack-bundle-tracker
# (en un virtualenv, por su...
Todo junto
var path = require('path')
var webpack = require('webpack')
var BundleTracker = require('webpack-bundle-tracker...
def index(request):
return render(request, 'index.html', {})
# backend/views.py
{% extends 'base.html' %}
{% load render_b...
Webpack: detalles de configuración
var path = require('path')
var webpack = require('webpack')
var BundleTracker = require...
Django
:8000
localhost:8000/
HTML
localhost:8000/api/*
JSON
Implementar una API ¿REST?
urlpatterns = [
url(r'^api/pics', api.pics),
url(r'^', views.index),
]
# backend/urls.py
def pi...
Autenticación
Una posible implementación: 2PA
http://localhost:8000/login http://localhost:8000/*
create session
redirect
...
Django + auth + sessions
<script>
export default {
name: 'app',
data() {
return {
msg: 'Welcome to Your Vue.js App!',
user...
DEMO
Rutas
urlpatterns = [
url(r'^api/suggestions/$', api.suggestions),
url(r'^api/search/$', api.search),
url(r'^api/pics/(?P<...
Comentarios Finales
• APIs
• REST?
• ‘a pelo’
• django-tastypie
• django-rest-framework
• GraphQL
• graphene (django)
• ap...
Conclusión
Referencias
• Doc de Vue: https://vuejs.org/v2/guide/single-file-components.html
• Doc de Webpack: https://webpack.js.org/...
Gracias!
@javierabadia
Próxima SlideShare
Cargando en…5
×

Vue.js + Django - configuración para desarrollo con webpack y HMR

2.189 visualizaciones

Publicado el

Presentación del meetup de Vue.js en Madrid, el 12/Sep/2017 donde explicamos cómo configurar Django y webpack para desarrollar SPAs con Vue.js y backend con Django: incluye configuración de Hot-Module-Reloading, autenticación, API y rutas.

El código de ejemplo se puede encontrar aquí: https://github.com/jabadia/gif_catalog

Publicado en: Tecnología
  • Sé el primero en comentar

Vue.js + Django - configuración para desarrollo con webpack y HMR

  1. 1. Vue.js con Django ¿tiene sentido? @javierabadia @VueJSMadrid
  2. 2. ¿Tiene sentido una SPA con backend? • Autenticación • Persistencia • Proceso de Datos • Acceso a almacenes de datos externos • elasticsearch • mongodb • … • Acceso a APIs externas • …
  3. 3. ¿por qué Django frente a Node.js?
  4. 4. La experiencia ‘óptima’ de desarrollo • Trabajar de forma unificada (mismo IDE) • Desarrollo en el backend • debugging • breakpoints, etc • Desarrollo en el frontend • con agilidad • usando Hot Module Replacement (HMR)
  5. 5. La estructura clásica de Django Vistas Templates Modelos ORM Autenticación Middleware Formularios Administración HTML
  6. 6. Ejemplo: Catálogo de GIFs para IoT http://localhost:8000/ http://localhost:8000/detail/323
  7. 7. DEMO
  8. 8. Arquitectura de una SPA de Vue.js $ vue init webpack-simple frontend $ cd frontend $ yarn $ npm run dev localhost:8080
  9. 9. El puente entre Django y Webpack $ cd frontend $ npm install --save-dev webpack-bundle-tracker # (en un virtualenv, por supuesto) $ pip install django-webpack-loader
  10. 10. Todo junto var path = require('path') var webpack = require('webpack') var BundleTracker = require('webpack-bundle-tracker'); module.exports = { … plugins: [ new BundleTracker({filename: './webpack-stats.json'}) ] } // frontend/webpack.conf.js {% extends 'base.html' %} {% load render_bundle from webpack_loader %} {% block content %} <div id="app"></div> {% render_bundle 'main' %} {% endblock %} {# backend/templates/index.html #} { "status": "done", "publicPath": "http://localhost:8080/dist/", "chunks": { "main": [ { "name": "build.js", "publicPath": "http://localhost:8080/dist/build.js", "path": "/Users/jami/…/gif_catalog/frontend/dist/build.js" } ] } } // frontend/webpack-stats.json … WEBPACK_LOADER = { 'DEFAULT': { 'BUNDLE_DIR_NAME': 'dist/', 'STATS_FILE': os.path.join(BASE_DIR, 'frontend/webpack-stats.json'), } } # settings.py
  11. 11. def index(request): return render(request, 'index.html', {}) # backend/views.py {% extends 'base.html' %} {% load render_bundle from webpack_loader %} {% block content %} <div id="app"></div> {% render_bundle 'main' %} {% endblock %} {# backend/templates/index.html #} Django :8000 Webpack :8080 urlpatterns = [ url(r'^', views.index), ] # backend/urls.py App.vue main.js *.vue localhost:8000/ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> … </head> <body> <div id="app"></div> <script type="text/javascript" src="http://localhost:8080/dist/build.js"> </script> </body </html> HMRbuild.js
  12. 12. Webpack: detalles de configuración var path = require('path') var webpack = require('webpack') var BundleTracker = require('webpack-bundle-tracker'); module.exports = { entry: './src/main.js', output: { path: path.resolve(__dirname, './dist'), publicPath: 'http://localhost:8080/dist/', filename: 'build.js' }, module: { ... }, devServer: { historyApiFallback: true, noInfo: true, headers: { 'Access-Control-Allow-Origin': '*' } }, plugins: [ new BundleTracker({filename: './webpack-stats.json'}) ] } url absoluta incluyendo puerto activar CORS para que el cliente HMR pueda hacer peticiones al devServer de webpack // webpack.config.js
  13. 13. Django :8000 localhost:8000/ HTML localhost:8000/api/* JSON
  14. 14. Implementar una API ¿REST? urlpatterns = [ url(r'^api/pics', api.pics), url(r'^', views.index), ] # backend/urls.py def pics(request): count = GifPicture.objects.all().count() all_ids = range(count) random.shuffle(all_ids) picked_ids = all_ids[:18] gif_pictures = GifPicture.objects .filter(id__in=picked_ids) .order_by('-upload_date') result = { 'pics': gif_pictures, } return JsonResponse(result) # backend/api.py import axios from 'axios'; export default { getRandomPics() { return axios.get('/api/pics') .then(response => { return response.data.pics; }); }, } // gifPicsApi.js Django :8000 … <script> import gifPicsApi from '../services/gifPicsApi.js'; export default { … mounted() { gifPicsApi.getRandomPics().then(pics => { this.pics = pics; }); }, }; </script> // GifHome.vue
  15. 15. Autenticación Una posible implementación: 2PA http://localhost:8000/login http://localhost:8000/* create session redirect set cookie vue-routing
  16. 16. Django + auth + sessions <script> export default { name: 'app', data() { return { msg: 'Welcome to Your Vue.js App!', user: {}, } }, created() { this.user = window.user; }, } </script> // App.vue @login_required def index(request): context = { 'user': request.user, } return render(request, 'index.html', context) # backend/views.py {% extends 'base.html' %} {% load render_bundle from webpack_loader %} {% block content %} <div id="app"></div> <script> var user = { username: "{{ user.username }}", email: "{{ user.email }}", }; </script> {% render_bundle 'main' %} {% endblock %} # backend/templates/index.html
  17. 17. DEMO
  18. 18. Rutas urlpatterns = [ url(r'^api/suggestions/$', api.suggestions), url(r'^api/search/$', api.search), url(r'^api/pics/(?P<id>[0-9]+)$', api.pic_details), url(r'^api/pics/$', api.pics), url(r'^', views.index), ] # backend/urls.py Vue.use(Router); const router = new Router({ mode: 'history', routes: [ { path: '/', name: 'home', component: GifHome },{ path: '/detail/:id', name: 'detail', component: GifDetail, props:true },{ path: '*', component: Error404 }, // Not found ], }); # router.js urlpatterns = [ url(r'^admin/', admin.site.urls), url('^', include('django.contrib.auth.urls')), url(r'^', include('backend.urls')) ] # urls.py /login /logout
  19. 19. Comentarios Finales • APIs • REST? • ‘a pelo’ • django-tastypie • django-rest-framework • GraphQL • graphene (django) • apollo (vue) • (no lo he probado) • Server Side Rendering • nope • seeding • sip • SEO • pre-render • inyectar contenido en Django
  20. 20. Conclusión
  21. 21. Referencias • Doc de Vue: https://vuejs.org/v2/guide/single-file-components.html • Doc de Webpack: https://webpack.js.org/ • SurviveJS: https://survivejs.com/webpack/ • webpack-bundle-tracker: https://github.com/ezhome/webpack-bundle-tracker • django-webpack-loader: https://github.com/ezhome/django-webpack-loader • hello-vue + Django project: https://github.com/rokups/hello-vue-django • modernize Django frontend: http://owaislone.org/blog/modern-frontends-with-django/ • Django + REACT with HMR: http://owaislone.org/blog/webpack-plus-reactjs-and-django/
  22. 22. Gracias! @javierabadia

×