Iterando rápido con Django y Heroku

Lanzar un negocio en línea puede resultar muy complicado. Aunque en papel, es mucho más fácil crear un negocio en línea que uno de ladrillo y mortero, un empresario puede perderse en la multitud de opciones. Algunos de los escollos más comunes en los que se atasca un empresario en línea incluyen:

  • Construyendo demasiado pronto: Pierde tiempo y quema dinero construyendo un producto complejo. Demórese en el camino, pierda la fe en el producto y abandone el proyecto..
  • Creer demasiado en la idea.: Atascarse con la idea original y no iterarla, aunque los clientes no se presentan, no pagan o no están satisfechos.
  • No comenzar: Cuando alguien comienza a construir un proyecto web, él / ella puede sentirse abrumado por las decisiones y decisiones aparentemente infinitas que deben tomarse. ¿Qué hosting utilizar? ¿Qué plataforma? ¿Qué tema de WordPress? ¿Cómo construir una página de inicio de alta conversión? ¿Qué lenguaje de programación y qué base de datos? ¿Deberías usar un framework web? ¿Vanilla JavaScript o jQuery para la parte delantera? Tal vez un marco frontal más complejo porque el proyecto lo necesitará una vez que esté lo suficientemente maduro?
  • No lanzar: Cuando creas un proyecto web, aunque te decidiste por tu pila de tecnología, puedes sentirte abrumado por los comentarios que recibes. Contraintuitivamente, se considera un error escuchar demasiados comentarios. Puede ser la respuesta de las personas que de todos modos no utilizarían su producto. Las personas tienden a tener una opinión sobre todo, a pesar de que no están completamente informados en el campo..

Dada la multitud de formas en que uno puede fallar en el camino, es realmente importante:

  • Desarrolle lo menos posible y tan rápido como sea posible, mostrándolo a las personas que considere clientes potenciales: Minimizar costes y esfuerzo..
  • Ponlo en línea lo antes posible.: Obtenga comentarios de personas sobre el producto, no sobre su idea abstracta.
  • Hacer cambios rapidamente: Cuando aprenda lo que quiere el cliente, es crucial ser ágil y atender bien a sus clientes que pagan por primera vez.

Aquí es donde entra en juego la creación de prototipos. Un empresario debe correr magro, no perder tiempo y recursos. Construir lo menos posible al principio puede ser una virtud.. 

Hay muchas escuelas de pensamiento sobre qué es un prototipo y cómo se debe crear. Algunos dicen que debería ser solo una página de destino, otros que debería ser una versión simplificada del producto final. Soy más fan del segundo. Usar solo una página de destino puede parecer una estafa. Además, no puede obtener comentarios sobre cómo está resolviendo el problema, sino solo si el problema vale la pena resolverlo..

Aquí está el cinturón de herramientas de un empresario de prototipos inteligentes en línea:

  • Marcos front-end: Bootstrap, Foundation, jQuery, Vue, etc. El uso de un marco de front-end hará que sus aplicaciones funcionen en diferentes tamaños de pantalla y diferentes navegadores, con un diseño decente.
  • Marcos de back-end: Django, Ruby on Rails, Laravel. El uso de marcos de back-end lo ayudará a lidiar fácilmente con plantillas HTML, formularios HTTP, acceso a bases de datos, esquemas de URL, etc..
  • Plataforma como servicio: Heroku, Google App Engine, AWS Elastic Beanstalk. La elección de un PaaS puede liberarlo del dolor de la administración de servidores, la agregación de registros, el monitoreo del tiempo de actividad, la infraestructura de implementación y más.

En este tutorial, crearemos una aplicación simple en el espíritu de la creación rápida de prototipos. Usaremos Django, Bootstrap CSS y Heroku. El foco estará en la parte de back-end en lugar de la parte delantera. 

Vamos a aprovechar la plataforma Heroku para poner algo en línea temprano y para desplegar rápidamente nuevas funciones. Vamos a utilizar Django para construir modelos de bases de datos complejos y funcionalidad. Bootstrap CSS nos dará un estilo predeterminado razonable para nuestras páginas. Basta de hablar, vamos.

Lo que estamos construyendo

Asegúrate de estar sentado para esto. La idea te sacará los calcetines. Aquí está el mensaje: no odias cómo obtienes todos estos códigos de descuento, pero te olvidas de usarlos y caducan.? 

