Iterating Fast With Django & Heroku

Att starta ett online-företag kan visa sig vara allvarligt komplicerat. Även om det på papper är lättare att skapa en online-verksamhet än en tegelsten, kan en entreprenör gå vilse i många alternativ. Några av de vanligaste fallgroparna som en online entreprenör fastnar i är:

  • Bygga för mycket för tidigt: Förlora tid och bränna pengar bygga en invecklad produkt. Få demotiverade längs vägen, förlora tro på produkten och överge projektet.
  • Att tro för mycket i idén: Att fastna vid den ursprungliga idén och inte iterera på den, trots att kunderna inte dyker upp, betalar inte eller inte är nöjda.
  • Underlåtenhet att börja: När någon börjar längs vägen för att bygga ett webbprojekt, kan han / hon bli överväldigad av de oändliga oändliga besluten och valen som måste göras. Vad värd att använda? Vilken plattform? Vilket WordPress-tema? Hur man bygger en högkonverterande målsida? Vilket programmeringsspråk och vilken databas? Ska du använda en webbram? Vanilla JavaScript eller jQuery för fronten? Kanske en mer komplicerad front-end ram eftersom projektet kommer att behöva en gång det är moget nog?
  • Underlåtenhet att starta: När du bygger ett webbprojekt, kan du bli överväldigad av den feedback du får om du bestämde dig för din teknikstack. Motstridigt anses det vara ett misstag att lyssna på för mycket feedback. Det kan vara feedback från personer som inte skulle använda din produkt ändå. Människor tenderar att ha en åsikt om allt, även om de inte är helt kunniga på fältet.

Med tanke på de många sätt man kan misslyckas längs vägen är det väldigt viktigt att:

  • Bygg så lite och så snabbt som möjligt och visa det för personer som du anser vara potentiella kunder: Minimera kostnader och ansträngningar.
  • Lägg det på nätet så snart som möjligt: Få feedback från personer på produkten, inte på din abstrakta idé.
  • Gör ändringar snabbt: När du lär dig vad kunden vill ha är det viktigt att vara smidig och tjäna dina första betalande kunder bra.

Här kommer prototyper på plats. En entreprenör bör springa, inte slösa tid och resurser. Att bygga så lite som möjligt i början kan visa sig en dygd. 

Det finns många tankskolor om vad en prototyp är och hur den ska skapas. Vissa säger att det bara ska vara en målsida, andra att det ska vara en avvecklad version av slutprodukten. Jag är mer av en fan av den andra. Om du bara använder en målsida kan du känna scammy. Du kan också inte få feedback om hur du löser problemet, utan bara om problemet är värt att lösa.

Här är verktyget på en smart prototyping online-entreprenör:

  • Front-End Framework: Bootstrap, Foundation, jQuery, Vue, etc. Med hjälp av ett front-end-ramverk kommer dina appar att fungera på olika skärmstorlekar och olika webbläsare, med en anständig design.
  • Back-End Framework: Django, Ruby on Rails, Laravel. Använda back-end-ramar hjälper dig att enkelt hantera HTML-mallar, HTTP-formulär, databasåtkomst, webbadresser, etc..
  • Platform-as-a-Service: Heroku, Google App Engine, AWS Elastic Beanstalk. Att välja en PaaS kan frigöra dig från smärtan att hantera servrar, loggaggregation, upptidskontroll, installationsinfrastruktur och mer.

I denna handledning bygger vi en enkel applikation i en anda av snabb prototypning. Vi använder Django, Bootstrap CSS och Heroku. Fokus kommer att ligga på back-end-delen i stället för frontänden. 

Vi kommer att dra nytta av Heroku-plattformen för att sätta något på nätet tidigt och att snabbt distribuera nya funktioner. Vi ska använda Django för att bygga komplexa databasmodeller och funktionalitet. Bootstrap CSS ger oss en förnuftig standardstil för våra sidor. Noga prata, låt oss gå.

Vad vi bygger

Se till att du sitter ner för den här. Tanken kommer att slå dina strumpor av. Här är höjden: Hata inte bara hur du får alla dessa rabattkoder, men du glömmer att använda dem och de löper ut? 

