Iterare velocemente con Django e Heroku

Il lancio di un business online può rivelarsi seriamente complicato. Sebbene sulla carta sia più facile creare un business online che un mattone, un imprenditore può perdersi nella moltitudine di opzioni. Alcune tra le insidie ​​più comuni che un imprenditore online si blocca includono:

  • Costruire troppo troppo presto: Perdere tempo e bruciare i soldi creando un prodotto complesso. Diventi demotivato lungo la strada, perdi la fiducia nel prodotto e abbandoni il progetto.
  • Credere troppo nell'idea: Rimanere fedeli all'idea originale e non iterare su di esso, anche se i clienti non si presentano, non pagano, o non sono soddisfatti.
  • In mancanza di iniziare: Quando qualcuno inizia il percorso di costruzione di un progetto web, può essere sopraffatto dalle decisioni e dalle scelte apparentemente infinite che devono essere fatte. Quale hosting usare? Quale piattaforma? Quale tema WordPress? Come creare una pagina di destinazione ad alta conversione? Quale linguaggio di programmazione e quale database? Dovresti usare un framework web? Vanilla JavaScript o jQuery per il front-end? Forse un framework di front-end più complesso perché il progetto ne avrà bisogno una volta che sarà abbastanza maturo?
  • In mancanza di lancio: Quando crei un progetto web, anche se hai deciso il tuo stack tecnologico, puoi essere sopraffatto dal feedback che ricevi. Contrariamente, è considerato un errore ascoltare troppi feedback. Può essere il feedback di persone che non utilizzerebbero comunque il tuo prodotto. Le persone tendono ad avere un'opinione su tutto, anche se non sono completamente informati sul campo.

Data la moltitudine di modi in cui uno può fallire lungo la strada, è molto importante:

  • Costruisci il meno possibile e il più rapidamente possibile, mostrandolo a persone che consideri potenziali clienti: Riduci i costi e gli sforzi.
  • Mettilo online il prima possibile: Ottieni feedback dalle persone sul prodotto, non sulla tua idea astratta.
  • Apporta modifiche rapidamente: Quando si apprende ciò che il cliente desidera, è fondamentale essere agili e servire bene i primi clienti paganti.

Ecco dove entra in scena la prototipazione. Un imprenditore dovrebbe correre snello, senza perdere tempo e risorse. Costruire il meno possibile all'inizio può rivelarsi una virtù. 

Ci sono molte scuole di pensiero su cosa sia un prototipo e come dovrebbe essere creato. Alcuni dicono che dovrebbe essere solo una pagina di destinazione, altri che dovrebbe essere una versione ridotta del prodotto finale. Sono più un fan del secondo. L'uso di una sola pagina di destinazione può sembrare una truffa. Inoltre, non è possibile ottenere feedback su come si sta risolvendo il problema, ma solo su se il problema vale la pena risolverlo.

Ecco il cinturino di un imprenditore online di prototipazione intelligente:

  • Framework front-end: Bootstrap, Foundation, jQuery, Vue, ecc. L'utilizzo di un framework front-end renderà le tue app funzionanti su schermi di dimensioni diverse e su browser diversi, con un design decente.
  • Framework di back-end: Django, Ruby on Rails, Laravel. L'utilizzo di framework back-end ti aiuterà a gestire facilmente modelli HTML, moduli HTTP, accesso ai database, schemi URL, ecc.
  • Platform-as-a-Service: Heroku, Google App Engine, AWS Elastic Beanstalk. La scelta di un PaaS può liberarti dalla sofferenza della gestione dei server, dell'aggregazione dei log, del monitoraggio del tempo di attività, dell'infrastruttura di distribuzione e altro ancora.

In questo tutorial, costruiremo una semplice applicazione nello spirito della prototipazione rapida. Useremo Django, Bootstrap CSS e Heroku. Il focus sarà sulla parte back-end piuttosto che sul front-end. 

Trarremo vantaggio dalla piattaforma Heroku per mettere online qualcosa in anticipo e per implementare rapidamente nuove funzionalità. Useremo Django per costruire modelli e funzionalità di database complessi. I CSS di bootstrap ci daranno uno stile predefinito per le nostre pagine. Basta parlare, andiamo.