¿No sería genial almacenar los códigos en algún lugar donde puedas buscarlos y también recibir notificaciones cuando estén a punto de caducar? Lo sé, gran idea, ¿verdad? Bueno, baja tu tarjeta de crédito, no invertirás en esta. Lo vas a construir.

Empezando

En este tutorial, usaré Python 3. Si está usando Python 2.7, los cambios deberían ser bastante fáciles. También voy a asumir que estás familiarizado con herramientas de configuración, Python virtualenvs, y Git. Una cosa más antes de seguir adelante: asegúrate de tener una cuenta de GitHub y de Heroku. Para utilizar Heroku, también necesita instalar el CLI de Heroku. 

Empecemos creando un virtualenv:

$ mkvirtualenv coupy

Como probablemente se haya dado cuenta, el nombre de nuestra aplicación es Coupy. Cambiemos al nuevo virtualenv., $ workon coupy, e instalar Django: 

$ pip instala Django

Entra en tu cuenta de GitHub y crea un nuevo proyecto. A continuación, vamos a clonar ese proyecto:

$ git clone https://github.com//.git $ cd 

El siguiente paso lógico es crear un proyecto Django. Para implementar un proyecto Django en Heroku, debemos seguir algunas pautas. Afortunadamente, podemos usar una plantilla de proyecto para eso. Aquí está cómo hacer eso:

$ django-admin.py startproject --template = https: //github.com/heroku/heroku-django-template/archive/master.zip --name = Procfile coupy

Es posible que necesite moverse alrededor de algunas carpetas. Asegúrate de que la carpeta raíz de tu repositorio se vea así:

. ├── Procfile ├── README.md ├── coupy │ ├── __init__.py ├── ├── settings.py │ ├── static │ │ └── humans.txt │ ├── urls.py │ └ ── wsgi.py ├── manage.py ├── Requirements.txt └── runtime.txt

Ahora instalemos los requisitos provistos por la plantilla:

$ pip install -r Requirements.txt

Ahora queremos enviar los archivos recién creados a GitHub:

$ git añadir. $ git commit -m "Init Django project" $ git push origin master

Veamos si lo que hemos hecho hasta ahora funciona:

$ python manage.py runserver

Ahora abra una ventana del navegador y vaya a http: // localhost: 8000. Si todo está bien, debería ver la página de bienvenida clásica de Django. Para asegurarnos de que todo sea bueno desde la perspectiva de Heroku, también podemos ejecutar la aplicación de esta manera:

$ heroku web local

Para demostrar la rapidez con la que podemos conectarse, hagamos nuestro primer despliegue en Heroku:

$ heroku login $ heroku crear

Ahora hemos creado una aplicación Heroku, pero no hemos enviado ningún código a Heroku. Tenga en cuenta que Heroku creó una ID de aplicación fácil de usar. Aquí está la salida que debe obtener:

Creación de la aplicación ... hecho, ⬢  https: //.herokuapp.com/ | https://git.heroku.com/.git

Ahora debemos asociar nuestro repositorio con la aplicación Heroku recién creada:

$ heroku git: remoto -a  $ git push heroku master $ heroku abierto

Impresionante, acabas de desplegar una aplicación para Heroku. No hace mucho, pero pones algo en línea en un tiempo récord. Buen trabajo.

Configuración de la base de datos

Probablemente nunca construirá una aplicación web no trivial sin una base de datos. La base de datos es la parte de almacenamiento de datos de la aplicación web. Aquí es donde la aplicación web mantiene su estado (al menos la mayor parte). Aquí es donde guardamos las cuentas de usuario y los detalles de inicio de sesión y mucho, mucho más. Heroku proporciona un servicio gestionado de PostgreSQL.. 

Eso es lo que vamos a utilizar. Asegúrese de haber instalado Postgres en su máquina y cree una instancia de base de datos para usar en nuestra aplicación. Heroku necesita una variable de entorno que se establezca para poder conectarse al servicio de base de datos. La variable que necesitamos establecer es DATABASE_URL:

$ export DATABASE_URL = "postgres: //:@localhost: 5432 /"

Ahora digamos a Django que aplique las migraciones y cree las tablas necesarias:

$ ./manage.py migrate

Vamos a crear un superusuario e iniciar sesión en la interfaz de administración en http: // localhost: 8000 / admin:

$ ./manage.py crea usuario superpuesto $ ./manage.py runserver

