Itereren snel met Django & Heroku

Het starten van een online bedrijf kan erg ingewikkeld zijn. Hoewel het op papier veel gemakkelijker is om een ​​online bedrijf te creëren dan een echte, kan een ondernemer verdwalen in de veelheid aan opties. Enkele van de meest voorkomende valkuilen waar een online ondernemer in vastloopt zijn:

  • Te veel te vroeg bouwen: Verlies tijd en verbrand geld door een ingewikkeld product te bouwen. Raak gedemotiveerd onderweg, verliest vertrouwen in het product en verlaat het project.
  • Te veel geloven in het idee: Vasthouden aan het oorspronkelijke idee en er niet op itereren, ook al komen klanten niet opdagen, betalen ze niet of zijn ze niet tevreden.
  • Niet starten: Wanneer iemand begint aan het pad van het bouwen van een webproject, kan hij / zij overweldigd raken door de schijnbaar oneindige beslissingen en keuzes die gemaakt moeten worden. Welke hosting te gebruiken? Welk platform? Welk WordPress-thema? Hoe maak je een hoogconverterende bestemmingspagina? Welke programmeertaal en welke database? Moet u een webraamwerk gebruiken? Vanille JavaScript of jQuery voor de voorkant? Misschien een complexer front-end framework omdat het project er een nodig heeft zodra het volwassen genoeg is?
  • Niet lukken: Bij het bouwen van een webproject, zelfs al hebt u besloten over uw technologiestack, kunt u overweldigd raken door de feedback die u krijgt. Contra-intuïtief gezien, wordt het als een vergissing beschouwd om naar teveel feedback te luisteren. Het kan de feedback zijn van mensen die uw product toch niet zouden gebruiken. Mensen hebben de neiging om een ​​mening over alles te hebben, ook al zijn ze niet volledig deskundig op dit gebied.

Gezien de vele manieren waarop je onderweg kunt falen, is het erg belangrijk om:

  • Bouw zo weinig en zo snel mogelijk en laat het zien aan mensen die u als potentiële klanten beschouwt: Minimaliseer kosten en moeite.
  • Zet het zo snel mogelijk online: Krijg feedback van mensen op het product, niet op uw abstracte idee.
  • Breng snel wijzigingen aan: Wanneer u leert wat de klant wil, is het van cruciaal belang om wendbaar te zijn en uw eerste betalende klanten goed te dienen.

Hier komt prototyping op zijn plaats. Een ondernemer moet slank zijn, geen tijd en middelen verspillen. In het begin zo min mogelijk bouwen, kan een deugd zijn. 

Er zijn veel stromingen over wat een prototype is en hoe het moet worden gemaakt. Sommigen zeggen dat het alleen een landingspagina zou moeten zijn, andere dat het een uitgeklede versie van het eindproduct zou moeten zijn. Ik ben meer een fan van de seconde. Als u alleen een bestemmingspagina gebruikt, kan dit oplichterijgevoelig zijn. Ook kun je geen feedback krijgen over hoe je het probleem oplost, maar alleen of het probleem de moeite van het oplossen waard is.

Hier is de toolbelt van een slimme prototyping online ondernemer:

  • Front-end frameworks: Bootstrap, Foundation, jQuery, Vue, etc. Met behulp van een front-end framework werken uw apps op verschillende schermformaten en verschillende browsers, met een fatsoenlijk ontwerp.
  • Back-end frameworks: Django, Ruby on Rails, Laravel. Het gebruik van back-end frameworks helpt u eenvoudig om te gaan met HTML-sjablonen, HTTP-formulieren, databasetoegang, URL-schema's, enz.
  • Platform-as-a-Service: Heroku, Google App Engine, AWS Elastische bonenstaak. Het kiezen van een PaaS kan u bevrijden van de pijn van het beheren van servers, log aggregatie, uptime monitoring, implementatie-infrastructuur en meer.

In deze tutorial bouwen we een eenvoudige applicatie in de geest van rapid prototyping. We gebruiken Django, Bootstrap CSS en Heroku. De focus zal liggen op het back-end gedeelte in plaats van op de voorkant. 

We gaan profiteren van het Heroku-platform om iets vroeg online te zetten en snel nieuwe functies in te zetten. We gaan Django gebruiken om complexe databasemodellen en -functionaliteit te bouwen. Bootstrap CSS geeft ons een verstandige standaardstijl voor onze pagina's. Genoeg gepraat, laten we gaan.

