Thursday, January 29, 2015

My new homesite and blog

Hey all.

I have make my new homesite - http://ankushchadda.in. This is hosted as Github pages.

Next I have also made a blog at http://blog.ankushchadda.in.

Both of these themes are taken from startbootstrap.com. Awesome free templates!!..

I will be publishing my future blogs there now. Will also move my posts to the new blog, but thats a work ill do gradually.

Thanks,
Ankush

Monday, January 12, 2015

PHP application with Mysql database to a Django app with Postgres Database

Recently I had a chance to work on a project, where a PHP app had to be converted to a Django one.

The work seemed trivial, but it brought a few difficult technicalities. It had a Mysql DB, with few tables. Overall, I had to  -


  • Convert them into Django models
  • Convert the app into Django
  • Setup the app on Heroku using Postgres

  1. Converting the models to Django is easy. Django provides an inspectdb command. It looks at the current model structures, inspects it and provides django model accordingly.
  2. This is a nice feature. It gave me a push forward to begin the app development. However, this feature lacked some points that I would like to point out - 
    1. In Mysql, we have a set type . This is basically similar to choices in Django models. I had to manually do that. 
    2. The foreign key constraint is set to id by default. The command could check this and set the field in model declaration using to_field parameter.
    3. The DB views had to created manually. 
  3. For changing Mysql Data to Heroku, https://devcenter.heroku.com/articles/heroku-mysql is a good resource.
As always, heroku has to be provided with a S3 access to uploading of static and media files. But thats a different matter.

Thursday, June 26, 2014

Musings on Openlibrary and my first get-to-know with Solr-1.4.1

OpenLibrary is a ambitious project which runs at openlibrary.org. As the name says, its a open(sourced) project. The code lies on github at https://github.com/internetarchive/openlibrary/.

Now the developers working on the project are extremely talented. The number of technologies and the way they have implemented them is awesome. Users can search a book( ofcourse ) , read it online ( using the beautiful Bookreader client side app) and also borrow a book ( havent used this feature ).

One of my clients , wanted me to implement the OpenLibrary project into their website. They already had some part working. BookReader was working , but the feature of searching inside a book , wasnt.

Openlibrary uses solr as its search engine. It is the most powerful search backend , as its said. Lack of previous developer made a big issue and moreover there was not much documentation present for my task.

I realised from the scripts, that solr 1.4.1 is to be used.  After reading more code, from BookReader I realised, that when we searched , it made a call to solr similar to -

<server>:8984/solr/inside/select?rows=1&wt=json&fl=ia,body_length,page_count&hl=true&hl.fl=body&hl.fragsize=0&hl.maxAnalyzedChars=-1&hl.usePhraseHighlighter=true&hl.simple.pre={{{&hl.simple.post=}}}&q.op=AND&q=ia%3A<id_of_opened_book>

It makes a similar second call with q as ia%3A<id_of_opened_book>%20AND%<searched_query>

In this second call, we get the highlighted results. Now these results are arranged in json. The next task is to locate and highlight the queried words on the ebook . For this we have a xml file of an OCR. In this case, we used abby reader. Queried words are located using the ocr xml file and highlighted on ebook.

Now the only thing remains is to get solr working for full text search. For this Openlibrary, makes a call to a php file called,  abby_to_text.php, which basically reads the OCR file and extracts paragraphs from it. This gets saved into solr.

To save into solr, we make a xml with fields of atleast the required ones, as , mentioned in schema.xml.
The schema I am using is at - https://github.com/internetarchive/openlibrary/blob/master/conf/solr-biblio/inside/conf/schema.xml.
The required fields are -
 <field name="ia" type="string" required="true" />
   <field name="body" type="textgen" required="true" compressed="true" />
   <field name="body_length" type="int" required="true" />
   <field name="page_count" type="int" indexed="true" required="true" />
