Itération rapide avec Django & Heroku

Lancer une activité en ligne peut s'avérer très compliqué. Bien que sur papier, il soit beaucoup plus facile de créer une activité en ligne qu'une activité physique, un entrepreneur peut se perdre dans la multitude d'options. Parmi les pièges les plus courants auxquels un entrepreneur en ligne est confronté, citons:

  • Construire trop, trop tôt: Perdre du temps et dépenser de l'argent en construisant un produit complexe. Soyez démotivé en cours de route, perdez confiance dans le produit et abandonnez le projet.
  • Croire trop à l'idée: Rester fidèle à l'idée initiale et ne pas y revenir, même si les clients ne se présentent pas, ne paient pas ou ne sont pas satisfaits.
  • A défaut de commencer: Lorsque quelqu'un commence à construire un projet Web, il / elle peut être submergé (e) par les décisions et les choix apparemment infinis qui doivent être faits. Quel hébergement utiliser? Quelle plateforme? Quel thème WordPress? Comment créer une page de destination générant beaucoup de conversion? Quel langage de programmation et quelle base de données? Devez-vous utiliser un framework web? JavaScript vanille ou jQuery pour le front-end? Peut-être un cadre frontal plus complexe, car le projet en aura besoin une fois qu'il sera suffisamment mûr?
  • A défaut de lancer: Lors de la création d'un projet Web, même si vous avez choisi votre pile technologique, vous pouvez être submergé par les commentaires que vous recevez. Contre-intuitivement, écouter trop de commentaires est considéré comme une erreur. Il peut s'agir des commentaires de personnes qui n'utiliseraient pas votre produit de toute façon. Les gens ont tendance à avoir une opinion sur tout, même s'ils ne sont pas parfaitement informés sur le terrain..

Étant donné les multiples façons dont on peut échouer sur la route, il est vraiment important de:

  • Construisez le moins possible et le plus rapidement possible, en le montrant aux personnes que vous considérez comme des clients potentiels: Minimiser les coûts et les efforts.
  • Mettez-le en ligne dès que possible: Obtenez les réactions des utilisateurs sur le produit et non sur votre idée abstraite.
  • Faire des changements rapidement: Pour savoir ce que veut le client, il est essentiel d'être agile et de bien servir ses premiers clients payants.

Voici où le prototypage est en place. Un entrepreneur doit fonctionner sans gaspillage, sans perdre de temps et de ressources. Construire le moins possible au début peut s'avérer une vertu. 

Il existe de nombreuses écoles de pensée sur ce qu'est un prototype et comment le créer. Certains disent qu'il ne devrait s'agir que d'une page de renvoi, d'autres que ce devrait être une version allégée du produit final. Je suis plus fan de la seconde. L'utilisation d'une page de destination peut donner l'impression d'être une arnaque. En outre, vous ne pouvez pas obtenir de commentaires sur la façon dont vous résolvez le problème, mais seulement sur si le problème mérite d'être résolu..

Voici la panoplie d'outils d'un entrepreneur en ligne de prototypage intelligent:

  • Cadres Front-End: Bootstrap, Foundation, jQuery, Vue, etc. L’utilisation d’un framework frontal permettra à vos applications de fonctionner sur différentes tailles d’écran et différents navigateurs, avec un design correct.
  • Cadres Back-End: Django, Ruby on Rails, Laravel. L'utilisation de structures dorsales vous aidera à gérer facilement les modèles HTML, les formulaires HTTP, l'accès aux bases de données, les schémas d'URL, etc..
  • Plateforme en tant que service: Heroku, Google App Engine, AWS Elastic Beanstalk. Le choix d'un PaaS peut vous libérer des difficultés liées à la gestion de serveurs, à l'agrégation de journaux, à la surveillance de la disponibilité, à l'infrastructure de déploiement, etc..

Dans ce tutoriel, nous allons construire une application simple dans l’esprit du prototypage rapide. Nous utiliserons Django, Bootstrap CSS et Heroku. L'accent sera mis sur la partie arrière plutôt que sur l'avant. 

Nous allons tirer parti de la plate-forme Heroku pour mettre quelque chose en ligne très tôt et déployer rapidement de nouvelles fonctionnalités. Nous allons utiliser Django pour créer des modèles et des fonctionnalités de base de données complexes. Bootstrap CSS nous donnera un style par défaut judicieux pour nos pages. Assez parlé, allons.