Wat we bouwen

Zorg dat je hier voor zit. Het idee zal je sokken uitschakelen. Hier is de toonhoogte: haat je niet gewoon hoe je al deze kortingscodes krijgt, maar je vergeet ze te gebruiken en ze vervallen? 

Zou het niet cool zijn om de codes ergens op te slaan waar je ze kunt doorzoeken en ook een melding krijgen als ze op het punt staan ​​te vervallen? Ik weet het, geweldig idee, toch? Welnu, zet je creditcard neer, je zult hier niet in investeren. Je gaat het bouwen.

Ermee beginnen

In deze tutorial ga ik Python 3 gebruiken. Als u Python 2.7 gebruikt, moeten de wijzigingen vrij eenvoudig zijn. Ik ga ook aannemen dat je bekend bent met setuptools, Python virtualenvs en Git. Nog een ding voordat je verder gaat: zorg dat je een GitHub- en een Heroku-account hebt. Om Heroku te gebruiken, moet u ook de Heroku CLI installeren. 

Laten we beginnen met het maken van een virtualenv:

$ mkvirtualenv coupy

Zoals u waarschijnlijk wel weet, is onze applicatienaam Coupy. Laten we overschakelen naar de nieuwe virtualenv, $ werk aan coupé, en installeer Django: 

$ pip installeer Django

Ga naar je GitHub-account en maak een nieuw project. Laten we vervolgens dat project klonen:

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

De volgende logische stap is om een ​​Django-project te maken. Om een ​​Django-project in Heroku te implementeren, moeten we enkele richtlijnen volgen. Gelukkig kunnen we daarvoor een projectsjabloon gebruiken. Hier is hoe te om dat te doen:

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

Mogelijk moet u enkele mappen verplaatsen. Zorg ervoor dat de hoofdmap van uw repository er als volgt uitziet:

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

Laten we nu de vereisten van de sjabloon installeren:

$ pip install -r requirements.txt

We willen nu de nieuw gecreëerde bestanden naar GitHub pushen:

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

Laten we eens kijken of wat we tot nu toe hebben gedaan werkt:

$ python manage.py runserver

Open nu een browservenster en ga naar http: // localhost: 8000. Als alles goed is, zou je de klassieke Django-welkomstpagina moeten zien. Om ervoor te zorgen dat alles goed is vanuit het perspectief van Heroku, kunnen we de toepassing ook als volgt uitvoeren:

$ heroku local web

Om te bewijzen hoe snel we online kunnen gaan, maken we onze eerste implementatie bij Heroku:

$ heroku login $ heroku create

We hebben nu een Heroku-applicatie gemaakt, maar we hebben geen code naar Heroku gestuurd. Merk op dat Heroku een gebruiksvriendelijke app-id heeft gemaakt. Dit is de uitvoer die u zou moeten krijgen:

App maken ... klaar, ⬢  https: //.herokuapp.com/ | https://git.heroku.com/.git

We moeten nu onze repo koppelen aan de nieuw gemaakte Heroku-app:

$ heroku git: remote -a  $ git push heroku master $ heroku open

Geweldig, je hebt net een app naar Heroku geïmplementeerd. Het doet niet veel, maar je hebt in een recordtijd iets online gezet. Goed gedaan.

De database instellen

U zult waarschijnlijk nooit een niet-triviale web-app bouwen zonder een database. De database is het gedeelte voor gegevensopslag van de webapp. Hier is waar de web-app zijn status behoudt (althans het grootste deel). Hier bewaren we de gebruikersaccounts en de inloggegevens en nog veel, veel meer. Heroku biedt een beheerde PostgreSQL-service. 

Dat is wat we gaan gebruiken. Zorg ervoor dat u PostGres op uw computer hebt geïnstalleerd en maak een database-instantie die u in onze toepassing kunt gebruiken. Heroku heeft een omgevingsvariabele nodig die kan worden ingesteld om verbinding te kunnen maken met de databaseservice. De variabele die we moeten instellen is DATABASE_URL:

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

Laten we Django nu vertellen om de migraties toe te passen en de nodige tabellen te maken:

$ ./manage.py migreren

Laten we een superuser maken en inloggen op de admin-interface op http: // localhost: 8000 / admin:

$ ./manage.py createuperuser $ ./manage.py runserver

