This code will allow you to use chained select boxes in the django automatic admin area. For example, you may have a product, then a category and subcategory. You'd like to create a product, and then choose a category, and then have a chained select box be filled with the appropriate subcategories.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | #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')))
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 11 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 3 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
- Help text hyperlinks by sa2812 1 year, 7 months ago
Comments
when I change the DEBUG variable to False in settings.py , this snippet doesn't work, Why? Help me
#
Please login first before commenting.