Ce que nous construisons

Assurez-vous que vous êtes assis pour celui-ci. L'idée va frapper vos chaussettes. Voici le pitch: Ne détestez pas la façon dont vous obtenez tous ces codes de réduction, mais vous oubliez de les utiliser et ils expirent? 

Ne serait-il pas cool de stocker les codes quelque part où vous pouvez les rechercher et également être averti de leur date d'expiration? Je sais, bonne idée, non? Eh bien, posez votre carte de crédit, vous n'investirez pas dans celui-ci. Vous allez le construire.

Commencer

Dans ce tutoriel, je vais utiliser Python 3. Si vous utilisez Python 2.7, les modifications devraient être assez simples. Je vais aussi supposer que vous connaissez setuptools, Virtualenvs Python et Git. Encore une chose avant d’aller de l’avant: assurez-vous d’avoir un compte GitHub et un compte Heroku. Pour utiliser Heroku, vous devez également installer Heroku CLI.. 

Commençons par créer un virtualenv:

$ mkvirtualenv coupy

Comme vous l'avez probablement compris, notre nom d'application est Coupy. Passons au nouveau virtualenv, $ bon de travail, et installez Django: 

$ pip installer Django

Allez dans votre compte GitHub et créez un nouveau projet. Ensuite, clonons ce projet:

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

La prochaine étape logique consiste à créer un projet Django. Pour déployer un projet Django sur Heroku, nous devons suivre certaines directives. Heureusement, nous pouvons utiliser un modèle de projet pour cela. Voici comment faire cela:

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

Vous devrez peut-être déplacer certains dossiers. Assurez-vous que le dossier racine de votre référentiel ressemble à ceci:

. ├── Procfile README.md Coupy __init__.py settings.py statique human.txt ├── urls.py └ ── wsgi.py ├── manage.py exigences.txt └── runtime.txt

Nous allons maintenant installer les exigences fournies par le modèle:

$ pip install -r Requirements.txt

Nous voulons maintenant transmettre les fichiers nouvellement créés à GitHub:

$ git add. $ git commit -m "Init Django project" $ git push origin master

Voyons si ce que nous avons fait jusqu'ici marche:

$ python manage.py runserver

Ouvrez maintenant une fenêtre de navigateur et accédez à http: // localhost: 8000. Si tout va bien, vous devriez voir la page d'accueil Django classique. Pour s'assurer que tout va bien du point de vue de Heroku, nous pouvons également exécuter l'application comme ceci:

$ heroku local web

Pour prouver à quelle vitesse nous pouvons aller en ligne, faisons notre premier déploiement sur Heroku:

$ heroku login $ heroku créer

Nous avons maintenant créé une application Heroku, mais nous n’avons envoyé aucun code à Heroku. Notez que Heroku a créé un identifiant d'application convivial. Voici le résultat que vous devriez obtenir:

Créer une application… fait,  https: //.herokuapp.com/ | https://git.heroku.com/.git

Nous devons maintenant associer notre repo à la nouvelle application Heroku:

$ heroku git: à distance -a  $ git pousse le maître heroku $ heroku ouvert

Génial, vous venez de déployer une application sur Heroku. Cela ne fait pas grand chose, mais vous mettez quelque chose en ligne en un temps record. Bon travail.

Configuration de la base de données

Vous ne construirez probablement jamais une application Web non triviale sans base de données. La base de données est la partie de stockage de données de l'application Web. Voici où l'application Web conserve son état (au moins la plupart). Voici où nous conservons les comptes d'utilisateurs et les informations de connexion et bien plus encore. Heroku fournit un service PostgreSQL géré. 

C'est ce que nous allons utiliser. Assurez-vous d’avoir installé Postgres sur votre machine et créez une instance de base de données à utiliser dans notre application. Heroku a besoin d'une variable d'environnement pour pouvoir se connecter au service de base de données. La variable que nous devons définir est DATABASE_URL:

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

Disons maintenant à Django d'appliquer les migrations et de créer les tables nécessaires:

$ ./manage.py migrer

Créons un superutilisateur et connectons-nous à l'interface d'administration à l'adresse http: // localhost: 8000 / admin:

$ ./manage.py crée un utilisateur utilisateur $ ./manage.py