Cosa stiamo costruendo

Assicurati di stare seduto per questo. L'idea ti farà perdere i calzini. Ecco il tono: non odiate solo come ottenete tutti questi codici sconto ma dimenticate di usarli e scadono? 

Non sarebbe bello conservare i codici da qualche parte dove puoi cercarli e anche essere avvisati quando stanno per scadere? Lo so, ottima idea, giusto? Bene, metti giù la tua carta di credito, non investirai in questo. Lo costruirai.

Iniziare

In questo tutorial, userò Python 3. Se stai usando Python 2.7, le modifiche dovrebbero essere abbastanza semplici. Immaginerò anche che tu sia a conoscenza setuptools, Python virtualenvs e Git. Ancora una cosa prima di andare avanti: assicurati di avere un account GitHub e Heroku. Per usare Heroku, devi anche installare la CLI di Heroku. 

Iniziamo creando un virtualenv:

$ mkvirtualenv coupy

Come probabilmente hai capito, il nostro nome dell'applicazione è Coupy. Passiamo al nuovo virtualenv, $ workon coupy, e installa Django: 

$ pip installa Django

Entra nel tuo account GitHub e crea un nuovo progetto. Quindi, cloniamo il progetto:

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

Il prossimo passo logico è creare un progetto Django. Per implementare un progetto Django su Heroku, dobbiamo seguire alcune linee guida. Fortunatamente, possiamo usare un modello di progetto per questo. Ecco come farlo:

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

Potrebbe essere necessario spostare alcune cartelle. Assicurati che la cartella principale del repository assomigli a questo:

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

Ora installiamo i requisiti forniti dal modello:

$ pip install -r requirements.txt

Ora vogliamo inviare i file appena creati a GitHub:

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

Vediamo se ciò che abbiamo fatto finora funziona:

$ python manage.py runserver

Ora apri una finestra del browser e vai a http: // localhost: 8000. Se tutto va bene, dovresti vedere la classica pagina di benvenuto di Django. Per assicurarci che tutto sia buono dal punto di vista di Heroku, possiamo anche eseguire l'applicazione in questo modo:

$ web locale di heroku

Per dimostrare quanto velocemente possiamo andare online, facciamo il nostro primo schieramento su Heroku:

$ heroku login $ heroku create

Ora abbiamo creato un'applicazione Heroku, ma non abbiamo inviato alcun codice a Heroku. Si noti che Heroku ha creato un ID app user-friendly. Ecco l'output che dovresti ottenere:

Creazione dell'app ... completata, ⬢  https: //.herokuapp.com/ | https://git.heroku.com/.idiota

Ora dobbiamo associare il nostro repository con l'app Heroku appena creata:

$ gita di heroku: remoto -a  $ git push open heroku master $ heroku

Fantastico, hai appena distribuito un'app a Heroku. Non fa molto, ma metti qualcosa online in tempi record. Buon lavoro.

Impostazione del database

Probabilmente non costruirai mai un'app web non banale senza un database. Il database è la parte di archiviazione dei dati dell'app Web. Qui è dove l'app web mantiene il suo stato (almeno la maggior parte). Ecco dove teniamo gli account utente e i dettagli di accesso e molto altro ancora. Heroku fornisce un servizio PostgreSQL gestito. 

Questo è ciò che useremo. Assicurati di aver installato Postgres sul tuo computer e crea un'istanza di database da utilizzare nella nostra applicazione. Heroku ha bisogno di una variabile di ambiente da impostare per potersi connettere al servizio del database. La variabile che dobbiamo impostare è DATABASE_URL:

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

Diamo ora a Django di applicare le migrazioni e creare le tabelle necessarie:

$ ./manage.py migrare

Creiamo un superutente e accedi all'interfaccia di amministrazione su http: // localhost: 8000 / admin:

$ ./manage.py createsuperuser $ ./manage.py runserver

