Thursday, May 27, 2010

Extending django model with custom search method

This is really fun. Been requested to developed a prototype for a simple system, my immediate choice is django, this time rather than using sqlalchemy, i'm using anything that comes with django umbrella. In this prototype, I add an ajax based auto completion/suggestion search input form, just to give a small 'wow' effect to my customer. Using jquery ajax call, and returning json list of dictionaries.

The best part actually the way how you can extend django model to add you own specific method, for example i add a search method in profile model.

once extended you can simply call it :

searchObj =['q']).order_by('prof_firstname')

and in the same time, the search box actually allowed user to search for profile firstname or lastname and aslo ic number using the same input box.

and here how you can do it in your models (this is my django profile model file):
make sure you add the ProfileManager class inside your model (highlighted in yellow).

# Load modules needed
import operator

from django.db import models
from django.db.models import Q

class ProfileManager(models.Manager):
    def search(self, search_terms):
        terms = [term.strip() for term in search_terms.split()]
        q_objects = []

        for term in terms:

        # Start with a bare QuerySet
        qs = self.get_query_set()

        # Use operator's or_ to string together all of your Q objects.
        return qs.filter(reduce(operator.or_, q_objects))

class Profile(models.Model):
    """ table profile """
    prof_ic = models.CharField(max_length = 12, primary_key = True) # mungkin ic ada abjad (tentera)
    prof_firstname = models.CharField(max_length = 32)
    prof_lastname = models.CharField(max_length = 32)
    prof_dob = models.DateTimeField()
    prof_gender = models.CharField(max_length = 1)
    prof_race = models.CharField(max_length = 32)
    prof_address_1 = models.CharField(max_length = 128)
    prof_address_2 = models.CharField(max_length = 128)
    prof_city = models.CharField(max_length = 32)
    prof_state = models.CharField(max_length = 32)
    prof_country = models.CharField(max_length = 32)
    prof_postcode = models.CharField(max_length = 16)
    prof_telno = models.CharField(max_length = 16)
    prof_mobileno = models.CharField(max_length = 16)
    prof_email = models.EmailField(max_length = 128)
    prof_img = models.ImageField(max_length = 256, upload_to = 'profile')
    prof_sysdate = models.DateTimeField()
    objects = ProfileManager()

    class Meta:
        app_label = "pingat"

Getting IP Address/Interfaces with Python

# easy_install netifaces

in python shell:

// list all interfaces

>>> import netifaces
>>> netifaces.interfaces()

['lo0', 'gif0', 'stf0', 'en0', 'fw0', 'en1', 'vboxnet0']

// now get the addresses only for AF_INET

>>> for iface in netifaces.interfaces():
...     if netifaces.AF_INET in netifaces.ifaddresses(iface) and\
...     'addr' in netifaces.ifaddresses(iface)[netifaces.AF_INET][0]:
...             print iface, netifaces.ifaddresses(iface)[netifaces.AF_INET][0]['addr']