finally{}

all will be well finally

Archive for April, 2008

Wayanad

with one comment

Kerala is a popular tourist destination in south India. With pleasant climate and equally pleasant people, it is rightly named as ‘god’s own country’.

Wayanad is one such popular destination on the north-east of the state. Being part of Western Ghats, it boasts of excellent natural beauty – wild life sanctuaries, mountain ranges, islands and lakes.

Three days are not sufficient enough to enjoy all of Wayanad; but unfortunately that was all the time that we had. We planned to utilize the best of these three days – we had detailed plans of what to see on each day.

imageWe started at about 6 am. from Bangalore in Toyota Qualis. We traveled via Mandya and reached Rain Country Resorts at about 1 pm., ready for lunch. It was an indicator of what we were going to have in the coming days – it was an excellent lunch.

After lunch, we left to Pookot Lake. We took a boat ride and then strolled along the lake for sometime.

Later in the day, at the resort, we were informed that a bandh was organized the next day to protest against the recent fuel hike. We didn’t like it; but what is a travel plan, if it doesn’t change during its course?

Though all of us took a book with us, I didn’t want to spend a whole day sitting in the resort. I discussed with the resort staff for options. One of them offered to be a guide to walk us through the woods to the near-by peak. My brother-in-law and I gladly agreed.

I was excited at change of plan. Walking through woods was not in our initial plan. We had planned to hop from one tourist spot to the other. But this sudden change will give us an opportunity to spend much more time with the nature.

I was excited for another reason too – I was reading Bill Bryson’s adventurous walk through the Appalachian Trail’ in his book ‘A Walk in the woods‘.  Obviously I was thrilled to take a walk through the woods; of course my brother-in-law is no match for Katz (Bryson’s partner in the walk), but he is closer.

We left after breakfast. The initial climb was a steep one and tiring. While BIL (brother-in-law) and I were panting and falling behind (much like Katz), the guide went on walking as if it was anything normal. I was afraid that our hike will end much before it started! But we survived.

The woods were wild and unspoiled. It was a fantastic feeling to be in the woods listening to the birds chirp and to the rustling sound of dry leaves on the ground. The rest of the walk was not so much steep as the initial one and we were glad about it.

The guide warned us that there were leeches along the route and he took a bottle of salt water in case it was needed. We didn’t use it though.

The final piece was a steep climb on the hill. While the guide climbed up without much effort, it took us a lot of sweat. But when we stood on top of the hill, we felt such an elation – not just because we made it to the top of the hill, but the scenery was splendid. We were on a hill surrounded on all directions by mountains with layers of natural beauty. Having done a basic degree in geology, BIL went about giving me information of the rocks that were surrounding us. Though it was mid noon with sun scorching, we stayed back as long as we could.

We did have a concern that we will be bored for the rest of the day. But we were wrong. As my sister was flying frequently and all of us were caught up in the pace of our work, we didn’t have any family time for few months. So this gave us a chance to sit down as a family and talk. We talked – talked about our childhood; dad’s and mom’s childhood days; our growing up; how life has changed and all else. We didn’t realize how fast time went by until one of the staff came in to call us for dinner. We resumed the family chit-chat after dinner too. All of us felt pretty good about the day.

Next day we left to Tholpatty wild life sanctuary. We were the first ones to take the safari and we expected a thrilling one; but we didn’t see any animals on the way. It was a disappointing one.

Immediately after breakfast, we went to Kuruva island, an uninhibited group of small islands. We were in the absolute tranquil with the nature. Having developed a liking for un-spoilt nature, I was enjoying each moment of the walk through the tall trees.

Kuruva island is not just a long stretch of tall trees; but it is made up of many rivulets, if I remember there are around 64 of them. Crossing each of them was dangerous – we had to cross on rocky bed as the stream flows through them. In some places water was knee deep. We were debating if we need to return without taking a risk on these rivulets, as my mom and dad were with us. But my mother surprised us saying, let us do it boys! We carefully crossed about 9 rivulets; in each my mother surprising us with her strength and stamina.

Every good thing comes to an end and so was this trip. But the trek through the woods, Crossing of rivulets with my parents and the quality time we had with each other will make us to remember our trip to Wayanad stay in our mind for a long time to come.

Enjoy some of the photos here. More photos in Flickr.

biker

Group of bikers followed us.

 abandoned boat

In Pookot Lake

 motherly care

Cute, isn’t it?

 a natural pool

Natural Swimming Pool in the Resort

in rain country resort

Shot during the Camp-fire in the Resort

 deer poached?

Deer skull found on our trek

  wild mushroom

Wild Mushroom. There were many more wild flowers

 scenic beauty

From the top of the hill

  title="on the way down" href="http://www.flickr.com/photos/22003141@N00/2278854855/" target="_blank">on the way down