Skulle det inte vara kul att lagra koderna någonstans där du kan söka efter dem och också bli underrättad när de kommer att löpa ut? Jag vet, bra idé, eller hur? Tja, sätt in ditt kreditkort, du investerar inte i den här. Du ska bygga den.

Komma igång

I den här handledningen kommer jag att använda Python 3. Om du använder Python 2.7 ska ändringarna vara ganska enkla. Jag kommer också att anta att du är bekant med setuptools, Python virtualenvs och Git. En sak innan du går framåt: Se till att du har ett GitHub-konto och ett Heroku-konto. För att kunna använda Heroku behöver du också installera Heroku CLI. 

Låt oss börja med att skapa en virtualenv:

$ mkvirtualenv coupy

Som du säkert har tänkt ut är vårt programnamn Coupy. Låt oss byta till den nya virtualenv, $ workon coupy, och installera Django: 

$ pip installera Django

Gå in på ditt GitHub-konto och skapa ett nytt projekt. Låt oss sedan klona det projektet:

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

Nästa logiska steg är att skapa ett Django-projekt. För att distribuera ett Django-projekt till Heroku måste vi följa några riktlinjer. Lyckligtvis kan vi använda en projektmall för det. Så här gör du det:

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

Du kan behöva flytta runt några mappar. Se till att din förlagsrotsmapp ser ut så här:

. ├── Procfile ├── README.md ├── coupy │ ├── __init__.py │ ├── settings.py │ ├── statisk │ │ └── human.txt │ ├── urls.py │ └ ─ - wsgi.py ├── manage.py ├── requirements.txt └── runtime.txt

Låt oss nu installera kraven från mallen:

$ pip installera -r requirements.txt

Vi vill nu driva de nyskapade filerna till GitHub:

$ git lägg till. $ git commit -m "Init Django projekt" $ git push origin master

Låt oss se om det vi hittills har gjort fungerar:

$ python manage.py körserver

Öppna nu ett webbläsarfönster och gå till http: // localhost: 8000. Om allt är bra borde du se den klassiska Django Welcome-sidan. För att se till att allt är bra från Heroku perspektiv kan vi också köra applikationen så här:

$ heroku lokal webb

För att bevisa hur snabbt vi kan gå online, låt oss göra vår första utplacering till Heroku:

$ heroku login $ heroku skapa

Vi har nu skapat en Heroku-ansökan, men vi har inte skickat någon kod till Heroku. Observera att Heroku skapade ett användarvänligt app-id. Här är produktionen du ska få:

Skapar app ... gjort, ⬢  https: //.herokuapp.com/ | https://git.heroku.com/.git

Vi behöver nu associera vår repo med den nyskapade Heroku appen:

$ heroku git: remote -a  $ git push heroku master $ heroku öppen

Awesome, du har just installerat en app till Heroku. Det gör inte mycket, men du lägger något online på rekordtid. Bra jobbat.

Ställa in databasen

Du kommer nog inte någonsin att bygga en icke-trivial webbapp utan en databas. Databasen är datalagringsdelen i webappen. Här är webappen som håller sitt tillstånd (åtminstone det mesta). Här håller vi användarkonton och inloggningsuppgifter och mycket, mycket mer. Heroku tillhandahåller en hanterad PostgreSQL-tjänst. 

Det är vad vi ska använda. Se till att du har installerat Postgres på din maskin och skapat en databasinstans att använda i vår applikation. Heroku behöver en miljövariabel som ska ställas in för att kunna ansluta till databastjänsten. Den variabel vi behöver ställa in är DATABASE_URL:

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

Låt oss nu berätta för Django att tillämpa migrationerna och skapa de nödvändiga tabellerna:

$ ./manage.py migrera

Låt oss skapa en superanvändare och logga in på admingränssnittet på http: // localhost: 8000 / admin:

$ ./manage.py skapar uppgift $ ./manage.py körserver

Vi kan se att tabellerna verkligen har skapats. Heroku har redan associerat en databasinstans till din app som standard. Du kan se till att det är fallet genom att checka in Heroku HEROKU_APP_ID> Inställningar> Config-variabler i din Heroku-konsol. Du borde se här att DATABASE_URL är inställd på en Heroku genererad databasadress. 

