congrats. interesting solution. Lately I've switched to newforms admin too.
On Nov 22, 11:50 am, Julien <[EMAIL PROTECTED]> wrote: > Hi Kamil and all, > > I have finally found what I was looking for by using the branch > newforms-admin. > It could be tidied up a bit, but at least it works! > Hope that will help others. > > (Note: all this led me to some other questions, which I have posted > there:http://groups.google.com/group/django-users/browse_thread/thread/cab9...) > > Here is the actual code: > > class Country(models.Model): > name = models.CharField(max_length=50) > def __unicode__(self): > return self.name > > class City(models.Model): > name = models.CharField(max_length=50) > country = models.ForeignKey(Country) > def __unicode__(self): > return self.name > > class Person(models.Model): > firstName = models.CharField(max_length=30) > lastName = models.CharField(max_length=30) > citiesLived = models.ManyToManyField(City, null=True, blank=True) > def __unicode__(self): > return self.firstName + " " + self.lastName > > from django.newforms.widgets import * > from django.newforms.fields import MultipleChoiceField > from django.template import Context, Template > from django.newforms.util import flatatt > from django.utils.encoding import force_unicode > from itertools import chain > from django.utils.html import escape > class CitiesWidget(CheckboxSelectMultiple): > template_string="""<p>{% regroup city_list|dictsort:"country" by > country as cities_by_country %} > {% for country in cities_by_country %} > <b>{{ country.grouper }}</b><br/> > {% for city in country.list|dictsort:"name" > %} > {{ city.html }}<br/> > {% endfor %} > <br/> > {% endfor %}</p> > """ > def render(self, name, value, attrs=None, choices=()): > if value is None: value = [] > has_id = attrs and 'id' in attrs > final_attrs = self.build_attrs(attrs, name=name) > str_values = set([force_unicode(v) for v in value]) # > Normalize to strings. > city_list = [] > for i, (option_value, option_label) in > enumerate(chain(self.choices, choices)): > city = City.objects.get(id=option_value) > # If an ID attribute was given, add a numeric index as a > suffix, > # so that the checkboxes don't all have the same ID > attribute. > if has_id: > final_attrs = dict(final_attrs, id='%s_%s' % > (attrs['id'], i)) > cb = CheckboxInput(final_attrs, check_test=lambda value: > value in str_values) > option_value = force_unicode(option_value) > rendered_cb = cb.render(name, option_value) > html = (u'%s %s' % (rendered_cb, > escape(force_unicode(option_label)))) > city_list.append({"country":city.country.name, "name": > option_label, "html":html}) > t = Template(self.template_string) > c = Context({"city_list": city_list}) > return t.render(c) > > class CitiesField(MultipleChoiceField): > widget = CitiesWidget > > from django.contrib.admin import widgets > class PersonOptions(admin.ModelAdmin): > def formfield_for_dbfield(self, db_field, **kwargs): > if db_field.name == 'citiesLived': > cities = kwargs['initial'] > kwargs['initial'] = [city.id for city in cities] > formfield = CitiesField(**kwargs) > formfield.choices = [(city.id, city.name) for city in > City.objects.all()] > formfield.widget.render = > widgets.RelatedFieldWidgetWrapper(formfield.widget.render, > db_field.rel, self.admin_site) > return formfield > else: > return > super(PersonOptions,self).formfield_for_dbfield(db_field,**kwargs) > > admin.site.register(Country) > admin.site.register(City) > admin.site.register(Person, PersonOptions) > > On Nov 22, 12:44 am, kamil <[EMAIL PROTECTED]> wrote: > > > sorry > > line "{{ group.grouper.name }}: [ > > shoud be: > > "{{ group.grouper.name }}": [ > > > On Nov 21, 11:49 am, kamil <[EMAIL PROTECTED]> wrote: > > > > HiJulien > > > > in fact you don't even have to write view for it you can use generic > > > view as follows: > > > > put in your url.py: > > > --------------------------------------- > > > > from yourproject.cities.models import City > > > > urlpatterns = patterns('', > > > ...... > > > (r'^custom_widget.js', > > > 'django.views.generic.list_detail.object_list', { 'queryset': > > > City.objects.all(), template_name='custom_widget.html' } ), > > > ............ > > > ) > > > > ------------------------------------------ > > > with this line you hook all together: model view template and url > > > recommeded read about generic views :) > > > > good luck > > > > On Nov 21, 12:14 am,Julien<[EMAIL PROTECTED]> wrote: > > > > > Thanks again Kamil for your help! > > > > > Ok, now I'm trying to put everything together. Sorry I'm just starting > > > > with Django and I am still a bit lost. > > > > > What I am not sure about is: > > > > - where to put the view? > > > > - how to hook the view to the model > > > > - how to hook the template with the view. > > > > > Could you provide a full example, based on the summarization below? > > > > > Thanks a lot! > > > > > models.py: > > > > --------------- > > > > > class Country(models.Model): > > > > name = models.CharField(max_length=50) > > > > def __unicode__(self): > > > > return self.name > > > > class Admin: > > > > pass > > > > > class City(models.Model): > > > > name = models.CharField(max_length=50) > > > > country = models.ForeignKey(Country) > > > > def __unicode__(self): > > > > return self.name > > > > class Admin: > > > > pass > > > > > class Person(models.Model): > > > > firstName = models.CharField(max_length=30) > > > > lastName = models.CharField(max_length=30) > > > > citiesLived = models.ManyToManyField(City, null=True, blank=True) > > > > def __unicode__(self): > > > > return self.firstName + " " + self.lastName > > > > class Admin: > > > > js = "http://mysite.com/custom_widget.js" > > > > > custom_widget.html (template) > > > > ------------------------------------------ > > > > > var countries = { > > > > {% regroup cities by country as grouped %} > > > > {% for group in grouped %} > > > > "{{ group.grouper.name }}: [ > > > > {% for city in group.list %} > > > > '{{city.name}}' , > > > > {% endfor %} ] > > > > {% endfor %} > > > > > } > > > > > custom_widget.js > > > > ------------------------ > > > > > var countries = {'england': ['London','Manchester'], 'france': > > > > ['Paris'] } > > > > > document.forms['your_form'].id_country.onchange = function() > > > > { listCities(this.value) }; > > > > > function listCities ( country ) { > > > > document.forms['your_form'].id_city.options.length = 0 > > > > var l = countries[ country ].length; > > > > for (var i = 0; l > i; i++) { > > > > document.forms['your_form'].id_city.options[i] = new > > > > Option( countries[ country ][i], countries[ country ][i]); > > > > } > > > > > } > > > > > On Nov 21, 11:06 am, kamil <[EMAIL PROTECTED]> wrote: > > > > > > You would achieve it using "regroup" template tag > > > > > First get cities in your view > > > > > and create template with code: > > > > > > var countries = { > > > > > {% regroup cities by country as grouped %} > > > > > {% for group in grouped %} > > > > > "{{ group.grouper.name }}: [ > > > > > {% for city in group.list %} > > > > > '{{city.name}}' , > > > > > {% endfor %} ] > > > > > {% endfor %} > > > > > > } > > > > > > (If it dosnt work straigt away just look at "regroup" template tag in > > > > > the docs - idea is there) > > > > > > add url of this template to js list in model admin code and thats > > > > > all :) > > > > > > On Nov 20, 11:54 am,Julien<[EMAIL PROTECTED]> wrote: > > > > > > > Hi, > > > > > > > When I look at the html source code generated for the regular > > > > > > ManyToManyField's widget, it's an html form, not javascript... > > > > > > Are you sure there is no other way? > > > > > > > Could you please give a full example? > > > > > > > I've spent quite sometime practicing with the tutorials but I'm a > > > > > > bit > > > > > > lost on this one. > > > > > > > Thanks a lot! > > > > > > > On Nov 20, 9:04 pm, kamil <[EMAIL PROTECTED]> wrote: > > > > > > > > I dont think there is another way that making your hands dirty > > > > > > > with > > > > > > > javascript. ;) > > > > > > > If you want to be fancy you can even make it ajax - getting the > > > > > > > cities > > > > > > > on demand > > > > > > > > On Nov 20, 9:35 am, kamil <[EMAIL PROTECTED]> wrote: > > > > > > > > > You can easily generate cities list to the javascript > > > > > > > > dynamically > > > > > > > > writing the template for separate js file. > > > > > > > > > On Nov 20, 9:22 am,Julien<[EMAIL PROTECTED]> wrote: > > > > > > > > > > Hi Kamil, > > > > > > > > > > Thanks a lot for your suggestion! > > > > > > > > > > I have a few remarks though. The list of cities is dynamic, > > > > > > > > > in the > > > > > > > > > sense that you may add, remove cities from the database at > > > > > > > > > any time > > > > > > > > > using the admin interface. > > > > > > > > > So how can we fetch dynamically the list of available cities > > > > > > > > > to > > > > > > > > > display them in the select widget? > > > > > > > > > > Also, isn't there a "recommended" way of doing? Hijacking with > > > > > > > > > javascript seems more like a trick. I may be wrong. > > > > > > > > > > Thanks! ;) > > > > > > > > > > On Nov 20, 8:13 pm, kamil <[EMAIL PROTECTED]> wrote: > > > > > > > > > > > HiJulien > > > > > > > > > > > The simple way is hijack city select box with javascript. > > > > > > > > > > You add > > ... > > read more >> --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~----------~----~----~----~------~----~------~--~---