Podemos ver que las tablas han sido creadas. Heroku ya ha asociado una instancia de base de datos a su aplicación de forma predeterminada. Puedes asegurarte de que ese sea el caso registrándote en Heroku HEROKU_APP_ID> Configuraciones> Configurar variables En tu consola Heroku en línea. Debes ver aquí que la DATABASE_URL se establece en una dirección de base de datos generada Heroku. 

Ahora tenemos que ejecutar las migraciones y crear los comandos de superusuario en línea. Veamos si todo funciona como se espera:

$ heroku ejecuta python manage.py migra $ heroku ejecuta python manage.py creasusuperusuario

Si todo fue bien, si nos visita. https: //.herokuapp.com/admin/, deberíamos poder iniciar sesión con las credenciales que acabamos de proporcionar.

Autenticacion de usuario

En esta sección, vamos a inicializar una aplicación Django y usar componentes predefinidos de Django para crear la funcionalidad de autenticación de usuario en nuestra aplicación..

$ ./manage.py startapp main

Dentro de la nueva aplicación, vamos a crear una urls.py expediente:

desde django.conf.urls importar url desde django.contrib.auth importar vistas como auth_views desde django.views.generic.base importar RedirectView urlpatterns = [url ('^ $', RedirectView.as_view (url = 'login'), nombre = "index"), url (r '^ login $', auth_views.LoginView.as_view (), name = "login"), url (r '^ logout $', auth_views.LogoutView.as_view (), name = " cerrar sesión"), ] 

Aquí usamos tres vistas genéricas de Django:

  • RedirectView: Dado que la URL base de la aplicación no hace nada, estamos redirigiendo a la página de inicio de sesión.
  • LoginView: Vista predefinida de Django que crea el formulario de inicio de sesión e implementa la rutina de autenticación del usuario.
  • LogoutView: Django vista predefinida que cierra la sesión de un usuario y redirige a una página determinada.

Añade el principal aplicación a la INSTALLED_APPS lista:

INSTALLED_APPS = ['django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', # Deshabilitar el manejo de archivos estáticos de Django en favor de WhiteNoise, para # mayor consistencia entre gunicorn y './manage.py runserver'. Consulte: # http://whitenoise.evans.io/en/stable/django.html#using-whitenoise-in-development 'whitenoise.runserver_nostatic', 'django.contrib.staticfiles', 'main',]

Conecte el main.urls al esquema de URL raíz:

desde django.conf.urls importar url, incluir desde django.contrib importar admin urlpatterns = [url (r '^', include ('main.urls')), url (r '^ admin /', admin.site.urls ),]

Para poder mostrar los formularios correctamente, con estilos, clases y todo, necesitamos instalar django-widget-tweaks:

$ pip instala django-widget-tweaks $ pip freeze> Requirements.txt

Añadir django-widget-tweaks a INSTALLED_APPS:

INSTALLED_APPS = [#… 'main', 'widget_tweaks',]

Ahora agregamos estas dos configuraciones a settings.py:

  • LOGIN_REDIRECT_URL: Le dice a Django dónde redirigir a un usuario después de una autenticación exitosa.
  • LOGOUT_REDIRECT_URL: Le dice a Django dónde redirigir al usuario después de que se desconecte.
# settings.py LOGIN_REDIRECT_URL = 'dashboard' LOGOUT_REDIRECT_URL = 'login'

Vamos a escribir una plantilla maestra simple base.html y un dashboard.html Plantilla que lo amplía. Regresaremos al tablero uno más tarde..

     % block title% % endblock%   
% block content% % endblock%
% extiende 'base.html'% % block title% Tablero % endblock% % contenido de bloque% 

Tablero

% endblock%

Escribe la vista que hace que el dashboard.html modelo:

desde django.shortcuts importar render desde django.core.urlresolvers importar reverse_lazy @login_required (login_url = reverse_lazy ('login')) def dashboard (request): return render (request, 'dashboard.html')

Estamos listos. Dirigirse a http: // localhost: 8000 / login / y prueba que la autenticación funciona. A continuación, guarde su progreso:

$ git añadir. $ git commit -m "Iniciar sesión / Cerrar sesión / Vistas de panel"

Crear el modelo de cupón

Ahora hemos llegado a la parte más importante de nuestra aplicación, diseñando el modelo de cupón. Estaremos instalando django-model-utils Para agregar algunas propiedades extra a nuestros modelos..

$ pip instala django-model-utils $ pip freeze> Requirements.txt

Escribe el Cupón modelo:

desde model_utils.models import TimeStampedModel, TimeFramedModel desde django.db import modelos desde django.contrib.auth.models import User Class Coupon (TimeStampedModel, TimeFramedModel): propietario = models.ForeignKey (User) , max_length = 100) website = models.URLField ("Website") description = models.TextField ("Description Coupon")

los django-model-utils Los modelos que ampliamos nos permiten:

  • TimeStampedModel nos ayuda a rastrear cuándo se colocó el modelo en la base de datos, a través de creado campo.
  • TimeFramedModel agrega el comienzo y fin Campos a nuestro modelo. Estamos utilizando estos campos para realizar un seguimiento de la disponibilidad del cupón.

Enganche el modelo al administrador:

desde django.contrib importar administrador desde .models importar Cupón @ admin.register (Cupón) clase CouponAdmin (admin.ModelAdmin): pasar

Crear y aplicar migraciones:

$ ./manage.py makemigrations $ ./manage.py migrate

Guardar progreso:

$ git añadir. $ git commit -m "Crear modelo de cupón"

ModelForm para la creación de cupones

Una de las características interesantes de Django es la capacidad de crear formularios a partir de clases modelo. Vamos a crear un formulario que permita a los usuarios crear cupones. Vamos a crear un forms.py archivo dentro de la principal solicitud:

desde django.forms importa ModelForm desde .models importa clase de cupón CouponForm (ModelForm): class Meta: model = Coupon exclude = ('owner',) # Estamos configurando este campo nosotros mismos

Vamos a añadir este formulario al panel de control. Necesitamos cambiar tanto la vista como la plantilla:

# views.py desde django.shortcuts importar render, redirigir desde django.core.urlresolvers importar reverse_lazy desde .forms import CouponForm @login_required (login_url = reverse_lazy ('login')) def dashboard (request): si request.method == ' POST ': form = CouponForm (request.POST) si form.is_valid (): coupon = form.save (commit = False) coupon.owner = request.user coupon.save () return redirect (' dashboard ') else: form = CouponForm () devuelve render (solicitud, 'dashboard.html', context = 'create_form': form)
% extiende 'base.html'% % load widget_tweaks% % block title% Tablero % endblock% % block content% 

Tablero

% csrf_token%
% render_field create_form.discount_code placeholder = "Código de descuento"%
% render_field create_form.website placeholder = "Website"%
% render_field create_form.description placeholder = "Description"%
% render_field create_form.start placeholder = "Available From (MM / DD / YYYY)"%
% render_field create_form.end placeholder = "Expires On (MM / DD / YYYY)"%
% endblock%

Ahora tenemos una forma de crear cupones desde el panel de control. Ve y pruébalo. No tenemos forma de ver los cupones en el panel, pero podemos hacerlo en el panel de administración. Guardemos el progreso:

$ git añadir. $ git commit -m "Formulario de creación de cupones en el panel"

Venciendo pronto cupones

Una cosa más que queremos que se muestre en el panel de control: cupones que vencen pronto, por ejemplo, los que caducan esta semana.

Añadir django.contrib.humanize a INSTALLED_APPS para mostrar fechas en las plantillas de una manera amigable para los humanos.

Mejoremos la vista para que obtenga los cupones que caducan pronto y los pase al contexto de la plantilla:

desde datetime import timedelta desde django.contrib.auth.decorators importar login_required desde django.shortcuts import render, redirigir desde django.core.urlresolvers importar reverse_lazy desde django.utils.utils importar la zona horaria. = reverse_lazy ('login')) def dashboard (request): expiring_coupons = Coupon.objects.filter (end__gte = timezone.now (), end__lte = timezone.now () + timedelta (days = 7)) si request.method = = 'POST': form = CouponForm (request.POST) si form.is_valid (): coupon = form.save (commit = False) coupon.owner = request.user coupon.save () return redirect ('dashboard') else : form = CouponForm () return render (solicitud, 'dashboard.html', context = 'create_form': form, 'expiring_coupons': expiring_coupons)

Actualicemos la plantilla para que muestre los cupones que caducan de forma tabular. También pondremos el formulario de creación y la tabla en dos columnas separadas utilizando el sistema de cuadrícula de Bootstrap:

% extiende 'base.html'% % load widget_tweaks% % load humanize% % block title% Tablero % endblock% % block content% 

