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
-~----------~----~----~----~------~----~------~--~---

Reply via email to