We kunnen zien dat de tabellen inderdaad zijn gemaakt. Heroku heeft standaard al een database-instantie gekoppeld aan uw app. U kunt ervoor zorgen dat dit het geval is door in Heroku in te checken HEROKU_APP_ID> Instellingen> Variabelen configureren in je online Heroku-console. Je zou hier moeten zien dat de DATABASE_URL is ingesteld op een door Heroku gegenereerd database-adres. 

We moeten nu de migraties uitvoeren en de supergebruikersopdrachten online maken. Laten we kijken of alles werkt zoals verwacht:

$ heroku voer python uit manage.py migreer $ heroku voer python uit manage.py maaktuperuser

Als alles goed ging, als we het bezoeken https: //.herokuapp.com/admin/, we zouden moeten kunnen inloggen met de inloggegevens die we zojuist hebben verstrekt.

Gebruikersverificatie

In dit gedeelte gaan we een Django-app initialiseren en Django-vooraf gedefinieerde componenten gebruiken om de gebruikersauthenticatiefunctionaliteit in onze app te maken.

$ ./manage.py startapp main

Binnen de nieuwe app gaan we een maken urls.py het dossier:

van django.conf.urls importeer URL van django.contrib.auth importeer views als auth_views van django.views.generic.base import RedirectView urlpatterns = [url ('^ $', RedirectView.as_view (url = 'login'), naam = "index"), url (r '^ login $', auth_views.LoginView.as_view (), name = "login"), url (r '^ logout $', auth_views.LogoutView.as_view (), name = " uitloggen"), ] 

Hier gebruiken we drie generieke Django-weergaven:

  • RedirectView: Omdat de basis-URL van de toepassing niets doet, worden we doorgestuurd naar de inlogpagina.
  • LoginView: Django heeft een voorgedefinieerde weergave gemaakt die het aanmeldingsformulier maakt en de routine voor gebruikersauthenticatie implementeert.
  • LogoutView: Django heeft een voorgedefinieerde weergave die een gebruiker logt en doorstuurt naar een bepaalde pagina.

Voeg de toe hoofd toepassing op de INSTALLED_APPS lijst:

INSTALLED_APPS = ['django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', # Schakel Django's eigen staticfiles-afhandeling in uit gunst van WhiteNoise, voor # grotere consistentie tussen gunicorn en './manage.py runserver'. Zie: # http://whitenoise.evans.io/en/stable/django.html#using-whitenoise-in-development 'whitenoise.runserver_nostatic', 'django.contrib.staticfiles', 'main',]

Sluit de main.urls naar het root URL-schema:

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

Om de formulieren correct weer te geven, met stijlen en klassen en alles, moeten we installeren Django-widget-tweaks:

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

Toevoegen Django-widget-tweaks naar INSTALLED_APPS:

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

We voegen nu deze twee configs toe aan settings.py:

  • LOGIN_REDIRECT_URL: Vertelt Django waar een gebruiker moet worden omgeleid na een succesvolle authenticatie.
  • LOGOUT_REDIRECT_URL: Vertelt Django waar de gebruiker moet worden omgeleid nadat hij / zij zich heeft afgemeld.
# settings.py LOGIN_REDIRECT_URL = 'dashboard' LOGOUT_REDIRECT_URL = 'login'

Laten we een eenvoudige hoofdsjabloon schrijven base.html en een dashboard.html sjabloon die het uitbreidt. We komen later terug op het dashboard.

     % block title% % endblock%   
% block content% % endblock%
% breidt 'base.html'% % block title% Dashboard % endblock% % block content% uit 

Dashboard

% endblock%

Schrijf de weergave die de dashboard.html sjabloon:

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

We zijn er klaar voor. Ga naar http: // localhost: 8000 / login / en testen of verificatie werkt. Sla vervolgens je voortgang op:

$ git add. $ git commit -m "Aanmelden / Afmelden / Dashboard-weergaven"

Maak het couponmodel

Nu zijn we bij het belangrijkste onderdeel van onze toepassing gekomen, het ontwerpen van het couponmodel. We zullen installeren Django-model-utils om wat extra eigenschappen toe te voegen aan onze modellen.

$ pip installeer django-model-gebruikt $ pip freeze> requirements.txt

Schrijf de Coupon model:

van model_utils.models importeer TimeStampedModel, TimeFramedModel van django.db importeer modellen van django.contrib.auth.models import Gebruikersklasse Coupon (TimeStampedModel, TimeFramedModel): owner = models.ForeignKey (User) discount_code = models.CharField ("Discount Code") , max_length = 100) website = models.URLField ("Website") description = models.TextField ("Beschrijving coupon")

