Ooops, just realised I didn't finished writing the first sentence of
my previous post. So here it is:
"I have created a custom widget using the branch newforms-admin to
represent a ManyToMany relation with checkboxes."

On Nov 22, 10:49 pm, Julien <[EMAIL PROTECTED]> wrote:
> Hi all,
>
> I have created a custom widget using the branch newforms-admin to
> represent  (see code below):
>
> To test it, create a couple of countries, then a few cities attached
> to those countries, and then create a new Person.
>
> In the class PersonOptions, the line "formfield.widget.render =
> widgets.RelatedFieldWidgetWrapper(formfield.widget.render,
> db_field.rel, self.admin_site)" allows me to get the green cross. By
> clicking that cross, a popup appears and you can add a new city. Until
> then it's great....
>
> ....except that once the new city is saved, the popup doesn't close.
> It remains blank, and if you look at the html source of that popup
> you'll get something like:
> "<script type="text/javascript">opener.dismissAddAnotherPopup(window,
> 7, "New York");</script>"
>
> By looking at the function "dismissAddAnotherPopup" in the file
> "http://127.0.0.1:8000/media/js/admin/RelatedObjectLookups.js"; it
> seems that if the widget is not a "select" component, then it won't be
> refreshed.
>
> So, my questions:
> - How can we get that pop up window to close when the new city is
> saved?
> - How can we refresh the custom widget?
> - How can we put the green cross in a better place? (with the current
> template it is placed in the bottom left corner, which is not that
> visible)
>
> Thanks a lot for your help!
>
> 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)
--~--~---------~--~----~------------~-------~--~----~
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