Nous pouvons voir que les tables ont bien été créées. Heroku a déjà associé une instance de base de données à votre application par défaut. Vous pouvez vous assurer que c'est bien le cas en vérifiant dans Heroku HEROKU_APP_ID> Paramètres> Variables de configuration dans votre console en ligne Heroku. Vous devriez voir ici que le DATABASE_URL est défini sur une adresse de base de données générée par Heroku. 

Nous devons maintenant exécuter les migrations et créer les commandes de super utilisateur en ligne. Voyons si tout fonctionne comme prévu:

$ heroku exécuter python manage.py migrer $ heroku exécuter python gérer.py crée un utilisateur

Si tout va bien, si nous visitons https: //.herokuapp.com/admin/, nous devrions pouvoir nous connecter avec les informations d'identification que nous venons de fournir.

Authentification d'utilisateur

Dans cette section, nous allons initialiser une application Django et utiliser les composants prédéfinis de Django pour créer la fonctionnalité d'authentification d'utilisateur dans notre application..

$ ./manage.py startapp main

Dans la nouvelle application, nous allons créer un urls.py fichier:

depuis l'URL d'importation de django.conf.urls depuis l'importation de django.contrib.auth en tant que vues d'auth_views depuis django.views.generic.base importation RedirectView urlpatterns = [url ('^ $', RedirectView.as_view (url = 'login'), nom = "index"), url (r '^ login $', auth_views.LoginView.as_view (), name = "login"), url (r '^ logout $', auth_views.LogoutView.as_view (), name = " Connectez - Out"), ] 

Nous utilisons ici trois vues génériques de Django:

  • RedirectView: L'URL de base de l'application ne faisant rien, nous redirigeons vers la page de connexion.
  • LoginView: Vue prédéfinie par Django qui crée le formulaire de connexion et implémente la routine d'authentification de l'utilisateur.
  • DéconnexionVue: Vue prédéfinie par Django qui déconnecte un utilisateur et redirige vers une certaine page.

Ajouter le principale application au INSTALLED_APPS liste:

INSTALLED_APPS = ['' django.contrib.admin ',' django.contrib.auth ',' django.contrib.contenttypes ',' django.contrib.sessions ',' django.contrib.messages ', # Désactivez la gestion des fichiers statiques propres à Django dans faveur de WhiteNoise, pour # une plus grande cohérence entre gunicorn et './manage.py runserver'. Voir: # http://whitenoise.evans.io/fr/stable/django.html#using-whitenoise-in-development 'whitenoise.runserver_nostatic', 'django.contrib.staticfiles', 'main',]

Brancher le main.urls au schéma de l'URL racine:

à partir de django.conf.urls import url, include à partir de django.contrib import admin urlpatterns = [url (r '^', include ('main.urls')), url (r '^ admin /', admin.site.urls ),]

Afin d’afficher correctement les formulaires, avec les styles, les classes et tout le reste, nous devons installer django-widget-tweaks:

$ pip install django-widget-tweaks $ pip gel> exigences.txt

Ajouter django-widget-tweaks à INSTALLED_APPS:

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

Nous ajoutons maintenant ces deux configs à settings.py:

  • LOGIN_REDIRECT_URL: Indique à Django où rediriger un utilisateur après une authentification réussie.
  • LOGOUT_REDIRECT_URL: Indique à Django où rediriger l'utilisateur après sa déconnexion.
# settings.py LOGIN_REDIRECT_URL = 'tableau de bord' LOGOUT_REDIRECT_URL = 'login'

Ecrivons un modèle maître simple base.html et un dashboard.html modèle qui le prolonge. Nous reviendrons au tableau de bord un plus tard.

     % block title% % endblock%   
% block content% % endblock%
% extend 'base.html'% % block title% Tableau de bord % endblock% % block content% 

Tableau de bord

% endblock%

Écrivez la vue qui rend le dashboard.html modèle:

from django.shortcuts importer le rendu de django.core.urlresolvers importer reverse_lazy @login_required (login_url = reverse_lazy ('login')) def tableau de bord (demande): renvoyer le rendu (demande, 'dashboard.html')

Nous sommes tous ensemble. Rendez-vous sur http: // localhost: 8000 / login / et tester que l'authentification fonctionne. Ensuite, enregistrez votre progression:

$ git add. $ git commit -m "Vues de connexion / déconnexion / tableau de bord"

Créer le modèle de coupon

Nous en arrivons maintenant à la partie la plus importante de notre application, à savoir la conception du modèle de coupon. Nous allons installer django-model-utils d'ajouter des propriétés supplémentaires à nos modèles.

$ pip install django-model-utils $ pip gel> exigences.txt

Écrire le Coupon modèle:

from model_utils.models import TimeStampedModel, TimeFramedModel de django.db modèles d'importation de django.contrib.auth.models import Classe utilisateur Coupon (TimeStampedModel, TimeFramedModel): propriétaire = models.ForeignKey (Utilisateur) discount_code = models.CharField ("Code Promo") , max_length = 100) website = models.URLField ("Site Web") description = models.TextField ("Description du coupon")

le django-model-utils les modèles que nous avons étendus nous permettent de:

  • TimeStampedModel nous aide à savoir quand le modèle a été placé dans la base de données, via le créé champ.
  • TimeFramedModel ajoute le début et fin champs à notre modèle. Nous utilisons ces champs pour suivre la disponibilité du coupon.

Accrochez le modèle à l'administrateur:

depuis django.contrib import admin depuis .models import Coupon @ admin.register (Coupon), classe CouponAdmin (admin.ModelAdmin): pass

Créer et appliquer des migrations:

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

Enregistrer les progrès:

$ git add. $ git commit -m "Créer un modèle de coupon"

ModelForm pour la création de coupon

L'une des fonctionnalités intéressantes de Django est la possibilité de créer des formulaires à partir de classes de modèle. Nous allons créer un tel formulaire qui permet aux utilisateurs de créer des coupons. Créons un forms.py déposer à l'intérieur du principale application:

depuis django.forms import ModelForm depuis .models import Coupon class CouponForm (ModelForm): class Meta: model = Coupon exclude = ('owner',) # Nous définissons nous-même ce champ

Ajoutons ce formulaire au tableau de bord. Nous devons changer à la fois la vue et le modèle:

# views.py de django.shortcuts importer le rendu, redirection de django.core.urlresolvers importer reverse_lazy depuis .forms importer CouponForm @login_required (login_url = reverse_lazy ('login')) def dashboard (demande): si request.method == ' POST ': form = FormonForm (request.POST) si form.is_valid (): coupon = form.save (commit = False) coupon.owner = request.user coupon.save () renvoie une redirection (' tableau de bord ') else: form = CouponForm () renvoie le rendu (request, 'dashboard.html', context = 'create_form': form)
% extend 'base.html'% % charger widget_tweaks% % titre du bloc% tableau de bord % endblock% % contenu du bloc% 

Tableau de bord

% csrf_token%
% render_field create_form.discount_code placeholder = "Code de réduction"%
% render_field create_form.website placeholder = "Site Web"%
% render_field create_form.description placeholder = "Description"%
% render_field create_form.start placeholder = "Disponible de (MM / JJ / AAAA)"%
% render_field create_form.end placeholder = "Expires le (MM / JJ / AAAA)"%
% endblock%

Nous avons maintenant un moyen de créer des coupons à partir du tableau de bord. Allez l'essayer. Nous n'avons aucun moyen de voir les coupons dans le tableau de bord, mais nous pouvons le faire dans le panneau d'administration. Sauvons le progrès:

$ git add. $ git commit -m "Formulaire de création de coupon dans le tableau de bord"

Coupons expirant bientôt

Une dernière chose à afficher dans le tableau de bord: les bons qui expirent bientôt, par exemple ceux qui expirent cette semaine..

Ajouter django.contrib.humanize à INSTALLED_APPS afficher les dates dans les modèles de manière conviviale.

Améliorons la vue afin qu’elle récupère les coupons qui arrivent à expiration et les passe dans le contexte du modèle:

depuis datetime import timedelta depuis django.contrib.auth.decorators import login_required depuis django.shortcuts import render, redirection depuis django.core.urlresolvers import reverse_lazy depuis django.utils importez le fuseau horaire depuis .forms import import CouponForm depuis .models import Coupon @login_re = reverse_lazy ('login')) def tableau de bord (demande): expiring_coupons = Coupon.objects.filter (end__gte = timezone.now (), end__lte = timezone.now () + timedelta (jours = 7)) si request.method = = 'POST': form = FormonForm (request.POST) si form.is_valid (): coupon = form.save (commit = False) coupon.owner = request.user coupon.save () renvoie une redirection ('tableau de bord') else : form = CouponForm () return render (request, 'dashboard.html', context = 'create_form': form, 'expiring_coupons': expiring_coupons)