Tablero

[El código del formulario]
% si expiring_coupons% % para el cupón en expiring_coupons% % endfor%
Código de descuento Sitio web Fecha de caducidad
coupon.discount_code coupon.website coupon.end | día natural
% else%
No hay cupones que expiren pronto
% endif% % endblock%

Luciendo bien. Guarda tu progreso:

$ git añadir. $ git commit -m "Implementando la lista de cupones caducados"

Vista de catálogo

Ahora aprendamos algunos otros accesos directos de Django para crear una vista que muestre la lista de cupones que tenemos disponibles. Estamos hablando de vistas genéricas. Aquí es cómo crear rápidamente un Vista de la lista:

# views.py # ... from django.views.generic.list import ListView from django.db.models import Q class CouponListView (ListView): model = Coupon def get_queryset (self): return Coupon.objects.filter (Q (end__gte = timezone.now ()) | Q (end__isnull = True)). order_by ('- end')

Ahora ata la vista en su esquema de URL:

# main / urls.py desde django.conf.urls importar url desde django.contrib.auth importar vistas como auth_views desde django.views.generic.base importar RedirectView desde .views import dashboard, CouponListView urlpatterns = [url ('^ $' , RedirectView.as_view (url = 'login'), name = "index"), url (r '^ login / $', auth_views.LoginView.as_view (), name = "login"), url (r '^ logout / $ ', auth_views.LogoutView.as_view (), name = "logout"), url (r' ^ dashboard / $ ', dashboard, name = "dashboard"), url (r' ^ catalog / $ ', CouponListView. as_view (template_name = 'catalogue.html'), name = "catalog"),]

Crear la plantilla catalogue.html:

% extiende 'base.html'% % load humanize% % block title% Catálogo % endblock% % block content% 

Catalogar

% si object_list% % para el cupón en object_list% % endfor%
Código de descuento Sitio web Fecha de caducidad
coupon.discount_code coupon.website coupon.end | día natural
% else%
No hay cupones todavía. Crea tu primera aquí.
% endif% % endblock%

Ya que hemos conectado todo, dirígete a http: // localhost: 8000 / catalog / para ver su catalogo de cupones.

Guarda el progreso:

$ git añadir. $ git commit -m "Creando la vista de catálogo"

Esto está bastante cerca de un MVP. Lo aliento a que haga algunos ajustes finos como crear una barra de navegación, botones de inicio / cierre de sesión / registro, etc. Lo importante es que comprende el proceso de creación de prototipos y su producto para que la gente lo vea. Hablando de eso, nuestro producto aún no está en línea. No empujamos la última versión a Heroku. Hagamos eso y luego levantemos el teléfono y llamemos a los inversores..

Conclusión

Creamos una aplicación sencilla pero práctica. Creamos características rápidamente, y las implementamos en línea para que nuestros clientes potenciales puedan usarlas y brindarnos sus comentarios. Es mejor mostrar a la gente que hablar sobre una idea.. 

Aquí hay algunas conclusiones que podemos sacar:

  • Elegir las herramientas adecuadas puede acelerar significativamente el proceso de desarrollo.
  • Las herramientas utilizadas para la creación de prototipos no siempre son la mejor opción para proyectos más maduros. Teniendo eso en cuenta, es mejor usar herramientas más ágiles desde el principio e iterarlas en lugar de perderse en los detalles de implementación al minuto..
  • Aprovechar un PaaS significa que las aplicaciones deben respetar algunos patrones de diseño. Por lo general, estos patrones tienen sentido y nos obligan a escribir códigos aún mejores..
  • Django tiene muchos atajos que nos facilitan la vida:
    • Django ORM ayuda con el acceso a la base de datos. No tiene que preocuparse por escribir el SQL correcto y ser muy cuidadoso con los errores de sintaxis.
    • Las migraciones nos ayudan a la versión e iterar en el esquema de base de datos. No es necesario ir y escribir SQL para crear tablas o agregar columnas.
    • Django tiene una arquitectura amigable con los complementos. Podemos instalar aplicaciones que nos ayuden a alcanzar nuestros objetivos más rápido..
    • Las vistas genéricas y los formularios modelo pueden inyectar algunos de los comportamientos más comunes: listado de modelos, creación de modelos, autenticación, redirección, etc..
  • Al lanzar, es importante ser delgado y rápido. No pierdas tiempo y no gastes dinero..