Here ia is the book id, and body is the text of the book.
Also, you need to commit the results so that you can immediately see in solr admin.

The imp thing here is , that this schema is of inside core. This was also new thing.
More problems came because of solr old version. 1.4.1 is more than 4 years old.

But anyways. It was a good learning.




COnverting MarkDown to ReST format

Generally we make Readme on Github in markdown, but while making ReadtheDocs or Pypi pachage , we need rst docs.

For this comes in handy Pandoc .

Just run the command

pandoc --from=markdown --to=rst --output=install.rst install.md

and rst is ready. Awesome!!.

Friday, April 25, 2014

Continuous Integration and Deployment using Bamboo and AWS Elastic Beanstalk

Walk-through of setting up Bamboo as CI and CD  

Bamboo is a popular Atlassion product . Lets go setup bamboo and discuss what steps did I do.
  • Install Bamboo on an EC2 instance
    • Configure to run on Port 80 instead on its default.
    • Make sure system has enough memory, I am using a m1.small instance. 
    • Bamboo has a startup script, use that , and make sure the permission thing.:P
  • For CI - 
    • Checkout the code
      • Used post push hook to automate the build plan on bamboo
    • Install dependencies
      • Remember to clean cache and remove the node_modules before installing
    • Run tests
      • Used Bamboo-mocha plugin for that. Ample doc is provided for that
    • Thats it !!
  • For CD -
    • Setup the deployment Server -
      • We are using Amazon Beanstalk,, our app being a Node.JS one.
    • The deployment process is tricky. Manually we have to initialize the repo and feed in a lot of details. But to do it automatically 
      • Initialize the repository with the AWSDevTools-RepositorySetup.sh script. It will add git aliases . We will now have git aws.push command
      • The deploy script searches for a file named aws_credentials_file, in the Home folder of the user in .elasticbeanstalk dir. So one task is to copy a file in home folder during each deployment.
    • Rest is simple.

This blog also has a lot of important details that helped me - http://blog.pedago.com/2014/02/18/build-and-deploy-with-grunt-bamboo-and-elastic-beanstalk/

Next step to include Code Coverage .. Will mention it in next blog post.

Wednesday, January 29, 2014

Python? , But why Python?

Well I am using python since last 3 years . It has been my main development language, other than javascript.

Often, someone comes around and asks , Why Python? I am usually left with my personal programming tasks where python comes in very handy when compared to other languages I have encountered, like  PHP or Java.

Well , here is a post for answering this question exactly. Check it here.

Here are the points -

  • Efficient - Has generators 
  • Fast
  • Broad use
  • Not just a language, has a number of implementations
  • Easy

Cheers!!

Yet another post on Redis

While working for a project , we used Redis as queue, using python-rq.  Running a redis-cli , I used the following commands -


  • keys *
  • type <key name>
  • and then according to the type , hash,list I would query the data
Some things were quite easy to understand
  • rq:workers
  • rq:queue:failed
  • rq:queue:default
  • and a success one as well
But apart from these, there were several entries - with name rq:job:<job_id>. After much reading, I found the internal working at http://python-rq.org/contrib/.

It says whenever a function call gets enqueued - 
  • Pushes the job's ids into queue , in my case the default
  • adds a hash objects of the job instance
So, when dequeue happens - 
  • Pops jobid from queue
  • Fetches Job data 
  • Executes the function and saves result has a hash key if success
  • else saves in failed queue with stack trace
All of this is given on Python-rq site.

There are two kinds of error I saw -
  • RuntimeError: maximum recursion depth exceeded while calling a Python object - This happened at queue.py of python-rq module, where I think, it was caused when control crossed max recursive limit, when it didnt find the jobs hashes, as discussed above in dequeue
  • Socket closed on remote end - The server closes client connection after 300s, in my case I didnt want to do them, so. let it be on forever by changing in /etc/redis/redis.conf , timeout value to 0
Go Redis!!

Sunday, January 19, 2014