Possiamo vedere che le tabelle sono state effettivamente create. Heroku ha già associato un'istanza di database all'app per impostazione predefinita. Puoi assicurarti che sia così, controllando Heroku HEROKU_APP_ID> Impostazioni> Variabili di configurazione nella tua console online di Heroku. Dovresti vedere qui che il DATABASE_URL è impostato su un indirizzo di database generato da Heroku. 

Ora dobbiamo eseguire le migrazioni e creare i comandi dell'utente super in linea. Vediamo se tutto funziona come previsto:

$ heroku run python manage.py migrate $ heroku run python manage.py createsuperuser

Se tutto andasse bene, se visitassimo https: //.herokuapp.com/admin/, dovremmo essere in grado di accedere con le credenziali che abbiamo appena fornito.

Autenticazione utente

In questa sezione, inizializzeremo un'applicazione Django e useremo i componenti predefiniti di Django per creare la funzionalità di autenticazione dell'utente nella nostra app.

$ ./manage.py startapp main

All'interno della nuova app, creeremo un urls.py file:

dall'URL di importazione django.conf.urls da django.contrib.auth importare le viste come auth_views da django.views.generic.base import RedirectView 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 = " disconnettersi"), ] 

Qui usiamo tre viste Django generiche:

  • RedirectView: Poiché l'URL di base dell'applicazione non fa nulla, stiamo reindirizzando alla pagina di accesso.
  • LoginView: Vista predefinita di Django che crea il modulo di accesso e implementa la routine di autenticazione dell'utente.
  • LogoutView: Vista predefinita di Django che registra un utente e reindirizza a una determinata pagina.

Aggiungi il principale applicazione al INSTALLED_APPS elenco:

INSTALLED_APPS = ['django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', # Disabilita la gestione dei file statici di Django in favore di WhiteNoise, per # maggiore coerenza tra gunicorn e './manage.py runserver'. Vedi: # http://whitenoise.evans.io/en/stable/django.html#using-whitenoise-in-development 'whitenoise.runserver_nostatic', 'django.contrib.staticfiles', 'main',]

Collega il main.urls allo schema dell'URL di root:

dall'URL di importazione django.conf.urls, includi da django.contrib import admin urlpatterns = [url (r '^', include ('main.urls')), url (r '^ admin /', admin.site.urls ),]

Per visualizzare correttamente i moduli, con stili e classi e tutto, dobbiamo installare django-Widget-ritocchi:

$ pip installa django-widget-tweaks $ pip freeze> requirements.txt

Inserisci django-Widget-ritocchi a INSTALLED_APPS:

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

Ora aggiungiamo queste due configurazioni settings.py:

  • LOGIN_REDIRECT_URL: Comunica a Django dove reindirizzare un utente dopo un'autenticazione corretta.
  • LOGOUT_REDIRECT_URL: Dice a Django dove reindirizzare l'utente dopo che si è disconnesso.
# settings.py LOGIN_REDIRECT_URL = 'dashboard' LOGOUT_REDIRECT_URL = 'login'

Scriviamo un semplice modello principale base.html e a dashboard.html modello che lo estende. Torneremo al cruscotto uno dopo.

     % block title% % endblock%   
% block content% % endblock%
% estende 'base.html'% % block title% Dashboard % endblock% % block content% 

Cruscotto

% endblock%

Scrivi la vista che rende il dashboard.html modello:

da django.shortcuts import rendering da django.core.urlresolvers import reverse_lazy @login_required (login_url = reverse_lazy ('login')) dashboard di def (richiesta): return rendering (request, 'dashboard.html')

Siamo a posto. Dirigetevi verso http: // localhost: 8000 / login / e verifica che l'autenticazione funzioni. Quindi, salva i tuoi progressi:

$ git add. $ git commit -m "Login / Logout / Viste dashboard"

Crea il modello di coupon

Ora siamo arrivati ​​alla parte più importante della nostra applicazione, progettando il modello Coupon. Installeremo django-model-utils aggiungere alcune proprietà extra ai nostri modelli.

$ pip installa django-model-utils $ pip freeze> requirements.txt

Scrivi la buono modello:

from model_utils.models import TimeStampedModel, TimeFramedModel from django.db import model from django.contrib.auth.models import User class Coupon (TimeStampedModel, TimeFramedModel): owner = models.ForeignKey (Utente) discount_code = models.CharField ("Codice Sconto") , max_length = 100) website = models.URLField ("Website") description = models.TextField ("Descrizione del coupon")

