Showing posts with label django. Show all posts
Showing posts with label django. Show all posts

Monday, October 14, 2013

Automatically create super user when running syncdb

MVP of the new world changing app is getting sculpted, you are still some weeks away from using migrations (aren't we always) and DB gets deleted even before it has time to say hello to it's neighbors on the disk, only to be recreated with another set of tables. Well, it is all fine and dandy for syncdb is smooth as silk expect for that annoying prompt to create super user! If I had a customer for every time I typed in admin/admin/admin/admin on terminal, I would receive VC funding faster than I can say funding.

But since we are not even getting a feature done leave aside getting a customer by doing this boring shit, here is how you get rid of it. You use fixtures. Next time you have created the super user, dump the auth tables thus:
$ django-admin.py dumpdata auth > initial_data.json
And next time run syncdb like this:
$ django-admin.py syncdb --noinput

And it is smooth as a chin shaved with Gillette Mach 3. Or Philips if that is what you prefer.

For better organization, do not forget to move it to a fixtures directory and add that directory to FIXTURES_DIR variable in settings.

Happy DB deleting!

Credits: Stackoverflow

Wednesday, September 25, 2013

Supporting IP address ranges in Django Internal IPs setting

Django internal ips is one of those pesky little details that turn out to be the reason for your css not loading in your web app after you restarted your machine. Here is the chain of events:

Restart -> DHCP -> IP change -> no longer an internal IP -> DEBUG is false -> your templates render as if on production -> you need css instead of less.

Unfortunately internal_ips can only take individual IP addresses and not a range. So if you decide to package your app into a nice vagrant VM for distributing to your colleagues, when they run and try to access it, again the same problem.

Solution is simple. After all it is Python we are talking about. :)

Inspired by http://dancarroll.org/blog/2011/01/debugging-django-dev-server/, I included a container derived from list that answers yes to the membership question whenever the given key matches one of the patterns in the list.

from fnmatch import fnmatch
class globlist(list):
    def __contains__(self, key):
        for pat in self:
            if fnmatch(key, pat): return True
        return False
# Put the whole internal range as internal ips
INTERNAL_IPS = globlist(['127.0.0.1','192.168.1.*'])

Voila!

Tuesday, June 4, 2013

Introspecting Django Models

कभी न कभी सभी को अपने गिरेबान में झांकना ही पड़ता है।
(Everyone is forced to look into their own affairs one day.)

We developers like to call it introspection. As if we are going to find something other than what we typed in ourselves! Thoreau went to a jungle to introspect. I am sure he was looking for a Python. Introspecting with Python is fun.

Anyway, it so happens that the simple matter of serializing JSON data to JSON was stuck on the matter of field instance vs field value. When you declare a field on a Django model and then create an instance of that model and do the following:

class DemoModel(models.Model):
    title = models.CharField(max_length=255)

model = DemoModel({'title': 'Introspecting'})
getattr(model, 'title') # 'introspecting'

You get the value of the field that it now holds.

But what if you need to access the methods and attributes of the CharField class. For that you need the instance of the CharField class. You can get that through the _meta attr on the model like this:

fld = model._meta.get_field('title')

# Now you can access the settings done on the class
getattr(fld, 'max_length') # prints 255

There are a bunch of other methods available that let you introspect everything from simple fields to foreign keys and many to many relations.

So now we can introspect from the comforts of our homes. No need to head out to woods.

Monday, June 3, 2013

Getting a Hierarchical URL structure going with DRF

Indians love hierarchy. Without hierarchy, our great nation will come to a stop. We wouldn't know what to do, whom to flatter and whom to diss. We carry over the same love of hierarchy to our technical architecture as well. If there is one thing you can be absolutely sure about DRF, it is that the author could not have been India. It is 2.3.4 and it still doesn't support hierarchical URLs out of box.

There are bunch of ways you can represent related resources in the API response. Out of them all, I liked the idea of returning a URL that you can use to fetch the related resource most appealing. So when you fetch a Publication, you get a list of URLs as part of it. Each URL represents one page. Now these URLs can be top level like:
/api/v1/pages/:pageid:

But since in our system, a page is always associated with a Publication, following seems more natural:
/api/v1/publications/:pubid:/pages/:pageid:

Trouble is that the built in HyperlinkedRelatedField cannot handle the second type of URL. Here is why. The URLs for related objects are generated by reverse lookup of views. Given a view_name, you can find the URL regex from URLconf. Then you fill in the captured parameter in the URL with the corresponding values for the given object and you have your URL.

However, HyperlinkedRelatedField only lets you specify only one captured argument and also mandates that it should be the same name as the corresponding field on the model. So if you are capturing the primary key which is the most common case, it would need to be called 'id' or 'pk'. This cannot work if you are capturing more than one primary keys from the URL since you cannot call both of them 'pk'. So we write our own MultilevelHyperlinkedField: 

class MultilevelHyperlinkedField(serializers.HyperlinkedRelatedField):
    '''
    Generate multilevel urls for foreign key relations
    '''
    def get_attr(self, obj, prop):
        '''
        Follow the dots
        '''
        value = obj
        for component in prop.split('.'):
            value = get_component(value, component)
            if value is None:
                break
        
        return value
    
    def get_url(self, obj, view_name, request, format):
        kwargs = {k: self.get_attr(obj, v) for k,v in self.lookup_field}
        logger.debug(kwargs)
        return reverse(view_name, kwargs=kwargs, request=request, format=format)
    
    def get_object(self, queryset, view_name, view_args, view_kwargs):
        qs_kwargs = {v: view_kwargs[k] for k,v in self.lookup_field}
        return queryset.get(**qs_kwargs)


Now we can build URLs as deep as we want:
pages = MultilevelHyperlinkedField(source='items', 
                                   many=True, 
                                   read_only = True, 
                                   view_name='page_details',
                                   lookup_field=[('pubid','publication.pk'),
                                                     ('pageid', 'pk')])

lookup_field, that can only be a single name in case of HyperlinkedRelatedField, is now a list of tuples. Each tuple provides a mapping between the name under which it is captured in the URL and the name of the field on the model. Notice that the name of the field on the model can be across models using the dot notation. This allows us to generate URLs as we like them.

Once we cross this hurdle, things start looking better for a while before they get ridiculous. I mean, how difficult would you imagine it would be, to serialize JSON? After all JSON is what we are serializing into! Turns out, not as easy as you would imagine. This sounds just too bureaucratic to be happening in my code. We hope to cut the red tape as soon as possible.

Sunday, June 2, 2013

Building a REST API using Django Rest Framework

It was a God forsaken day when I decided to build the front end of Instascribe using Backbone. I was so happy with my existing Spaghetti DOM code. It made me feel like a gladiator in the Roman Colosseum. But then good times never last.

As soon as I started using Backbone, it wanted REST. So much for a robust framework. It is thus that I found myself in need of a RESTful API for my Django app. My previous attempt at an API had produced a jungle of api endpoints that was as diverse as Amazon. The return values of the endpoints were also all over the map, sometimes returning html, sometimes json. (It is but natural that one would use the format that is easiest for the job at hand.)

But they say, to get REST, you need to be consistent. As I started cleaning up my code, I realized that there are other important things related to APIs that I have not yet thought about. Things like permissions, rate control, discovery. So I looked around and found django-tastypie and django-rest-framework. While Django tastypie sounded delicious and I was already feeling ravenous having lost my spaghetti, it lost the battle to django-rest-framework on account of its hydrate and dehydrate functions. No way I am going to write functions that are called hydrate and dehydrate in my web application code. I found the class based approach of writing serializers in django-rest-framework a lot more intuitive and cleaner.

The examples in the documentation of drf are varied and well written giving the impression that it will work fine for my use case (which, for some strange reason, almost always turns out to be that corner case that is still pending implementation).

So now I am busy building my new API using django-rest-framework. It is time to REST!