Python Decorators - The correct way to do it

Was going through Graham Dumpleton's blog post - how you implemented your python decorator is wrong. Simple points that were discussed were -


  • Decorators can be functions as well as Classes.
    As a class -  

    class function_wrapper(object):
        def __init__(self, wrapped):
            self.wrapped = wrapped
        def __call__(self, *args, **kwargs):
            return self.wrapped(*args, **kwargs) 
    @function_wrapper
    def function():
        pass 

    As a function 

    def function_wrapper(wrapped):
        def _wrapper(*args, **kwargs):
            return wrapped(*args, **kwargs)
        return _wrapper 
    @function_wrapper
    def function():
        pass 

  • Use the functools.wraps decorator , it only preserves original functions __name__ and __class__
    In functions 

    import functools 
    def function_wrapper(wrapped):
        @functools.wraps(wrapped)
        def _wrapper(*args, **kwargs):
            return wrapped(*args, **kwargs)
        return _wrapper 
    @function_wrapper
    def function():
        pass 

    In classes, use the update_wrapper method- 

    import functools 
    class function_wrapper(object):
        def __init__(self, wrapped):
            self.wrapped = wrapped
            functools.update_wrapper(self, wrapped)
        def __call__(self, *args, **kwargs):
            return self.wrapped(*args, **kwargs)
  • Python 2.7 preserves Argument specification ( inspect.getargspec ) only in functional decorators, not in class based ones.
  • Doesnt preserve function source code for inspection ( inspect.getsource ) 
  • Cannot apply decorators on top of other decorators that are implemented as descriptors.

Saturday, January 11, 2014

Failed to attach to key daemon - Error in Shrew Soft VPN

Using Shrew Soft VPN on Ubuntu 12.04, I often face this error

Failed to attach to key daemon 

On some googling I found this post -> Ubuntu Forums

It says that this error is because IKE Daemon isnt running.

sudo iked

Hope this helps.

Friday, December 20, 2013

Solving failed to load canberra-gtk-module error on precise.

I have Ubuntu Precise(12.04) 64 bit.