Il django-model-utils i modelli che abbiamo esteso ci consentono di:

  • TimeStampedModel ci aiuta a tenere traccia quando il modello è stato inserito nel database, tramite il creato campo.
  • TimeFramedModel aggiunge il inizio e fine campi al nostro modello. Stiamo utilizzando questi campi per tenere traccia della disponibilità del coupon.

Aggancia il modello all'admin:

da django.contrib import admin da .models import Coupon @ admin.register (Coupon) class CouponAdmin (admin.ModelAdmin): pass

Crea e applica le migrazioni:

$ ./manage.py makemigrations $ ./manage.py migrare

Salva i progressi:

$ git add. $ git commit -m "Crea modello coupon"

ModelForm per la creazione di coupon

Una delle fantastiche funzionalità di Django è la possibilità di creare moduli da classi di modelli. Creeremo un modulo che consente agli utenti di creare coupon. Creiamo a forms.py file all'interno del principale applicazione:

da django.forms importare ModelForm da .models import Classe coupon CouponForm (ModelForm): class Meta: model = Coupon exclude = ('owner',) # Stiamo impostando questo campo da soli

Aggiungiamo questo modulo alla dashboard. Dobbiamo modificare sia la vista che il modello:

# views.py da django.shortcuts importazione rendering, reindirizzamento da django.core.urlresolvers importazione reverse_lazy da .forms import CouponForm @login_required (login_url = reverse_lazy ('login')) dashboard def (richiesta): if request.method == ' POST ': form = CouponForm (request.POST) se form.is_valid (): coupon = form.save (commit = False) coupon.owner = request.user coupon.save () return redirect (' dashboard ') else: form = CouponForm () restituisce il rendering (request, 'dashboard.html', context = 'create_form': form)
% estende 'base.html'% % carica widget_tweaks% % block title% Dashboard % endblock% % block content% 

Cruscotto

% csrf_token%
% render_field create_form.discount_code placeholder = "Codice sconto"%
% render_field create_form.website placeholder = "Sito web"%
% render_field create_form.description placeholder = "Descrizione"%
% render_field create_form.start placeholder = "Disponibile da (MM / GG / AAAA)"%
% render_field create_form.end placeholder = "Expires On (MM / DD / YYYY)"%
% endblock%

Ora abbiamo un modo per creare coupon dalla dashboard. Vai a provare. Non abbiamo modo di vedere i coupon nella dashboard, ma possiamo farlo nel pannello di amministrazione. Salviamo i progressi:

$ git add. $ git commit -m "Modulo di creazione coupon in dashboard"

Scadenza dei tagliandi

Un'altra cosa che vogliamo mostrare nella dashboard: tagliandi che scadono presto, ad esempio quelli che scadono questa settimana.

Inserisci django.contrib.humanize a INSTALLED_APPS per visualizzare le date nei modelli in un modo umano.

Miglioriamo la vista in modo che recuperi i buoni in scadenza e li passi al contesto del modello:

da data / ora import timedelta da django.contrib.auth.decorators import login_required da django.shortcuts import rendering, reindirizza da django.core.urlresolvers import reverse_lazy da django.utils importa il fuso orario da .forms import CouponForm da .models import Coupon @login_required (login_url = reverse_lazy ('login')) dashboard def (richiesta): expiring_coupons = Coupon.objects.filter (end__gte = timezone.now (), end__lte = timezone.now () + timedelta (days = 7)) if request.method = = 'POST': form = CouponForm (request.POST) se form.is_valid (): coupon = form.save (commit = False) coupon.owner = request.user coupon.save () return redirect ('dashboard') altro : form = CouponForm () return render (request, 'dashboard.html', context = 'create_form': form, 'expiring_coupons': expiring_coupons)

