#This requires Mootools.  
#Get it at http://mootools.net/downloads/mootools-1.2-core-yc.js  
#I put mine in media/js.

#**Here are the models:**

from django.db import models

class Category(models.Model):
    name = models.CharField(max_length=255)

    def __unicode__(self):
        return self.name

    class Meta:
        app_label = 'product'
        verbose_name_plural = 'Categories'

class SubCategory(models.Model):
    category = models.ForeignKey('Category')
    name = models.CharField(max_length=255)

    def __unicode__(self):
        return self.name

    class Meta:
        app_label = 'product'
        verbose_name = 'Sub-Category'
        verbose_name_plural = 'Sub-Categories'

STATUS = (
    ( 'A', 'Active' ),
    ( 'I', 'Inactive' ),
    ( 'O', 'Out of Production'),
)

class Product(models.Model):
    name = models.SlugField(max_length=255)
    status = models.CharField(max_length=2, choices=STATUS, default='I')
    subcategory = models.ForeignKey(SubCategory)
    brand = models.CharField(max_length=255, blank=True)
    manufacturer = models.CharField(max_length=255, blank=True)
    description = models.TextField()
    short_description = models.CharField(max_length=255, blank=True)
    part_number = models.CharField(max_length=50, blank=True)
    model_number = models.CharField(max_length=50, blank=True)
    quantity = models.IntegerField(null=True, blank=True)
    image = models.ImageField(upload_to='product_images', blank=True)
    image_thumbnail = models.ImageField(upload_to='product_images', blank=True)
    created = models.DateField(auto_now_add=True)

    def __unicode__(self):
        return self.name.title()

    class Meta:
        app_label = 'product'


#**Then in admin.py:**

from django.contrib import admin
from django import forms
from vacancy.product.models import Category, SubCategory, Product

#first create a custom form to use in admin
class ProductAdminForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(ProductAdminForm, self).__init__(*args, **kwargs)
        print dir(self.instance)
        try:
            #Try and set the selected_cat field from instance if it exists
            self.fields['selected_cat'].initial = self.instance.subcategory.category.id
        except:
            pass
    #The product model is defined with out the category, so add one in for display
    category = forms.ModelChoiceField(queryset=Category.objects.all().order_by('name'), widget=forms.Select(attrs={'id':'category'}), required=False)
    #This field is used exclusively for the javascript so that I can select the 
    #correct category when editing an existing product
    selected_cat = forms.CharField(widget=forms.HiddenInput, required=False)

    class Meta:
        model = Product

    class Media:
        #Alter these paths depending on where you put your media 
        js = (
            'js/mootools-1.2-core-yc.js',
            'js/product.js',
        )

class ProductAdmin(admin.ModelAdmin):
    form = ProductAdminForm
    #I don't like using a fieldset here, because it makes the form more brittle,
    #if you change the model for form be sure to update the fieldset.
    #I'm using it in this instance because I need for category to show up 
    #right above the subcategory
    fieldsets = (
        (None, {
            'fields' : ('name','status','category','subcategory','description')
        }),
        ('Optional', {
            'classes' : ('collapse',),
            'fields' : ('brand','manufacturer','short_description','part_number','model_number','image','image_thumbnail','selected_cat')
        })
    )

admin.site.register(Product, ProductAdmin)

#**put this file in your media dir (ex: project_foo/media/js/product.js):**
window.addEvent('domready',function() {

    //You may will need to change category, id_subcategory, and id_selected_cat
    //to match the names of the fields that you are working with.
    var category = $('category');
    var subcategory = $('id_subcategory');

    var update_subcat = function() {
        var cat_id = $('id_selected_cat').value;
        if (cat_id) {
            $('id_selected_cat').value='';
            category.value=cat_id;
        } else {
            cat_id = category.getSelected()[0].value;
        }
        //cat_id = category.getSelected()[0].value;
        var subcat_id = subcategory.getSelected()[0].value;
        var request = new Request.JSON({
            url: "/product/subcategory/"+cat_id+"/",
            onComplete: function(subcats){
                subcategory.empty();
                if (subcats) {
                    subcats.each(function(subcat) {
                        var o = new Element('option', {
                            'value':subcat.pk,
                            'html':subcat.fields.name
                        });
                        if (subcat.pk == subcat_id) {
                            o.set('selected','selected');
                        }
                        o.inject(subcategory);
                    });
                } else {
                    var o = new Element('option', {
                        'value':'',
                        'html':'Please Choose A Category First'
                    });
                    o.inject(subcategory);
                }
            }
        }).get();
    };
    update_subcat();

    category.addEvent('change', function(e){
        e.stop();
        update_subcat();
    });

});

#**Then create the view to handle the ajax subcategory request:**

urls.py:
urlpatterns = patterns('',
    url(r'^subcategory/(?P<category_id>\d*)/$', 'foo.app.views.subcategory', name='subcategory'),
)

views.py:
from django.http import HttpResponse
from django.core import serializers

def subcategory(request, category_id):
    return HttpResponse(serializers.serialize('json', SubCategory.objects.filter(category=category_id), fields=('pk','name')))