BIL and the guide walking down from the hill

 ubiquitous vehicle

Jeep is an economical vehicle owing to the hilly surroundings

Written by Joseph Jude

April 7th, 2008 at 12:06 pm

Posted in Travel

Tagged with

A simple ‘Twitter’ clone in Django

with 9 comments

It started when my boss challenged me to write a twitter/orkut for our department. Having already decided to learn web development with Django (read about it here), I jumped into action over the weekend.

As it was my first application and it was for internal use, I limited myself to the below feature list:

  • multi-user system with login/logoff
  • micro-blog (<= 150 characters per blog)
  • groups (something similar to threads; a provision for related conversation)
  • Active Directory authentication (so there was no need for user registration)

I decided to take up AD authentication later. I understood from Django forum that it was possible to plug-in that feature.

I looked for a ‘cool’ name for the application. Being a micro-blog, I wanted a simple, single syllable word that represents word or conversation or talk. I settled with ‘SOL’ – it is a Tamil word representing what I expected.

Typical Django applications consists of models (classes), views (logic) and templates (presentation). URLs bind all of these components together.

Models

It seemed logical to start with models – one for SOLs and another one for group. There is nothing complex here; pretty simple models. I also built form models for each of these. So here is models.py:

class group(models.Model):
	desc = models.TextField(max_length=25)

	def __unicode__(self):
		return unicode(self.id)

	def get_absolute_url(self):
		return "/g/%s" % unicode(self.id)

	class Admin:
		list_display = ('id','desc')
	class Meta:
		ordering = ['-id']

class sol(models.Model):
	body = models.TextField(max_length=150)
	author = models.ForeignKey(auth.User)
	date = models.DateTimeField('Date')
	group = models.ForeignKey(group)

	def __unicode__(self):
		return unicode(self.id)

	def get_absolute_url(self):
		return "/sol/%s/" % unicode(self.id)

	def get_author_url(self):
		return "/u/%s/p/0" % (self.author)

	class Admin:
		list_display = ('author', 'body', 'date')
		date_hierarchy = 'date'
	class Meta:
		ordering = ['-date']

class solForm(ModelForm):

	body = forms.CharField(max_length=150, widget=forms.Textarea(attrs={'rows':2, 'cols': 40}),label= 'Your Sol:')
	author = forms.CharField(widget=forms.HiddenInput)
	date = forms.CharField(widget=forms.HiddenInput)
	group = forms.CharField(widget=forms.HiddenInput)

	class Meta:
		model = sol

class grpForm(ModelForm):

	desc = forms.CharField(max_length=25, label= 'Create Your Group:')

	class Meta:
		model = group

Views

There are only three functions (or views):

  • create a group
  • create a SOL
  • display list of SOLs (for groups, users, and all)

It is so simple to display list of SOLs (for that matter any objects). Django provides generic views for that. However I used my own views. All that is needed is the template name and a dictionary of values to be passed to the template.

Object (user or group or a default home page), object id, template name, and page number are passed to the view function; each variable also have default values. Using ObjectPaginator, these objects are paginated. Here is my views.py:

#for pagination: http://www.slideshare.net/simon/the-django-web-application-framework/#

#generic view function for homepage (solhome), userhome and group home
#object is one of the param; object="u" -> user; g->group; s->sol, which is default home page
#object id : for u & g the respective ids; for sol nothing; defaults to sol(0)
#pagenum : for pagination; default is 0 otherwise the pagenumber to be displayed in the input

def home(request, model="s",objectId="0",page_num=0, template='home.html'):
	paginate_by = settings.PAGINATE_BY
	#what we get as parameter is always a string
	page_num = int(page_num)
	if model == 'u': #for user we need to filter for the user
		info_list = ObjectPaginator(sol.objects.all().filter(author__username=objectId),paginate_by)
	elif model== 's': #for sol; home page
		info_list = ObjectPaginator(sol.objects.all(),paginate_by)
	elif model =='g': #for group
		if objectId == '0':
			info_list = ObjectPaginator(group.objects.all(),paginate_by)
		else:
			info_list = ObjectPaginator(sol.objects.all().filter(group=group.objects.get(id=objectId)),paginate_by)

	has_previous = info_list.has_previous_page(page_num)
	has_next = info_list.has_next_page(page_num)

	info_dict = {
		'query_list' : info_list.get_page(page_num),
		'has_previous' : has_previous,
		'previous_page' : page_num - 1,
		'has_next' : has_next,
		'next_page' : page_num + 1,
		'site_name' : 'sol',
		'user' : request.user,
	}

	if model == 's':
		form = solForm()
		#this is how you append to a dict
		info_dict['solForm'] = form

	if model == 'u':
		#this is how you append to a dict
		info_dict['u_id'] = objectId
		info_dict['nickname'] = userprofile.objects.get(user__username=objectId).nickname

	if model == 'g':
		info_dict['grpForm'] = grpForm()
		if objectId == '0':
			info_dict['solForm'] = solForm()
		else:
			info_dict['solForm'] = solForm(initial={'group': group.objects.get(id=objectId)})
			info_dict['grpName'] = group.objects.get(id=objectId).desc

	return render_to_response(template, info_dict)

