ArunRocks - Building a Hacker News Clone in Django - Part 2 (User Profiles and Registrations)
Transcript of ArunRocks - Building a Hacker News Clone in Django - Part 2 (User Profiles and Registrations)
-
Building a Hacker News clone in Django - Part 2(User Profiles and Registrations)(http://arunrocks.com/building-a-hacker-news-clone-in-django-part-2/)
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/)
It has been more than a week since the first part of this tutorialseries(/building-a-hacker-news-clone-in-django-part-1/) was posted and Ivebeen getting positive feedback from several channels. Ironically, it wasextremely popular on Hacker News(https://news.ycombinator.com/item?id=5784689). It was even translated intoChinese(http://www.oschina.net/translate/building-a-hacker-news-clone-in-django-part-1).
To be sure, the objective was not to create a full featured clone of anywebsite. The real objective is to learn Django using a medium-sized projectthat utilises it to the fullest. Many tutorials fall short of bringing togethervarious parts of Django. Compared to a microframework like Flask (which isalso great, btw), Django comes with a lot of batteries included. If you areshort on time, this makes it ideal for completing an ambitious projectlike this.
This tutorial would show you how to implement social features likesupporting user registration and profile pages. We will leverage Djangosclass based views(https://docs.djangoproject.com/en/dev/topics/class-based-views/) for buildingCRUD(http://en.wikipedia.org/wiki/Create,_read,_update_and_delete)functionality. There is a lot of ground to be covered this time.
As before, there is a text description of the steps if you do not prefer to watchthe entire video. There is also a goodies pack(https://github.com/arocks/sr-goodies/archive/master.zip) with templates and other assets included, whichwould be required if you are following this tutorial.
This video would be a continuation of the previous video(/building-a-hacker-news-clone-in-django-part-1/) and I recommend watching it. Click on theimage below to watch the screencast or scroll down to read the steps.
(http://www.youtube.com/watch?v=NeYKGTSFF6I&hd=1)
Enjoyed 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 websites
BLOG(/ ARCH IVES / )ABOUT (H TTP :/ / ARUNROCKS .COM / ABOUT/ )
A RU N RO CKS ( / )
Arun Ravindran
-
are built andgraduallytacklesadvancedtopics liketesting,security,databasemigrationsand debugging.
Step-by-
step Instructions
Here is the text version of the video for people who prefer to read. In part 1,we showed you how to create a private beta-like site to publish rumors aboutMan of Steel(http://www.imdb.com/title/tt0770828/).
The outline of Part 2 of the screencast is:
Better branding and templatesCustom login/logoutSociopath to actually social - django-registrationsSimple registrationUser Profiles
Open the goodies pack
So far, the appearance of the website looks a bit bland. Lets use some assetswhich are pre-designed for the tutorial.
1. Download sr-goodies-master.zip(https://github.com/arocks/sr-goodies/archive/master.zip) to any convenient location. On Linux, youcan use the following commands to extract it to the /tmp directory.
cd /tmpwget https://github.com/arocks/sr-goodies/archive/master.zipunzip master.zip
Explore the extracted files in /tmp/sr-goodies-master
2. Copy the entire static directory from the extracted files tosteelrumors/steelrumors. Also, overwrite the extracted sr-goodies-master/templates/base.html template intosteelrumors/steelrumors/templates/
-
cp -R /tmp/sr-goodies-master/static ~/proj/steelrumors/steelrumors/cp /tmp/sr-goodies-master/templates/base.html ~/proj/steelrumors/steelrumors/templates/
Custom Login page
1. Add to steelrumors/urls.py:
url(r'^login/$', 'django.contrib.auth.views.login', { 'template_name': 'login.html'}, name="login"),url(r'^logout/$', 'django.contrib.auth.views.logout_then_login', name="logout"),
2. Add the login/logout URL locations to steelrumors/settings.py:
from django.core.urlresolvers import reverse_lazy
LOGIN_URL=reverse_lazy('login')LOGIN_REDIRECT_URL = reverse_lazy('home')LOGOUT_URL=reverse_lazy('logout')
3. Now copy login.html from the goodies pack to the templates directory:
cp /tmp/sr-goodies-master/templates/login.html ~/proj/steelrumors/steelrumors/templates/
Refresh your browser to view the newly styled pages.
Using django-registrations
We will be using the simple backend(https://django-registration.readthedocs.org/en/latest/simple-backend.html) of django-registrations(https://django-registration.readthedocs.org/en/latest/) since it iseasy to use and understand.
1. Currently, the version of django registration on the the PythonPackage Index(https://pypi.python.org/pypi/django-registration)doesnt work well with Django 1.5. So we will use my forked versionusing pip:
pip install git+git://github.com/arocks/django-registration-1.5.git
Or if you dont have git installed, use:
pip install https://github.com/arocks/django-registration-1.5/tarball/master
2. Edit settings.py to add registration app to the end of INSTALLED_APPS
'registration',)
3. Run syncdb to create the registration models:
./manage.py syncdb
-
4. We need to use the registration form template from goodies pack.Since, this is for the registration app we need to create a registrationdirectory under templates:
mkdir ~/proj/steelrumors/steelrumors/templates/registration/cp /tmp/sr-goodies-master/templates/registration/registration_form.html ~/proj/steelrumors/steelrumors/templates/registration/
5. Add to urls.py:
url(r'^accounts/', include('registration.backends.simple.urls')),
Visithttp://127.0.0.1:8000/accounts/register/(http://127.0.0.1:8000/accounts/register/)and create a new user. This will throw a Page not found error after auser is created.
Create a users profile page
1. Add UserProfile class and its signals to models.py:
class UserProfile(models.Model): user = models.OneToOneField(User, unique=True) bio = models.TextField(null=True)
def __unicode__(self): return "%s's profile" % self.user
def create_profile(sender, instance, created, **kwargs): if created: profile, created = UserProfile.objects.get_or_create(user=instance)
# Signal while saving userfrom django.db.models.signals import post_savepost_save.connect(create_profile, sender=User)
2. Run syncdb again to create the user profile model:
./manage.py syncdb
3. Add these to admin.py of links app to replace/extend the default adminfor User:
-
from django.contrib.auth.admin import UserAdminfrom django.contrib.auth import get_user_model...class UserProfileInline(admin.StackedInline): model = UserProfile can_delete = False
class UserProfileAdmin(UserAdmin): inlines=(UserProfileInline, )
admin.site.unregister(get_user_model())admin.site.register(get_user_model(), UserProfileAdmin)
Visit http://127.0.0.1:8000/admin/(http://127.0.0.1:8000/admin/) andopen any users details. The bio field should appear in the bottom.
4. Add to views.py of links apps:
from django.views.generic import ListView, DetailViewfrom django.contrib.auth import get_user_modelfrom .models import UserProfile....class UserProfileDetailView(DetailView): model = get_user_model() slug_field = "username" template_name = "user_detail.html"
def get_object(self, queryset=None): user = super(UserProfileDetailView, self).get_object(queryset) UserProfile.objects.get_or_create(user=user) return user
5. Copy user_detail.html from goodies to steelrumors/templates/:
cp /tmp/sr-goodies-master/templates/user_detail.html \ ~/proj/steelrumors/steelrumors/templates/
6. Lets add the urls which failed last time when we tried to create a user.Add to urls.py:
from links.views import UserProfileDetailView...url(r'^users/(?P\w+)/$', UserProfileDetailView.as_view(), name="profile"),
Now try to create a user and it should work. You should also see theprofile page for the newly created user, as well as other users.
7. You probably dont want to enter these links by hand each time. Solets edit base.html by adding the lines with a plus sign + (omitting theplus sign) below:
-
{% if user.is_authenticated %} Logout | + {{ user.username }} {% else %} + Register |
Refresh the browser to see the changes.
Edit your profile details
1. Add UserProfileEditView class to views.py in links app:
from django.views.generic.edit import UpdateViewfrom .models import UserProfilefrom .forms import UserProfileFormfrom django.core.urlresolvers import reverse
class UserProfileEditView(UpdateView): model = UserProfile form_class = UserProfileForm template_name = "edit_profile.html"
def get_object(self, queryset=None): return UserProfile.objects.get_or_create(user=self.request.user)[0]
def get_success_url(self): return reverse("profile", kwargs={'slug': self.request.user})
2. Create links/forms.py:
from django import formsfrom .models import UserProfile
class UserProfileForm(forms.ModelForm): class Meta: model = UserProfile exclude = ("user")
3. Add the profile edit view to urls.py. Protect it with an auth decorator toprevent unlogged users from seeing this view.
from django.contrib.auth.decorators import login_required as authfrom links.views import UserProfileEditView...url(r'^edit_profile/$', auth(UserProfileEditView.as_view()), name="edit_profile"),
4. Copy edit_profile.html from goodies to steelrumors/templates/:
cp /tmp/sr-goodies-master/templates/edit_profile.html \ ~/proj/steelrumors/steelrumors
-
5. Add the following lines to templates/user_detail before the final endblock:
{% if object.username == user.username %}Edit my profile{% endif %}
Now, visit your profile page and try to edit it.
Easter Egg Fun
Add the following lines to user_detail.html before the endblock line:
{% if "zodcat" in object.userprofile.bio %}
html { background: #EEE url("/static/img/zod.jpg");}
{% endif %}
Now mention zodcat to your bio. You have your easter egg!
Final Comments
We have a much better looking site at the end of this tutorial. While anyonecould register to the site, they will not be part of the staff. Hence, you cannotsubmit links through the admin interface. This will be addressed in thenext part.
That concludes Part 2. Follow me on Twitter at@arocks(http://twitter.com/arocks/) to get updates about upcoming parts.
Resources
Full Source(https://github.com/arocks/steel-rumors/tree/episode2)on GithubGoodies pack(https://github.com/arocks/sr-goodies/archive/master.zip) on Github
-
Building a Hacker News clone inDjango - Part 3 (Commentsand CRUD)(http://arunrocks.com/building-a-hacker-news-clone-in-django-part-3/)
Building a Hacker News clone inDjango - Part 1
(http://arunrocks.com/building-a-hacker-news-clone-in-django-part-1/)
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: Thu 06 June 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)
Share on: Twitter(http://twitter.com/share?url=http://arunrocks.com/building-a-hacker-news-clone-in-django-part-2/),Facebook(http://www.facebook.com/sharer.php?u=http://arunrocks.com/building-a-hacker-news-clone-in-django-part-2/),Google+(https://plus.google.com/share?url=http://arunrocks.com/building-a-hacker-news-clone-in-django-part-2/)
Comments
8Comments ArunRocks Login
SortbyOldest Share Favorite
Don'tmissanyfutureposts!
Subscribetoourmailinglist
emailaddress
Subscribe
-
Jointhediscussion
Reply
tony ayearagoThankslovingthistutorial.Lookingforwardtoseehowyouimplementthefrontendforvoting.
1
Reply
jackson 10monthsagoIwasalsogettinganintegrityerrorwhenIaddedanewuseratstep6ofcreatingauser'sprofilepageabove.
Icommentedoutthefollowinglinesinmodels.pyandIcouldcreateusers:
#fromdjango.db.models.signalsimportpost_save
#post_save.connect(create_profile,sender=User)
Reply
jackson 10monthsagoUnderedityourprofilestep3,Ihadtoadd'UserProfileEditView'totheendofthisline:
fromlinks.viewsimportLinkListView,UserProfileDetailView,UserProfileEditView
Reply
CJMac 9monthsago
seemore
Hi,I'mrunningintothiserrorandhaven'tbeenabletosolveityet.Ioriginallyhadtofightwithafewfilesformixingtabsandspaces.NowthatIhavegotridofthaterror,Inowgetthiserror,ifanyonecouldpointmeintherightdirectionthatwouldbegreat.
"
Nomodulenamedforms
RequestMethod:GET
RequestURL:http://127.0.0.1:8000/
DjangoVersion:1.5.2
ExceptionType:ImportError
Share
Share
Share
Share
-
Home(/) Feed(http://arunrocks.com/blog/feed/atom.xml) @arocks(http://twitter.com/arocks)
MarsRoverinPythonandHaskell3commentsayearago
AkkulThanksfordroppingby!IhavemovedtheL&Rorientationmappingbeforewhile(thatwasntsupposedtobeinthe
RealtimeApplicationsandwillDjangoadapttoit?21comments7monthsago
HAHAHAHAHAHAHAHHAHAHAAHHAHAHAHLastjobweusedMeteor.js,wereadthebook,andwentouttobuildthe
DecodingGooglesFirstTweetinPython1commentayearago
UnderstandingTestDrivenDevelopmentwithDjango5comments3monthsago
ALSOONARUNROCKS
Reply
Reply
ChrysCantonaOgwara 8monthsagohowdoiputprofilepictures
Reply
ArunRavindran 8monthsago
Author ChrysCantonaOgwara
Ithinkyoucancheckdjangogravatar2forthis.
Reply
muck 5monthsagothanksforthetutorial!FYI:i'musingdjango1.6.1andIwasgettinganimportError'nomodulenamedefaultsfound'whenItriedtocompletetheUsingDjangoRegistrationstep.So,ingoodies/registration/auth_urls.pyandregistration/backends/simple/urls.pyIchanged"fromdjango.conf.urls.defaultsimport*"to"fromdjango.conf.urlsimportpatterns,url,include"andthisworked.Apparently,fromdjango.conf.urls.defaultsimport*isnolongerinuseondjango1.6
Reply
ArunRavindran 5monthsagoAuthor muckThanksmuckforhighlightingthisproblemandprovidingasolution.IshallupdatetheregistrationappsothatitworksfineinDjango1.6.
WHAT'STHIS?
Share
Share
Share
Share
Share