ArunRocks - Building a Hacker News Clone in Django - Part 1

download ArunRocks - Building a Hacker News Clone in Django - Part 1

of 12

Transcript of ArunRocks - Building a Hacker News Clone in Django - Part 1

  • Building a Hacker News clone in Django -Part 1(http://arunrocks.com/building-a-hacker-news-clone-in-django-part-1/)

    You are reading a post from a four-part tutorial series

    Part 1(/building-a-hacker-news-clone-in-django-part-1/) Part 2(/building-a-hacker-news-clone-in-django-part-2/)

    Part 3(/building-a-hacker-news-clone-in-django-part-3/) Part 4(/building-a-hacker-news-clone-in-django-part-4/)

    There is no better way to learn something than to watch someone else do it .So, if you have been waiting to go beyond the basics in Django, you havecome to the right place.

    In this video tutorial series, I would take you through building a social newssite called Steel Rumors from scratch in Django 1.5. In case you dont likevideos and prefer to read the steps, you can find them here too.

    Even though we will start from the basics, if you are an absolute beginner toDjango, I would suggest reading thetutorial(https://docs.djangoproject.com/en/dev/intro/tutorial01/) or myprevious screencast on building a blog in30 mins(http://www.youtube.com/watch?v=srHZoj3ASmk)

    The completed site would support user signups, link submissions,comments, voting and a cool ranking algorithm. My approach would be touse as many builtin Django features as possible and use external apps onlywhen absolutely necessary.

    Check out a [demo of Steel Rumors][demo] yourself.

    Click on the image below to watch the screencast or scroll down to readthe steps.

    BLOG(/ ARCH IVES / )ABOUT (H TTP :/ / ARUNROCKS .COM / ABOUT/ )

    A RU N RO CKS ( / )

    Arun Ravindran

    1

  • (http://www.youtube.com/watch?v=ST9d7qevCVo&hd=1)

    If you liked this tutorial, then you should sign up for my upcoming bookBuilding a Social News Site in Django(https://leanpub.com/social-news-site-in-django). It tries to explain in a learn-from-a-friend style how websitesare built and gradually tackles advanced topics like database migrationsand debugging.

    Step-by-step Instructions

    Here is the text version of the video for people who prefer to read. We aregoing to create a social news site similar to HackerNews(https://news.ycombinator.com/) or Reddit(http://www.reddit.com/). Itwill be called Steel Rumors and would be a place to share and vote someinteresting rumors about Man ofSteel(http://www.imdb.com/title/tt0770828/).

    The outline of Part 1 of the screencast is:

    ObjectiveVirtualEnv - Start from Scratch!Model Managers - Dream Job #78Basic TemplateGeneric Views - ListView and DetailViewPagination - For free!

    Setup Virtual Environment

    1. We will create a virtual development environment usingvirtualenv(http://pypi.python.org/pypi/virtualenv) andvirtualenvwrapper(https://bitbucket.org/dhellmann/virtualenvwrapper/).Make sure you have installed them first:

    mkvirtualenv djangorocks

  • I use an Ubuntu variant called Xubuntu in my screencast. But youshould be able to replicate these steps in other OSes withminimal changes.

    2. Install Django (make sure you already have pip(http://www.pip-installer.org/en/latest/) installed)

    pip install Django==1.5

    You can also use Django 1.5.1. The latest Django version may or maynot work with our code, hence it is better to specify a version to followthis tutorial.

    Create Project and Apps

    1. Create a project called steelrumors:

    cd ~/projdjango-admin.py startproject steelrumorscd steelrumorschmod +x manage.py

    2. Open steelrumors/settings.py in your favourite editor. Locate andchange the following lines (changes in bold):

    1. ENGINE: django.db.backends.sqlite32. NAME: database.db,3. At the end of INSTALLED_APPS = ( django.contrib.admin,

    3. Next, change steelrumors/urls.py by uncommenting the following lines:

    from django.conf.urls import patterns, include, urlfrom django.contrib import adminadmin.autodiscover()

    urlpatterns = patterns('', url(r'^admin/', include(admin.site.urls)),)

    4. Sync to create admin objects and enter the admin details:

    ./manage.py syncdb

    5. Open a new tab or a new terminal and keep a server instance running(dont forget to issue workon djangorocks in this terminal):

    ./manage.py runserver

    6. Visit the admin page (typically athttp://127.0.0.1:8000/admin/(http://127.0.0.1:8000/admin/)) and login.

    7. Create links app:

    ./manage.py startapp links

    8. Enter the following two model classes into links/models.py:

  • from django.db import modelsfrom django.contrib.auth.models import User

    class Link(models.Model): title = models.CharField("Headline", max_length=100) submitter = models.ForeignKey(User) submitted_on = models.DateTimeField(auto_now_add=True) rank_score = models.FloatField(default=0.0) url = models.URLField("URL", max_length=250, blank=True) description = models.TextField(blank=True)

    def __unicode__(self): return self.title

    class Vote(models.Model): voter = models.ForeignKey(User) link = models.ForeignKey(Link)

    def __unicode__(self): return "%s upvoted %s" % (self.voter.username, self.link.title)

    9. Create the corresponding admin classes. Enter the following intolinks/admin.py:

    from django.contrib import adminfrom .models import Link, Vote

    class LinkAdmin(admin.ModelAdmin): passadmin.site.register(Link, LinkAdmin)

    class VoteAdmin(admin.ModelAdmin): passadmin.site.register(Vote, VoteAdmin)

    10. Enter the following into links/views.py:

    from django.views.generic import ListViewfrom .models import Link, Vote

    class LinkListView(ListView): model = Link

    11. Insert following lines into steelrumor/urls.py:

    from links.views import LinkListView...urlpatterns = patterns('', url(r'^$', LinkListView.as_view(), name='home'),

    12. Create a new templates directory and enter the following atsteelrumors/templates/links/link_list.html:

  • {% for link in object_list %} {{ link.title }} {% endfor %}

    13. Edit settings.py to add our two apps to the end of INSTALLED_APPS = (

    'links','steelrumors',)

    14. Sync to create link objects:

    ./manage.py syncdb

    Visit http://127.0.0.1:8000/admin/ and add a couple of Link objects.Now if you open http://127.0.0.1:8000/ you should see the added Links

    Add Branding

    1. Create a common base template at steelrumors/templates/base.html:

    Steel Rumors

    {% block content %}{% endblock %}

    2. Modify steelrumors/templates/links/link_list.html and surroundprevious code with this:

    {% extends "base.html" %}

    {% block content %}...{% endblock %}

    VoteCount Model Manager

    1. We need a count of votes within our generic ListView. Add these tolinks/models.py:

  • from django.db.models import Count

    class LinkVoteCountManager(models.Manager): def get_query_set(self): return super(LinkVoteCountManager, self).get_query_set().annotate( votes=Count('vote')).order_by('-votes')

    2. Insert these two lines into the Link class in links/models.py:

    class Link(models.Model):...

    with_votes = LinkVoteCountManager() objects = models.Manager() #default manager

    3. Edit links/views.py and insert these two lines into the LinkListView class:

    class LinkListView(ListView):...

    queryset = Link.with_votes.all() paginate_by = 3

    Crazy Fun

    You can add 100 votes to random headlines using the following lines in thedjango shell:

    $ ./manage.py shell>>> from links.models import Link, Vote>>> from django.contrib.auth.models import User>>> a = User.objects.all()[0]>>> for i in xrange(100): Vote(link=Link.objects.order_by('?')[0],voter=a).save()

    Now visit http://127.0.0.1:8000/admin/ to find lots of Votes objects.

    Final Comments

    In case, you are wondering if this version of the site would be useful, I wouldsay that it works well for a private beta version. Any new user would have tobe added by the admin interface manually. They must be of the staff kind ifthey have to login via the admin interface. Staff can vote by manuallycreating Vote objects.

    The public facing part of the site can still show the top rumors based thevotes received by the staff. Based on how well designed the templates are,this version could be also used to get feedback about the sites designand branding.

    That concludes Part 1. Follow me on Twitter at@arocks(http://twitter.com/arocks/) to get updates about the following parts.

  • EDIT: Check out Part 2(/building-a-hacker-news-clone-in-django-part-2/)!

    Resources

    Full Source(https://github.com/arocks/steel-rumors/tree/episode1) onGithub (repository has changed!)

    1. This became very controversial. Most people learn best by doing itthemselves. But they need to read/hear/see it first from someone. I amactually a self-taught programmer. I learnt most of programming frombooks and trying it myself.

    Learning by doing is certainly the best way to learn. But among sourceof learning, watching an expert is probably the best.

    Arun Ravindran(http://arunrocks.com)

    Hi! Welcome to ArunRocks, an odd collection of writeups on programming,travel, gadgets and practically anything under the sun. This state of affairscould be blamed on the ecelectic interests of your host, Arun Ravindran. Heloves programming in several languages especially Python. In his day job heworks as a Solution Manager at Unisys. Read more...(/about/)

    Posted on: Wed 29 May 2013

    Tagged: screencast(http://arunrocks.com/tag/screencast.html) /django(http://arunrocks.com/tag/django.html) /python(http://arunrocks.com/tag/python.html) /technical(http://arunrocks.com/tag/technical.html) /tutorial(http://arunrocks.com/tag/tutorial.html) /steelrumors(http://arunrocks.com/tag/steelrumors.html)

    Don'tmissanyfutureposts!

    Subscribetoourmailinglist

    emailaddress

    Subscribe

  • Building a Hacker News clone inDjango - Part 2 (User Profilesand Registrations)(http://arunrocks.com/building-a-hacker-news-clone-in-django-part-2/)

    Easy and Practical Web scrapingin Python

    (http://arunrocks.com/easy-practical-web-scraping-in-python/)

    Share on: Twitter(http://twitter.com/share?url=http://arunrocks.com/building-a-hacker-news-clone-in-django-part-1/),Facebook(http://www.facebook.com/sharer.php?u=http://arunrocks.com/building-a-hacker-news-clone-in-django-part-1/),Google+(https://plus.google.com/share?url=http://arunrocks.com/building-a-hacker-news-clone-in-django-part-1/)

    Comments

    33Comments ArunRocks Login

    SortbyOldest Share

    Jointhediscussion

    Reply

    JonHearty ayearagoThanks,Arun!Watchingyour'Buildingablogin30minutes'videoonYouTubewasactuallyadefiningmomentformewhenitcametolearningPythonandDjangowithoutitIdon'tknowifIwouldeverhavecomeasfarasIhave.I'mactuallyworkingonbuildingsomethingverysimilartothisrightnow,soI'mexcitedtowatchthevideoandlearnsomethings!

    3

    Reply

    ArunRavindran ayearagoAuthor JonHeartyGladtohearthatmyvideoshelpedyou.HopetocreatemoreofthemandmakeDjangomoreaccessible.

    1

    Reply

    KylePennell 9monthsagoArunRavindranwhynotputthisonUdemyandchargeforit?(Iworkthere)

    Reply

    MakeEduFree 4monthsago

    KylePennell

    Whydon'tyoueffoffandmakeeducationfree?

    Reply

    zdys ayearagoLoveit.

    2

    Favorite

    Share

    Share

    Share

    Share

    Share

  • Reply

    dbg ayearagothisiscool.thanksforposting.

    1

    Reply

    Adi ayearagowonderful,anydemo?

    2

    Reply

    ArunRavindran ayearagoAuthor AdiNotyet.Shalltrytoputoneupnexttime!

    Reply

    scrummyin ayearagoSorryIhatetobepicky,butitthrewmeofftoseeXubuntuasXUbuntu.ImaybewrongbutIhaveneverseenitthatway.

    Reply

    ArunRavindran ayearagoAuthor scrummyinNoproblem.Ihavefixedit.

    1

    Reply

    PiotrMigdal ayearagoNice,butthetextinstruction(whichIread,asIpreferreadingtowatching)missesafewsteps:

    steelrumor/serrings.pyput'links'and'steelrumors'inINSTALLED_APPS

    steelrumor/urls.pyputlinefromlinks.viewsimportLinkListView

    1

    Reply

    liuzhiyu ayearagoPiotrMigdalyes,Youareright,authormissthesesteps.

    Reply

    liuzhiyu ayearagoPiotrMigdalNameError:name'LinkVoteCountManager'isnotdefined.

    Amimissanotherhiddensteps?

    ArunRavindran ayearagoAuthor PiotrMigdalThanksalotforpointingthisout.Ihaveaddedtheseinmypost.

    Share

    Share

    Share

    Share

    Share

    Share

    Share

    Share

  • Reply

    Reply

    PiotrMigdal ayearagoArunRavindranBTW:ThanksforpostingcodeonGitHub.OtherwiseIwouldn'tfindwhatwaswrongwithmycode.

    Reply

    liuzhiyu ayearagoNameError:name'LinkVoteCountManager'isnotdefined.

    Igotthiswhenirun'./manage.pysyncdb',iknowknowwhy......

    Reply

    ArunRavindran ayearagoAuthor liuzhiyuItwouldbehardtodebugwithoutseeingyourcode.Couldyoucompareyourcodewithmycodeongithub?

    Reply

    liuzhiyu ayearagoArunRavindranthankyou!

    Reply

    zkc ayearagoliuzhiyuYouneedtoputclassLinkVoteCountManagerdefinitionbeforeclassLinkdefinition.

    1

    Reply

    __future__ ayearagoFantasticvideo!Lookingforwardtothefollowup...

    1

    Reply

    matt ayearagoThanksforthisgreatlecture.I'mcurioustoknowwhat'sthecolorschemeyou'reusinginyourshell?

    Thanks

    1

    Reply

    ArunRavindran ayearagoAuthor mattIusethezenandartthemeforEmacs24.

    EDIT:Youmeanttheterminalcolorscheme?IusethedefaultterminalcolorschemefromXubuntu.

    Chrislawlor ayearagoGreattutorialsofar,thankyou!Ipersonallylearnbestbyfollowingthrougha'real'projectlikethis(whichiswhyIloved

    Share

    Share

    Share

    Share

    Share

    Share

    Share

    Share

    Share

  • Reply

    'PracticalDjangoProjects'somuch).

    I'msurprisedyou'renotcapturingthedatetimeintheVotemodel.Iwouldthinkthatinformationwouldbeneededfortherankingalgorithm.

    1

    Reply

    ArunRavindran ayearagoAuthor ChrislawlorIamgladthatyouliketheapproach.Mostrankingalgorithmsdon'tusethevotingtimestamps,probablybecauseitmightinvolvealotofcomputation.ThealgorithmIwouldusewouldbesimplisticbuttypicalofmostsocialsites.

    1

    Reply

    RoaldD ayearagoHey,Ithinkthe>"Thereisnobetterwaytolearnsomethingthantowatchsomeoneelsedoit."

    partsoundslame,becauseobviouslythebestwaytolearntodosomethingistodoit.

    Greatstuff,bytheway.

    Reply

    Josh ayearagoThankyou,beenlookingforsomethinglikethisforawhile!Anactualyprojecttopracticethethingsi'velearnt.Lookingforwardtoworkingthroughthetutorialsandhopingsolearnasmuchaspossible!

    Reply

    CJMac 10monthsagoHi,

    First,thanksforthistutorial.

    correctedmysillyerror.

    Reply

    Vladdy 7monthsagoIrunthefollwongcode:>>>fromlinks.modelsimportLink>>>foriinxrange(100):Vote(link=Link.objects.order_by('?')[0],voter=a).save()andgetthefollowingerror:NameError:name'Vote'isnotdefined

    Share

    Share

    Share

    Share

    Share

    Share

  • Home(/) Feed(http://arunrocks.com/blog/feed/atom.xml) @arocks(http://twitter.com/arocks)

    Reply

    ArunRavindran 7monthsagoAuthor VladdyGoodpoint.Inthefirstline,justaddVoteaswelltobeimported.Shallupdatetheposttoo.

    Reply

    Vladdy 7monthsagoArunRavindranThankyousomuch.

    Reply

    Vladdy 7monthsagoArunRavindran"voter=a"causedmesomeproblems.Isubstituteditwith:

    >>>user=User.objects.all()[0]>>>foriinxrange(100):...Vote(link=Link.objects.order_by('?')[0],voter=user).save()or>>>foriinxrange(100):...Vote(link=Link.objects.order_by('?')[0],voter=User.objects.order_by('?')[0]).save()

    Reply

    8indaas 6monthsagoGreatArun!Thankyouverymuch.HowaboutTDD?CanyoupleasemakeonethatshowsTDDbaseddevelopment?Thankyoumuch

    Reply

    HiAron 4monthsagoYourockarunThanks!!.

    Share

    Share

    Share

    Share

    Share