Mettons à jour le modèle pour qu'il affiche les coupons expirants sous forme de tableau. Nous allons également mettre le formulaire de création et le tableau dans deux colonnes séparées en utilisant le système de grille de Bootstrap:

% extend 'base.html'% % load widget_tweaks% % load humanize% % block title% Tableau de bord % endblock% % block content% 

Tableau de bord

[Le code du formulaire]
% si expiring_coupons% % pour le coupon dans expiring_coupons% % endfor%
Code de réduction Site Internet Date d'expiration
coupon.discount_code coupon.website coupon.end | naturalday
% autre %
Aucun coupon expirant bientôt
% endif% % endblock%

Vous cherchez bien. Enregistrez vos progrès:

$ git add. $ git commit -m "Implémentation de la liste des bons expirés"

Vue catalogue

Apprenons maintenant quelques autres raccourcis Django pour créer une vue qui affiche la liste des coupons disponibles. Nous parlons de vues génériques. Voici comment créer rapidement un ListView:

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

Nouez maintenant la vue dans votre schéma d'URL:

# main / urls.py de django.conf.urls, importez l’URL de django.contrib.auth, importez les vues sous le nom auth_views de django.views.generic.base, importez RedirectView depuis le tableau de bord d’importation de Coups, 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' ^ tableau de bord / $ ', tableau de bord, name = "tableau de bord"), url (r' ^ catalogue / $ ', CouponListView. as_view (template_name = 'catalogue.html'), name = "catalogue"),]

Créer le modèle catalogue.html:

% extend 'base.html'% % charger humaniser% % titre du bloc% Catalogue % endblock% % contenu du bloc% 

Catalogue

% si object_list% % pour coupon dans object_list% % endfor%
Code de réduction Site Internet Date d'expiration
coupon.discount_code coupon.website coupon.end | naturalday
% autre %
Aucun coupon pour le moment. Créez votre premier ici.
% endif% % endblock%

Puisque nous avons tout connecté, dirigez-vous vers http: // localhost: 8000 / catalog / pour voir votre catalogue de coupons.

Enregistrez le progrès:

$ git add. $ git commit -m "Création de la vue catalogue"

C'est assez proche d'un MVP. Je vous encourage à faire quelques ajustements tels que la création d'une barre de navigation, les boutons de connexion / déconnexion / enregistrement, etc. L'important est que vous compreniez le processus de prototypage et que votre produit soit accessible aux utilisateurs. En parlant de cela, notre produit n'est pas encore en ligne. Nous n'avons pas envoyé la dernière version à Heroku. Faisons-le, décrochez le téléphone et appelez les investisseurs.

Conclusion

Nous avons créé une application simple mais pratique. Nous avons créé des fonctionnalités rapidement et les avons déployées en ligne afin que nos clients potentiels puissent les utiliser et nous faire part de leurs commentaires. Il est préférable de montrer aux gens plutôt que de parler d'une idée. 

Voici quelques conclusions que nous pouvons tirer:

  • Choisir les bons outils peut considérablement accélérer le processus de développement.
  • Les outils utilisés pour le prototypage ne sont pas toujours le meilleur choix pour des projets plus matures. Gardez cela à l'esprit, il est préférable d'utiliser des outils plus agiles dès le début et de les parcourir au lieu de vous perdre rapidement dans les détails de la mise en œuvre..
  • Tirer parti d'une PaaS signifie que les applications doivent respecter quelques modèles de conception. Habituellement, ces modèles ont un sens et nous obligent à écrire du code encore meilleur.
  • Django a beaucoup de raccourcis qui facilitent nos vies:
    • Django ORM aide à accéder à la base de données. Pas besoin de s'inquiéter d'écrire du code SQL correct ni de faire très attention aux erreurs de syntaxe.
    • Les migrations nous aident à la version et à l'itération sur le schéma de base de données. Pas besoin d'aller écrire SQL pour créer des tables ou ajouter des colonnes.
    • Django a une architecture compatible avec les plugins. Nous pouvons installer des applications qui nous aident à atteindre nos objectifs plus rapidement.
    • Les vues génériques et les formulaires de modèle peuvent intégrer certains des comportements les plus courants: liste de modèles, création de modèles, authentification, redirection, etc..
  • Lors du lancement, il est important d'être svelte et rapide. Ne perdez pas de temps et ne dépensez pas d'argent.