Doesn't anyone know how to help me on this? Also, I've found another problem. Using the custom form field CitiesField makes the attribute required (I get an error if I don't put any cities in a person's profile). But it is not required if I switch back to the regular ManyToManyField form field. How can I make the custom one not required and interpret the "blank=True" statement?
Many thanks, Julien On Nov 22, 10:53 pm, Julien <[EMAIL PROTECTED]> wrote: > 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 -~----------~----~----~----~------~----~------~--~---