def logout(request):
		auth.logout(request)
		return HttpResponseRedirect('/')

def createsol(request):
	#if there is nothing in the text field, do nothing
	if request.POST['body'] == "":
		return HttpResponseRedirect('/')

	newsol = sol()
	newsol.author = request.user
	newsol.date = datetime.datetime.today()
	newsol.body = request.POST['body']
	if request.POST['group'] <> '':
		newsol.group = group.objects.get(id=request.POST['group'])
	newsol.save()
	return HttpResponseRedirect('/')

def creategroup(request):
	if request.POST['desc'] == "":
		return HttpResponseRedirect('/groups/')

	newgrp = group()
	newgrp.desc = request.POST['desc']
	newgrp.save()
	return HttpResponseRedirect('/groups/')

def help(request):
	return render_to_response('help.html')

SOL URLs:

URLs are the routing engines connecting both models and views. The URLs for SOL are:

  • homepage (of sol) – listing all SOLs
  • user’s homepage – SOLs of a particular user
  • group homepage – SOLs belonging to a particular group
  • creation of new sol
  • creation of new group

With support for pagination and admin, url.py is like:

urlpatterns = patterns('cool.sol.views',
     #default page number is 0;
     #url like: http://sol.com/
     (r'^$', 'home'),

     #homepage for sol with pagination enabled
     #url like: http://sol.com/p/0
     (r'^p/(?P<page_num>d+)/$', 'home',{'template':'home.html', 'model':'s'}),

     #user homepage - employees with employee ids as numbers;
     #url like: http://sol.com/u/1029/p/0
     (r'^u/(?P<objectId>d+)/p/(?P<page_num>d+)/$', 'home',{'template':'user_home.html', 'model':'u'}),

     #groups homepage
     #url like: http://sol.com/groups/ or http://sol.com/groups/p/0 
     (r'^groups/$', 'home',{'template':'groups_home.html', 'model':'g'}),
     (r'^groups/p/(?P<page_num>d+)/$', 'home',{'template':'groups_home.html', 'model':'g'}),

     #homepage for a particular group
     #url like: http://sol.com/g/100/p/0
     (r'^g/(?P<objectId>d+)/$', 'home',{'template':'group_home.html', 'model':'g'}),
     (r'^g/(?P<objectId>d+)/p/(?P<page_num>d+)/$', 'home',{'template':'group_home.html', 'model':'g'}),

     #logoff
     (r'^logout/$', 'logout'),

     #create a sol; called by form action
     (r'^createsol/$', 'createsol'),

     #create a sol; called by form action
     (r'^creategroup/$', 'creategroup'),

     #help
     (r'^help/$', 'help'),
)

#these are derived from admin
urlpatterns += patterns('',
        #login page
        (r'^login/$', 'django.contrib.auth.views.login', {'template_name': 'login.html'}),

        #admin page
        (r'^admin/', include('django.contrib.admin.urls')),

)

Templates

Only thing left are templates. Django templates can be inherited. Hence first you define the basic template with placeholder blocks – for html headers, page headers like navigation menus and footer – then build upon that template until the final template. It is okay to fill-in only few blocks.

Here is a snippet from base.html.

            <div id="content">
                <div id="left">
                    {% block content %}
                        {% block newgroup %} {% endblock %}
                        {% block newsol %} {% endblock %}
                        {% block entries%} {% endblock %}
                        {% block paginate %} {% endblock %}
                    {% endblock %}
                </div>
                <div id="footer">
                    {% block footer %}{% endblock %}
                </div>
            </div>

Now in home.html, I derive from base.html and define what is needed:

{# Template for home page for sol; it lists all the sols #}
{% extends "base.html" %}

{% block newsol %}
{% if user.is_authenticated %}
<div class="form">
	<form action="/createsol/" method="post" enctype="multipart/form-data">
	  <table>
		{{ solForm }}
	  </table>
	  <input type="submit" value="Update" />
	</form>
</div>
{% endif %}
{% endblock newsol%}

Once you get these concepts (model, view, template and urls), it is extremely easy to put together a website.

The complete code can be downloaded from google code page.

(Note: There might be a better way to do all of this. As I read more and write more of Django, I hope to figure them out. However, if there is a better way, there is no harm in leaving a comment about the same.)

Written by Joseph Jude

April 5th, 2008 at 11:26 pm

Posted in Programming

Tagged with