De Django-model-utils modellen die we hebben uitgebreid stellen ons in staat om:

  • TimeStampedModel helpt ons bij te houden wanneer het model in de database werd geplaatst, via de aangemaakt veld-.
  • TimeFramedModel voegt het toe begin en einde velden naar ons model. We gebruiken deze velden om de beschikbaarheid van de kortingsbon bij te houden.

Koppel het model aan de beheerder:

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

Aanmaken en toepassen van migraties:

$ ./manage.py migratiemigraties $ ./manage.py migreren

Voortgang opslaan:

$ git add. $ git commit -m "Create Coupon-model"

ModelForm voor het maken van een kortingsbon

Een van de coole functies van Django is de mogelijkheid om formulieren van modelklassen te maken. We gaan zo'n formulier maken waarmee gebruikers kortingsbonnen kunnen maken. Laten we een maken forms.py bestand in de hoofd toepassing:

van django.forms import ModelForm van .models import Coupon klasse CouponForm (ModelForm): class Meta: model = Coupon exclude = ('owner',) # We stellen dit veld zelf in

Laten we dit formulier toevoegen aan het dashboard. We moeten zowel de weergave als de sjabloon wijzigen:

# views.py van django.shortcuts importeren renderen, omleiden van django.core.urlresolvers importeren reverse_lazy van .forms importeren CouponForm @login_required (login_url = reverse_lazy ('inloggen')) def dashboard (request): if request.method == ' POST ': form = CouponForm (request.POST) als form.is_valid (): coupon = form.save (commit = False) coupon.owner = request.user coupon.save () retouromleiding (' dashboard ') else: formulier = CouponForm () retourrendering (verzoek, 'dashboard.html', context = 'create_form': formulier)
% breidt 'base.html'% % load widget_tweaks% % block title% Dashboard % endblock% % block content% uit 

Dashboard

% csrf_token%
% render_field create_form.discount_code placeholder = "Kortingscode"%
% render_field create_form.website placeholder = "Website"%
% render_field create_form.description placeholder = "Beschrijving"%
% render_field create_form.start placeholder = "Beschikbaar vanaf (MM / DD / JJJJ)"%
% render_field create_form.end placeholder = "Vervalt op (MM / DD / JJJJ)"%
% endblock%

We hebben nu een manier om kortingsbonnen van het dashboard te maken. Ga het proberen. We kunnen de kortingsbonnen niet zien in het dashboard, maar we kunnen dit doen in het beheerdersdashboard. Laten we de voortgang opslaan:

$ git add. $ git commit -m "Formulier voor het maken van coupons in dashboard"

Vervalt snel Coupons

Nog één ding willen we in het dashboard worden weergegeven: kortingsbonnen die binnenkort aflopen, bijvoorbeeld kortingsbonnen die deze week verlopen.

Toevoegen django.contrib.humanize naar INSTALLED_APPS om datums in de sjablonen op een mensvriendelijke manier weer te geven.

Laten we de weergave verbeteren zodat deze de snel verlopende kortingsbonnen ophaalt en doorgeeft aan de sjablooncontext:

van datetime importeren timedelta van django.contrib.auth.decorators importeren login_required van django.shortcuts importeren renderen, omleiden van django.core.urlresolvers importeren reverse_lazy van django.utils importeren tijdzone van .forms importeren CouponForm van .models importeren Coupon @login_required (login_url = reverse_lazy ('login')) def dashboard (request): expiring_coupons = Coupon.objects.filter (end__gte = timezone.now (), end__lte = timezone.now () + timedelta (days = 7)) if request.method = = 'POST': form = CouponForm (request.POST) als form.is_valid (): coupon = form.save (commit = False) coupon.owner = request.user coupon.save () retouromleiding ('dashboard') anders : form = CouponForm () return render (request, 'dashboard.html', context = 'create_form': form, 'expiring_coupons': expiring_coupons)

Laten we de sjabloon bijwerken zodat deze de verlopen coupons op een tabellarische manier weergeeft. We zullen ook het aanmaakformulier en de tabel in twee afzonderlijke kolommen plaatsen met behulp van Bootstrap's rastersysteem:

% breidt 'base.html'% % load widget_tweaks% % load humanize% % block title% Dashboard % endblock% % block content% uit 

Dashboard

[De formuliercode]
% if expiring_coupons% % voor coupon in expiring_coupons% % endfor%
Kortingscode Website Vervaldatum
Coupon.discount_code Coupon.website coupon.end | naturalday
% else%
Geen kortingsbonnen verlopen binnenkort
% endif% % endblock%

Ziet er goed uit. Bewaar je voortgang:

$ git add. $ git commit -m "Implementatie van de verlopen kortingsbonlijst"

Catalogusweergave

Laten we nu een aantal andere Django-snelkoppelingen leren om een ​​weergave te maken die de lijst met kortingsbonnen weergeeft die we beschikbaar hebben. We hebben het over generieke weergaven. U kunt als volgt snel een maken Lijstweergave:

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

Bind nu de weergave in uw URL-schema:

# main / urls.py van django.conf.urls import url van django.contrib.auth import views als auth_views van django.views.generic.base import RedirectView from .views import dashboard, CouponListView urlpatterns = [url ('^ $' , RedirectView.as_view (url = 'login'), naam = "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"),]

Maak de sjabloon catalogue.html:

% breidt 'base.html'% % load humanize% % block title% Catalog % endblock% % block content% uit 

Catalogus

% if object_list% % voor coupon in objectlijst% % endfor%
Kortingscode Website Vervaldatum
Coupon.discount_code Coupon.website coupon.end | naturalday
% else%
Nog geen coupons. Maak hier je eerste.
% endif% % endblock%

Aangezien we alles hebben aangesloten, ga je naar http: // localhost: 8000 / catalogus / om uw couponcatalogus te bekijken.

Bewaar de voortgang:

$ git add. $ git commit -m "De catalogusweergave maken"

Dit komt aardig in de buurt van een MVP. Ik moedig u aan om een ​​aantal fijne afstemmingen uit te voeren, zoals het maken van een navigatiebalk, inlog- / logout- / registerknoppen, enz. Het belangrijkste is dat u het proces van prototyping begrijpt en uw product daar krijgt zodat mensen het kunnen zien. Nu we het daarover hebben, ons product is nog niet online. We hebben de nieuwste versie niet naar Heroku geduwd. Laten we dat doen en dan de telefoon opnemen en de beleggers bellen.

Conclusie

We hebben een eenvoudige maar praktische applicatie gemaakt. We hebben functies snel gemaakt en we hebben ze online geïmplementeerd, zodat onze potentiële klanten ze kunnen gebruiken en feedback kunnen geven. Het is beter om mensen te laten zien in plaats van alleen over een idee te praten. 

Hier zijn enkele conclusies die we kunnen trekken:

  • Het kiezen van de juiste tools kan het ontwikkelingsproces aanzienlijk versnellen.
  • De tools die worden gebruikt voor prototyping zijn niet altijd de beste keuze voor meer volwassen projecten. Met dat in gedachten is het beter om al in een vroeg stadium agile tools te gebruiken en deze eerder uit te werken in plaats van ze in een vroeg stadium te verliezen in de details van de implementatie..
  • Profiteren van een PaaS betekent dat de applicaties een paar ontwerppatronen moeten respecteren. Meestal kloppen deze patronen, en ze dwingen ons om nog betere code te schrijven.
  • Django heeft veel snelkoppelingen die ons leven gemakkelijker maken:
    • Django ORM helpt bij toegang tot databases. U hoeft zich geen zorgen te maken over het schrijven van de juiste SQL en wees extra voorzichtig met syntaxisfouten.
    • Migraties helpen ons het databaseschema te verslaan en te itereren. U hoeft niet te gaan en SQL te schrijven om tabellen te maken of kolommen toe te voegen.
    • Django heeft een plug-in vriendelijke architectuur. We kunnen apps installeren die ons helpen onze doelen sneller te bereiken.
    • Generieke weergaven en modelvormen kunnen enkele van de meest voorkomende gedragingen injecteren: lijstmodellen, het maken van modellen, authenticatie, doorverwijzing, enz..
  • Bij het opstarten is het belangrijk om mager en snel te zijn. Verspil geen tijd en besteed geen geld.