On openinig sublime, it gave me this error -
(sublime:7247): Gtk-WARNING **: Unable to locate theme engine in module_path: "murrine",
(sublime:7247): Gtk-WARNING **: Unable to locate theme engine in module_path: "murrine",
(sublime:7247): Gtk-WARNING **: Unable to locate theme engine in module_path: "murrine",
Gtk-Message: Failed to load module "canberra-gtk-module"
'import site' failed; use -v for traceback
`menu_proxy_module_load': sublime: undefined symbol: menu_proxy_module_load
(sublime:7247): Gtk-WARNING **: Failed to load type module: (null)


on running strace on sublime ,

I got this output  -

access("/usr/lib/i386-linux-gnu/gtk-2.0/modules/libcanberra-gtk-module.la", F_OK) = -1 ENOENT (No such file or directory)
access("/usr/lib/gtk-2.0/2.10.0/i686-pc-linux-gnu/modules/libcanberra-gtk-module.so", F_OK) = -1 ENOENT (No such file or directory)
access("/usr/lib/gtk-2.0/2.10.0/i686-pc-linux-gnu/modules/libcanberra-gtk-module.la", F_OK) = -1 ENOENT (No such file or directory)
access("/usr/lib/gtk-2.0/2.10.0/modules/libcanberra-gtk-module.so", F_OK) = -1 ENOENT (No such file or directory)
access("/usr/lib/gtk-2.0/2.10.0/modules/libcanberra-gtk-module.la", F_OK) = -1 ENOENT (No such file or directory)
access("/usr/lib/gtk-2.0/i686-pc-linux-gnu/modules/libcanberra-gtk-module.so", F_OK) = -1 ENOENT (No such file or directory)
access("/usr/lib/gtk-2.0/i686-pc-linux-gnu/modules/libcanberra-gtk-module.la", F_OK) = -1 ENOENT (No such file or directory)
access("/usr/lib/gtk-2.0/modules/libcanberra-gtk-module.so", F_OK) = -1 ENOENT (No such file or directory)
access("/usr/lib/gtk-2.0/modules/libcanberra-gtk-module.la", F_OK) = -1 ENOENT (No such file or directory)
stat64("libcanberra-gtk-module.so", {st_mode=S_IFREG|0644, st_size=23072, ...}) = 0
open("/lib/i386-linux-gnu/libcanberra-gtk-module.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/i386-linux-gnu/sse2/libcanberra-gtk-module.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/i386-linux-gnu/libcanberra-gtk-module.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/lib/libcanberra-gtk-module.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/libcanberra-gtk-module.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
write(2, "Gtk-Message: Failed to load modu"..., 57Gtk-Message: Failed to load module "canberra-gtk-module"

 As the error says, it was trying to locate libcanberra-gtk-module.so in a number of locations.

Googling the package name , I saw that the location in which it was trying to find was wrong, in locations where 32bit packages are there.

There was the solution. I was trying to load 32 bit Sublime Text on 64 bit system. Downloading a 64 bit version worked like a charm.



Tuesday, October 1, 2013

Ejabberd Dissection

Working on Ejabbered 2.1.13, in order to understand ejabbered db calls and processes, I followed this presentation  - http://www.slideshare.net/ShaojieYang/ejabberd-installation-configuration-15508995
.
 It showed an easy process to connect Ejabberd to an external database.
Here I would be going a step ahead and saving the DB calls Ejabberd makes, assuming this will be same, when it using its internal Mnesia DB.

When adding a new user(registration)  from web admin - test3@192.168.1.250
----------------------------------------------------------------------------------------------------------
  113 Query select password from users where username='admin'
  112 Query select password from users where username='admin'
  112 Query select password from users where username='test3'

  104 Query insert into users(username, password) values ('test3', 'test3')

Below for count for Offline Messages and  Last Activity shown in admin
-----------------------------------------------------------------------
108 Query select username from users
104 Query select count(*) from spool  where username='admin'
104 Query select seconds, state from last where username='admin'
107 Query select count(*) from spool  where username='admin3'
108 Query select seconds, state from last where username='admin3'

Connecting a user - test2@192.168.1.250
-------------------------------------------------------
109 Query select password from users where username='test2'
113 Query select username, jid, nick, subscription, ask, askmessage, server, subscribe, type from rosterusers where username='test2'
104 Query select name from privacy_default_list where username='test2'
105 Query select username, jid, nick, subscription, ask, askmessage, server, subscribe, type from rosterusers where username='test2'
112 Query select jid, grp from rostergroups where username='test2'
109 Query select password from users where username='test2'
113 Query select name from privacy_default_list where username='test2'
105 Query select name from privacy_list where username='test2'
105 Query select id from privacy_list where username='test2' and name='invisible'
110 Query begin
110 Query select id from privacy_list where username='test2' and name='invisible'
110 Query insert into privacy_list(username, name) values ('test2', 'invisible')
110 Query select id from privacy_list where username='test2' and name='invisible'
110 Query delete from privacy_list_data where id='1'
110 Query insert into privacy_list_data(id, t, value, action, ord, match_all, match_iq, match_message, match_presence_in, match_presence_out ) values ('1', 'n', '', 'd', '1', '0', '0', '0', '0', '1')
110 Query commit
104 Query begin
104 Query select username, xml from spool where username='test2'  order by seq
104 Query delete from spool where username='test2'
104 Query commit
108 Query select username, jid, nick, subscription, ask, askmessage, server, subscribe, type from rosterusers where username='test2'
110 Query select username, jid, nick, subscription, ask, askmessage, server, subscribe, type from rosterusers where username='test2'
113 Query select jid, grp from rostergroups where username='test2'
105 Query select subscription from rosterusers where username='test2' and jid='test2@192.168.1.250'
112 Query select subscription from rosterusers where username='test2' and jid='test2@192.168.1.250'
112 Query select subscription from rosterusers where username='test2' and jid='test2@192.168.1.250'
104 Query select subscription from rosterusers where username='test2' and jid='test2@192.168.1.250'

111 Query select subscription from rosterusers where username='test2' and jid='test2@192.168.1.250'

Adding contact - test1@192.168.1.250 by test4
--------------------------------------------------------------

122 Query begin
122 Query select username, jid, nick, subscription, ask, askmessage, server, subscribe, type from rosterusers where username='test4' and jid='test1@192.168.1.250'
122 Query update rosterusers set username='test4', jid='test1@192.168.1.250', nick='', subscription='N', ask='N', askmessage='', server='N', subscribe='', type='item' where username='test4' and jid='test1@192.168.1.250'
122 Query insert into rosterusers(username, jid, nick, subscription, ask, askmessage, server, subscribe, type) values ('test4', 'test1@192.168.1.250', '', 'N', 'N', '', 'N', '', 'item')
122 Query delete from rostergroups       where username='test4'         and jid='test1@192.168.1.250'
122 Query commit
131 Query begin
131 Query select username, jid, nick, subscription, ask, askmessage, server, subscribe, type from rosterusers where username='test4' and jid='test1@192.168.1.250'
131 Query select grp from rostergroups where username='test4' and jid='test1@192.168.1.250'
131 Query update rosterusers set username='test4', jid='test1@192.168.1.250', nick='', subscription='N', ask='O', askmessage='', server='N', subscribe='', type='item' where username='test4' and jid='test1@192.168.1.250'
131 Query commit
129 Query select name from privacy_default_list where username='test1'
128 Query select password from users where username='test1'
123 Query begin
123 Query select username, jid, nick, subscription, ask, askmessage, server, subscribe, type from rosterusers where username='test1' and jid='test4@192.168.1.250'
123 Query update rosterusers set username='test1', jid='test4@192.168.1.250', nick='', subscription='N', ask='I', askmessage='', server='N', subscribe='', type='item' where username='test1' and jid='test4@192.168.1.250'
123 Query insert into rosterusers(username, jid, nick, subscription, ask, askmessage, server, subscribe, type) values ('test1', 'test4@192.168.1.250', '', 'N', 'I', '', 'N', '', 'item')
123 Query commit

Now asks for permission 

in rosterusers table - subscription field is N (related to pending as others which are already accepted contacts have B) and  ask field is O for test4 and I for test1 (test4 added test1)


Ater accepting
-------------------

122 Query begin
122 Query select username, jid, nick, subscription, ask, askmessage, server, subscribe, type from rosterusers where username='test4' and jid='test1@192.168.1.250'
122 Query update rosterusers set username='test4', jid='test1@192.168.1.250', nick='', subscription='N', ask='N', askmessage='', server='N', subscribe='', type='item' where username='test4' and jid='test1@192.168.1.250'
122 Query insert into rosterusers(username, jid, nick, subscription, ask, askmessage, server, subscribe, type) values ('test4', 'test1@192.168.1.250', '', 'N', 'N', '', 'N', '', 'item')
122 Query delete from rostergroups       where username='test4'         and jid='test1@192.168.1.250'
122 Query commit
131 Query begin
131 Query select username, jid, nick, subscription, ask, askmessage, server, subscribe, type from rosterusers where username='test4' and jid='test1@192.168.1.250'
131 Query select grp from rostergroups where username='test4' and jid='test1@192.168.1.250'
131 Query update rosterusers set username='test4', jid='test1@192.168.1.250', nick='', subscription='N', ask='O', askmessage='', server='N', subscribe='', type='item' where username='test4' and jid='test1@192.168.1.250'
131 Query commit
129 Query select name from privacy_default_list where username='test1'
128 Query select password from users where username='test1'
123 Query begin
123 Query select username, jid, nick, subscription, ask, askmessage, server, subscribe, type from rosterusers where username='test1' and jid='test4@192.168.1.250'
123 Query update rosterusers set username='test1', jid='test4@192.168.1.250', nick='', subscription='N', ask='I', askmessage='', server='N', subscribe='', type='item' where username='test1' and jid='test4@192.168.1.250'
123 Query insert into rosterusers(username, jid, nick, subscription, ask, askmessage, server, subscribe, type) values ('test1', 'test4@192.168.1.250', '', 'N', 'I', '', 'N', '', 'item')
123 Query commit

Memory footprint 
-----------------------

connecting 100 clients to ejabberd - no issue,
there are 9 instances running with around 70mb each.

Used this script to hit to server (Uses XMPPY )
-----------------------------------------

It assumes that we have test users already registered with username test1, test2.. and pass test1 and test2.  (ejabberdctl register command can be used to make such users)

from xmpp import *

clients = []
for i in range(100):
    clients.append(Client('192.168.1.250'))
for cl in clients:
    cl.connect(server=('192.168.1.250',5222))
for i in range(1,101):
    clients[i-1].auth('test%d'%i,'test%d'%i)

while True:
    for cl in clients:
        cl.sendPresence()

        cl.Process(2)



Sum good post
http://metajack.im/2008/08/27/migrating-to-ejabberd-the-gory-details/‎



Wednesday, September 11, 2013

Timezone and Confusion in Django

https://docs.djangoproject.com/en/dev/topics/i18n/timezones/

1) We use USE_TZ = True in our settings. It means, that Django will use Time zone aware datetime objects.
so, instead of doing this,


import datetimecur = datetime.datetime.now() # which doesnt give us tzinfo

we should use this -

import datetimefrom django.utils.timezone import utc
cur = datetime.datetime.now().replace(tzinfo=utc) # Note: This is for timezone aware not for local time

This will remove the warnings we usually see, "Datetimefield received a naive datetime."

2) For converting local time into current time zone,  according to one specified in settings file. We should use this

from django.utils import timezonetimezone.localtime(timezone.now())


Wednesday, September 4, 2013

Using Google Charts to show Data Point Values

Like most of us, in order to quickly use Google Charts Library, I copy pasted a simple code from https://code.google.com/apis/ajax/playground/?type=visualization#line_chart, adjusted to my use.

I wanted a Line Graph, with two data lines,  hours(1-24) on x axis and a number on y axis. This example was easy to customize , and most of my work was done(Please note- Most of it)

Now, I only wanted to show data values in the graph. As you can see, a tooltip pops up, when we hover on data points, I wanted tooltips or data values to show without the hover action.

The only way I could find was here - http://stackoverflow.com/questions/13449467/google-charts-api-always-show-the-data-point-values-in-graph

It says - data.addColumn({type: 'string', role: 'annotation'});


Now this is new, whats data? On going through the docs, I found that I have been using a method arraytoDataTable() [here] .This is a shortcut method to add data to graph. There is a DataTable class which has methods

  • addColumn
  • addRow
  • addRows
See here  

this data in the above code, is the instance of the DataTable class. Now coming back to the same problem, in order to add annotation, we added the columns with role: annotation. Roles can be read here.

So now, I am able to see , the not so beautiful , annotations. 

What could be made better - Examples should be added for showing annotations. Currently there are none.

Tuesday, September 3, 2013

Compiling Ejabbered Module

While working on ejabbered, I came across a case where I had to compile a new module.

On googling and reading around stuff, I went through different posts -



All of these posts were indeed very helpful to start but I faced some errors to compile , even after following the given steps.

My basic mod_hello.erl module,  had 

-module(mod_hello).
-behavior(gen_mod).

-export([
    start/2,
    stop/1
    ]).
start(_Host, _Opt) ->
        ?INFO_MSG("Loading module 'mod_hello' ", []).
stop(_Host) ->
        ok.

Using commands to compile this , 
erlc mod_hello.erl
erlc  -I {erlang_src_dir}/src -pa {erlang_src_dir}/src mod_hello.erl
 But nothing worked. I looked at the compiling commands that Ejabbered src used on compiling its erl modules. It was similiar to mine. Atlast on looking through the code, I found out the missing code..
the include commands.

So now, after addiing
-include("ejabberd.hrl").
-include("jlib.hrl").
Everything worked. Hooray.. 

Monday, August 26, 2013

Json makes tuples to list

While working on json format, came across something interesting.

sample_list  = [(1,2),(3,4)]
print json.dumps(sample_list)  # [[1,2],[3,4]]

As we can see here, json isnt preserving tuples. On searching, I got to know, JSON doesnt understand tuples. These are the basic data types for json(from Wikipedia )

JSON's basic types are:
  • Array (an ordered sequence of values, comma-separated and enclosed in square brackets; the values do not need to be of the same type)
  • Object (an unordered collection of key:value pairs with the ':' character separating the key and the value, comma-separated and enclosed in curly braces; the keys must be strings and should be distinct from each other)
Here are some solutions for the same on stackoverflow.

Cheers..!!

Thursday, August 22, 2013

Lesser known Stress testing Utility - Siege

Siege is a HTTP/HTTPS Stress testing tool.

Here is the man page for it.

Here is short intro from the man page -

Siege is a multi-threaded http load testing and benchmarking utility. It was designed to let web developers measure the performance of their code under duress. It allows one to hit a web server with a configurable number of concurrent simulated users.


A basic command for testing a web app locally is
siege http://localhost:8000/?q=pants -c10 -t10s
c -> number of concurrent users
t -> time for running tests for.


Hope it was useful. 

Sunday, July 14, 2013

Experiment with Heroku, Google Charts, and Django

So, one of the experiments that I just did was quickly making a Django app, deploying it on heroku.

I have uploaded it to Github as well. Here is the link.

The problems that I faced were -

1) the static files handling in heroku -  foreman doesnt work like runserver, and has to be configured as the help says. But in my case, I didnt want to re configure just to serve a small app, so my app is currently serving 3 static files.
2) The structure of the app is such that the root folder had name different than that of the app, registered at heroku. This caused the error no Cedar supported app detected.


These were the two small problems that I faced. reference solutions can be seen in github link.

Monday, June 3, 2013

Submit a form having File input via ajax

Googling the topic of the post would give the link to stackoverflow which suggests . http://jquery.malsup.com/form. However , I missed this plugin , and started researching-

A list of options  -
1) Hidden Iframes -
        Didnt know anything about form submit through Iframes. Eventually found the promising plugin jQuery.AjaxFileUpload from J.Feldstein. But this was helpful in submitting only individual fields, one by one. It uses hidden iframes, where it wraps the field with the form and submits it to iframe using the target attribute. There is some hack that I havent yet understood. (Here).

2) Form-Data/ Xhr2 -  
       This is a clean implementation of HTML5. Easy 2 liners and form is submitted with file inputs. But it was not implemented in every browser, and lesser number of mobile browsers, so ..didnt go ahead with that.
     

Thursday, October 11, 2012

Django-mapistration Posted to Pypi

So, a long awaited task got completed today.

On 2nd Oct, I published my first django app - django-mapistration , on django packages.

Today , I put this app on pypi as well. on this url.

So , a pip install django-mapistration would download the app


Feels AWESOME!!!!! 

Thursday, August 30, 2012

No sound after hibernate in Ubuntu 11.04 - the Natty Narwhal

This problem want there earlier, but came after a update .

To solve it, either restart or

sudo alsa force-reload

This reloads drivers..and viola ..u have sound