Aggiorniamo il modello in modo che mostri i coupon in scadenza in modo tabulare. Metteremo anche il modulo di creazione e la tabella in due colonne separate usando il sistema di griglia di Bootstrap:

% estende 'base.html'% % carica widget_tweaks% % carica humanize% % block title% Dashboard % endblock% % block content% 

Cruscotto

[Il codice del modulo]
% se expiring_coupons% % per coupon in expiring_coupons% % endfor%
Codice di sconto Sito web Data di scadenza
Coupon.discount_code Coupon.website coupon.end | naturalday
% altro %
Nessun tagliando scadrà presto
% endif% % endblock%

Guardando bene Salva i tuoi progressi:

$ git add. $ git commit -m "Implementazione dell'elenco di coupon in scadenza"

Vista del catalogo

Ora impariamo altre scorciatoie di Django per creare una vista che mostra l'elenco dei coupon che abbiamo a disposizione. Stiamo parlando di visualizzazioni generiche. Ecco come creare rapidamente un Visualizzazione elenco:

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

Ora lega la vista nel tuo schema URL:

# main / urls.py dall'URL di importazione django.conf.urls da django.contrib.auth importare le viste come auth_views da django.views.generic.base importare RedirectView dal dashboard di importazione di .views, 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"),]

Crea il modello catalogue.html:

% estende 'base.html'% % carica humanize% % block title% Catalogue % endblock% % block content% 

Catalogare

% se object_list% % per coupon in object_list% % endfor%
Codice di sconto Sito web Data di scadenza
Coupon.discount_code Coupon.website coupon.end | naturalday
% altro %
Nessun coupon ancora. Crea il tuo primo qui.
% endif% % endblock%

Dal momento che abbiamo agganciato tutto, vai su http: // localhost: 8000 / catalogo / per visualizzare il tuo catalogo di coupon.

Salva i progressi:

$ git add. $ git commit -m "Creazione della vista del catalogo"

Questo è abbastanza vicino a un MVP. Vi incoraggio a fare un po 'di messa a punto come creare una barra di navigazione, i pulsanti di login / logout / register, ecc. L'importante è capire il processo di prototipazione e ottenere il vostro prodotto là fuori affinché le persone possano vederlo. A proposito, il nostro prodotto non è ancora online. Non abbiamo inviato l'ultima versione a Heroku. Facciamolo e poi prendiamo il telefono e chiamiamo gli investitori.

Conclusione

Abbiamo creato un'applicazione semplice ma pratica. Abbiamo creato rapidamente le funzioni e le abbiamo implementate online in modo che i nostri potenziali clienti possano utilizzarle e darci feedback. È meglio mostrare le persone piuttosto che parlare solo di un'idea. 

Ecco alcune conclusioni che possiamo trarre:

  • Scegliere gli strumenti giusti può velocizzare significativamente il processo di sviluppo.
  • Gli strumenti utilizzati per la prototipazione non sono sempre la scelta migliore per progetti più maturi. Tenendo presente questo, è meglio utilizzare strumenti più agili nelle fasi iniziali e iterare su di essi piuttosto che perdersi nei minimi dettagli di implementazione nelle prime fasi.
  • Approfittando di un PaaS significa che le applicazioni devono rispettare alcuni schemi di progettazione. Di solito questi schemi hanno senso e ci costringono a scrivere codice ancora migliore.
  • Django ha molte scorciatoie che semplificano la nostra vita:
    • Django ORM aiuta con l'accesso al database. Non c'è bisogno di preoccuparsi di scrivere SQL corretto e di fare attenzione con gli errori di sintassi.
    • Le migrazioni ci aiutano nella versione e iterare sullo schema del database. Non c'è bisogno di scrivere SQL per creare tabelle o aggiungere colonne.
    • Django ha un'architettura plug-friendly. Possiamo installare app che ci aiutano a raggiungere i nostri obiettivi più rapidamente.
    • Viste generiche e moduli modello possono iniettare alcuni dei comportamenti più comuni: elencazione di modelli, creazione di modelli, autenticazione, reindirizzamento, ecc..
  • Al momento del lancio, è importante essere snelli e veloci. Non perdere tempo e non spendere soldi.