Malcolm Tredinnick schrieb: > On Tue, 2006-10-24 at 08:19 -0700, exdnc wrote: >> Is there a 'proper' way to get the framework to add more than >> num_in_admin related objects to both the Add/ChangeManipulator and to >> the FormWrapper? Thanks! > > The short answer to your question is "no": the num_in_admin setting > controls the default number of form entry fields in that case. > > To solve your problem in a neat way, you might want to have a look in > django/forms/__init__.py at the InlineObjectCollection class and try to > exploit that in a custom manipulator. This isn't documented at all, so > you'll have to read the source code and do a bit of experimenting, but > it should be possible to get something that works.
OK--I wanted to wait whether Malcolms comes up with a better idea ;-) I can provide you with a skeleton, but it's not that easy, and I'm not such a good writer. If you try it, we could summarize the results into a wiki page. I have gone that path (and I really hope that the reworked forms will make this easier. It was all trial and error.) I removed everything specific from my working code, so there might be trivial typing errors, but the idea worked. But you need to follow my instructions not blindly, try to understand what I mean. First, you need a class that represents the collection of inlined objects, RelatedWHATEVER (replace WHATEVER with the inline model name and ... with what fits). It's needed for all the FormWrapper stuff to work and allows {{ XXX.1.fieldname }} in the template. (Of course you should replace XXX with a better name.) ---------------------------- class RelatedWHATEVER(object): class DummyField(object): """ Fakes a database field """ def __init__(self, field_names): self.field_names = field_names def get_manipulator_field_names(self, dummy): return [self.field_names] def __init__(self, related_objs): self.related_objs = related_objs self.related_fields = ["fieldname1", ...] self.name = 'XXX' # qualifier in forms self.opts = models.WHATEVER._meta def extract_data(self, data): """Values for inline model data. It doesn't hurt to return everything, though. """ return data def get_list(self, original_mailbox): """Returns inline objects and None for empty lines to insert""" return self.related_objs + [None] def editable_fields(self): """Needs to return kind of placebos for all database fields.""" return [self.DummyField(name) for name in self.related_fields] ------------------------- Then you need custom manipulators (I hope I haven't lost you now). I usually derive them from Manipulator and not from the automatic manipulators, these seem to get into my way and try to validate fields I don't use etc. Your custom manipulator needs to do a little extra stuff. Some imports: from itertools import izip, chain, repeat, count from django.utils.datastructures import DotExpandedDict In __init__: self.rel_WHATEVER = RelatedWHATEVER(related_objs) # (Or [] in the AddManipulator) for i in range(related_objs + 1): prefix = "XXX.%d." % i self.fields.extend([ ... # add fields with names like "%s.fieldname" % prefix" ]) You need the following function for FormWrapper etc. def get_related_objects(self): return [self.rel_WHATEVER] The ChangeManipulator needs to flatten the related objects too: def flatten_data(self): data = { ... } # data for your master object for i, obj in enumerate(self.rel_WHATEVER.related_objs): prefix = 'XXX.%d.' % i ... # add data['%s.fieldname' % prefix] # for all fields of the related object obj return data Save also needs to save your related data. I found it's best to move this into a separate method, so my save() looks like this: ... # save your master object, then self.save_related(...) ... And this is save_related(self, data, ...): dot_data = DotExpandedDict(data)['XXX'] # go through all related rows, put data in rel_data # and the corresponding mailrule object into rule, filling in None when # we run out of existing related objs. for rel_data, obj in izip( (dot_data[str(i)] for i in range(len(dot_data))), chain(self.rel_WHATEVER.related_objs, repeat(None))): # you have the data for one related obj in rel_data ... # save it All validators for your related fields will be called the normal way, but if you need to have special validation on the related data, you need to tweak get_validation_errors. This is optional! def get_validation_errors(self ,data): errors = super(..., self).get_validation_errors(data) dot_data = DotExpandedDict(data)['XXX'] for rel_data, obj in izip( (dot_data[str(i)] for i in range(len(dot_data))), chain(self.rel_WHATEVER.related_objs, repeat(None))): ... # do your validation with rel_data and obj. ... That's it. It probably won't work immediately, just ask when you have trouble that you can't solve on your own. Michael -- noris network AG - Deutschherrnstraße 15-19 - D-90429 Nürnberg - Tel +49 911 9352-0 - Fax +49 911 9352-100 http://www.noris.de - The IT-Outsourcing Company --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---