Vi måste nu köra migrationerna och skapa superkommandon på nätet online. Låt oss se om allt fungerar som förväntat:

$ heroku kör python manage.py migrera $ heroku kör python manage.py skapar uppgift

Om allt gick bra, om vi besöker https: //.herokuapp.com/admin/, Vi borde kunna logga in med referenser som vi just tillhandahöll.

Användarautentisering

I det här avsnittet kommer vi att initiera en Django-app och använda Django-fördefinierade komponenter för att skapa användarautentiseringsfunktionaliteten i vår app.

$ ./manage.py startapp main

Inuti den nya appen ska vi skapa en urls.py fil:

från django.conf.urls importera url från django.contrib.auth importera visningar som auth_views från django.views.generic.base import RedirectView urlpatterns = [url ('^ $', RedirectView.as_view (url = 'login'), namn = "index"), url (r '^ login $', auth_views.LoginView.as_view (), namn = "inloggning"), url (r '^ logout $', auth_views.LogoutView.as_view (), name = " logga ut"), ] 

Här använder vi tre generiska Django-vyer:

  • RedirectView: Eftersom grundadressen till programmet inte gör något, omdirigeras vi till inloggningssidan.
  • LoginView: Django fördefinierad vy som skapar inloggningsformuläret och implementerar användarautentiseringsrutinen.
  • LogoutView: Django fördefinierad vy som loggar ut en användare och omdirigerar till en viss sida.

Lägg till huvud ansökan till INSTALLED_APPS lista:

INSTALLED_APPS = ['django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', # Inaktivera Djangos egen statiska filhantering i gynnar WhiteNoise, för # större konsistens mellan gunicorn och './manage.py runserver'. Se: # http://whitenoise.evans.io/en/stable/django.html#using-whitenoise-in-development 'whitenoise.runserver_nostatic', 'django.contrib.staticfiles', 'main',]

Haka upp main.urls till root-URL-schemat:

från django.conf.urls import url, inkludera från django.contrib import admin urlpatterns = [url (r '^', inkludera ('main.urls')), url (r 'admin /', admin.site.urls )]

För att visa formuläret korrekt, med stilar och klasser och allt, måste vi installera django-widget-tweaks:

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

Lägg till django-widget-tweaks till INSTALLED_APPS:

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

Vi lägger nu till dessa två configs till settings.py:

  • LOGIN_REDIRECT_URL: Berättar Django var att omdirigera en användare efter en framgångsrik autentisering.
  • LOGOUT_REDIRECT_URL: Berättar Django var att omdirigera användaren efter att han / hon loggat ut.
# settings.py LOGIN_REDIRECT_URL = 'instrumentpanel' LOGOUT_REDIRECT_URL = 'inloggning'

Låt oss skriva en enkel huvudmall base.html och a dashboard.html mall som utökar den. Vi kommer senare till instrumentpanelen.

     % block title% % endblock%   
% block content% % endblock%
% utökar 'base.html'% % block title% Dashboard % endblock% % block content% 

instrumentbräda

% endblock%

Skriv den vy som gör dashboard.html mall:

från django.shortcuts import render från django.core.urlresolvers importera reverse_lazy @login_required (login_url = reverse_lazy ('login')) def dashboard (request): returnera render (request, 'dashboard.html')

Vi är alla uppsatta. Gå över till http: // localhost: 8000 / användarnamn / och testa att autentisering fungerar. Spara sedan dina framsteg:

$ git lägg till. $ git commit -m "Logga in / Logga ut / Dashboard visningar"

Skapa kupongmodellen

Nu har vi kommit till den viktigaste delen av vår ansökan och utformat kupongmodellen. Vi installerar django-modell-utils att lägga till några extra egenskaper till våra modeller.

$ pip installera django-modell-utils $ pip frysa> requirements.txt

Skriv Kupong modell:

från model_utils.models importera TimeStampedModel, TimeFramedModel från django.db importmodeller från django.contrib.auth.models importera Användarklasskupong (TimeStampedModel, TimeFramedModel): owner = models.ForeignKey (Användare) discount_code = models.CharField ("Rabattkod" , max_length = 100) website = models.URLField ("Website") description = models.TextField ("Kupongbeskrivning")

De django-modell-utils modeller vi förlängt gör det möjligt för oss att:

  • TimeStampedModel hjälper oss att spåra när modellen placerades i databasen via skapad fält.
  • TimeFramedModel lägger till Start och slutet fält till vår modell. Vi använder dessa fält för att hålla koll på kupongens tillgänglighet.

Haka modellen till admin:

från django.contrib import admin från .models import Kupong @ admin.register (Kupong) klass CouponAdmin (admin.ModelAdmin): passera

Skapa och tillämpa migreringar:

$ ./manage.py makemigrations $ ./manage.py migrera

Spara framsteg:

$ git lägg till. $ git commit -m "Skapa kupong modell"

ModelForm för kupong skapande

En av de coola funktionerna i Django är möjligheten att skapa former från modellklasser. Vi ska skapa en sådan form som gör att användarna kan skapa kuponger. Låt oss skapa en forms.py filen inuti huvud Ansökan:

från django.forms importera ModelForm från .models import Kupongklass CouponForm (ModelForm): klass Meta: modell = Kupong exkluderar = ('ägare') # Vi ställer in oss själva själva

Låt oss lägga till denna blankett i instrumentpanelen. Vi behöver ändra både vyn och mallen:

# views.py från django.shortcuts import render, omdirigera från django.core.urlresolvers importera reverse_lazy från .forms import CouponForm @login_required (login_url = reverse_lazy ('inloggning')) def dashboard (request): om request.method == ' POST ': blankett = CouponForm (request.POST) om form.is_valid (): coupon = form.save (commit = False) coupon.owner = request.user coupon.save () returnera omdirigering (' instrumentpanel ') annars: formulär = CouponForm () returnera render (begäran, "dashboard.html", context = 'create_form': form)
% utökar 'base.html'% % load widget_tweaks% % block title% Dashboard % endblock% % block content% 

instrumentbräda

% csrf_token%
% render_field create_form.discount_code placeholder = "Rabattkod"%
% render_field create_form.website placeholder = "Webbplats"%
% render_field create_form.description placeholder = "Beskrivning"%
% render_field create_form.start placeholder = "Tillgänglig från (MM / DD / ÅÅÅÅ)"%
% render_field create_form.end placeholder = "Expires On (MM / DD / ÅÅÅÅ)"%
% endblock%

Vi har nu ett sätt att skapa kuponger från instrumentbrädan. Ge det ett försök. Vi har ingen möjlighet att se kupongerna på instrumentpanelen, men vi kan göra det på adminpanelen. Låt oss spara framstegen:

$ git lägg till. $ git commit -m "Kupong skapande formulär i instrumentbrädan"

Förfallande kort kuponger

En sak vi vill visas i instrumentbrädan: kuponger som löper ut snart, till exempel de som löper ut den här veckan.

Lägg till django.contrib.humanize till INSTALLED_APPS att visa datum i mallarna på ett mänskligt sätt.

Låt oss förbättra visningen så att den hämtar de snart utgående kupongerna och skickar dem till mallkontexten:

från datetime import timedelta från django.contrib.auth.decorators importera login_required från django.shortcuts import render, omdirigera från django.core.urlresolvers importera reverse_lazy från django.utils importera tidszon från .forms import CouponForm från .models import Kupong @login_required (login_url = reverse_lazy ('login')) def dashboard (begäran): expiring_coupons = Coupon.objects.filter (end__gte = timezone.now (), end__lte = timezone.now () + timedelta (days = 7)) om request.method = = 'POST': blankett = CouponForm (request.POST) om form.is_valid (): coupon = form.save (commit = False) coupon.owner = request.user coupon.save () returnera omdirigering ('instrumentpanel') annars : form = CouponForm () return render (begäran, 'dashboard.html', context = 'create_form': formulär, 'expiring_coupons': expiring_coupons)

Låt oss uppdatera mallen så att den visar de utgående kupongerna på ett tabellformat. Vi lägger också skapningsformuläret och tabellen i två separata kolumner med Bootstraps nätverkssystem:

% sträcker sig 'base.html'% % load widget_tweaks% % load humanize% % block title% Dashboard % endblock% % block content% 

instrumentbräda

[Formulärkoden]
% om expiring_coupons% % för kupong i expiring_coupons% % endfor%
Rabattkod Hemsida Utgångsdatum
Coupon.discount_code Coupon.website coupon.end | naturalday
% else%
Inga kuponger slutar snart
% endif% % endblock%

Ser bra ut. Spara dina framsteg:

$ git lägg till. $ git commit -m "Implementera den utgående kuponglistan"

Katalogvy

Låt oss nu lära oss några andra Django-genvägar för att skapa en vy som visar listan över kuponger som vi har tillgängliga. Vi pratar om generiska vyer. Så här skapar du snabbt en Listvy:

# views.py # ... från django.views.generic.list importera ListView från django.db.models importera Q-klass CouponListView (ListView): modell = Kupong def get_queryset (själv): returnera Coupon.objects.filter (Q (end__gte = timezone.now ()) Q (end__isnull = True)). order_by ('- end')

Koppla nu vyn i ditt webbadressschema:

# main / urls.py från django.conf.urls importera url från django.contrib.auth importera visningar som auth_views från django.views.generic.base import RedirectView från .views import dashboard, CouponListView urlpatterns = [url ('^ $' , RedirectView.as_view (url = 'login'), namn = "index"), url (r '^ inloggning / $', auth_views.LoginView.as_view (), namn = "inloggning"), url (r '^ logout / $ ', auth_views.LogoutView.as_view (), namn = "logout"), url (r' dashboard / $ ', instrumentpanel, namn = "instrumentbräda"), url (r' ^ catalog / $ ', CouponListView. as_view (template_name = 'catalogue.html'), namn = "katalog")]

Skapa mallen catalogue.html:

% sträcker sig 'base.html'% % load humanize% % block title% Katalog % endblock% % block content% 

Katalog

% om object_list% % för kupong i object_list% % endfor%
Rabattkod Hemsida Utgångsdatum
Coupon.discount_code Coupon.website coupon.end | naturalday
% else%
Inga kuponger än. Skapa din första här.
% endif% % endblock%

Eftersom vi har kopplat upp allt, gå över till http: // localhost: 8000 / katalog / för att se din kupongkatalog.

Spara framstegen:

$ git lägg till. $ git commit -m "Skapa katalogvy"

Detta är ganska nära en MVP. Jag uppmuntrar dig att göra lite finjustering som att skapa navbar, logga in / logga ut / registrera knappar etc. Det viktiga är att du förstår prototypprocessen och får din produkt där ute för att människor ska se den. På vilket sätt är vår produkt ännu inte online. Vi tryckte inte den senaste versionen till Heroku. Låt oss göra det och hämta sedan telefonen och ringa till investerarna.

Slutsats

Vi skapade en enkel men praktisk tillämpning. Vi skapade funktioner snabbt, och vi har distribuerat dem online så att våra potentiella kunder kan använda dem och ge oss feedback. Det är bättre att visa människor istället för att bara prata om en idé. 

Här är några slutsatser vi kan dra:

  • Att välja rätt verktyg kan påskynda utvecklingsprocessen.
  • De verktyg som används för prototypning är inte alltid det bästa valet för mer mogna projekt. Med tanke på det är det bättre att använda mer smidiga verktyg tidigt och iterera på dem istället för att gå vilse i minuters implementeringsdetaljer tidigt.
  • Att utnyttja en PaaS innebär att applikationerna måste respektera några designmönster. Vanligtvis är dessa mönster meningsfulla, och de tvingar oss att skriva ännu bättre kod.
  • Django har många genvägar som gör våra liv enklare:
    • Django ORM hjälper till med databasåtkomst. Du behöver inte oroa dig för att skriva korrekt SQL och vara extra försiktig med syntaxfel.
    • Migreringar hjälper oss att versionera och iterera på databasschemat. Du behöver inte gå och skriva SQL för att skapa tabeller eller lägga till kolumner.
    • Django har en plugin-friendly arkitektur. Vi kan installera appar som hjälper oss att uppnå våra mål snabbare.
    • Generella visningar och modellformer kan injicera några av de vanligaste beteendena: noteringsmodeller, skapa modeller, autentisering, omdirigering, etc.
  • När du startar är det viktigt att vara mager och snabb. Slösa inte tid, och spendera inte pengar.