4

Given:

from django.db import models
class MyModel(models.Model):
    ...
    owners = models.CharField(max_length=255, blank=False)

where owners is a pipe-separated list of email addresses.

In the page, there are multiple <input> fields with the same name, so the server gets the values in an array.

The HTML code for the form was done by-hand and doesn't use built-in templates (such as form.as_p).

Can Django's ModelForms handle something like this?

What is the proper location to handle the data transformation, both when retrieving the model (do I have to make a custom models.Manager?) and when saving it (which save() method do I override? the Model's or the ModelForm's)?

--UPDATE FOR CLARIFICATION--

In the database:

+-----+---------------------------+-----+
| ... |           owners          | ... |
+-----+---------------------------+-----+
| ... | "a@a.com|b@b.com|c@c.com" | ... |
+-----+---------------------------+-----+

The form:

<form ... >
    ...
    <input type="text" name="owners" />
    <input type="text" name="owners" />
    <input type="text" name="owners" />
    ...
</form>
Nikki Erwin Ramirez
  • 9,676
  • 6
  • 30
  • 32

2 Answers2

10

You can use forms.MultiValueField and forms.MultiWidget. MultiValueField knows that your model's one field contains multiple discrete values and the MultiWidget widget knows how each discrete value should be presented. They'll handle creating unique names for your fields so that they can reconstruct the form from POST values and you won't have to override any form methods that provide implementation, i.e. you won't have to override save().

As you can see, the official docs are a bit thin on the topic. I suggest you take a peek at the code to figure out how everything is wired and what gets called when, since your requirements are always going to need a unique solution, i.e: how many emails will the field contain? Exactly two, so I can specify two CharField widgets by hand, or is it going to be between 0-2, so I have to dynamically construct everything depending on the value passed? If you need a good example as a starting reference, check out this SO question which contains a clean and easy to follow implementation.

Ideally, you'll want to have a PipedEmailAddressesField that extends CharField as your model's field, one that knows that it's storing piped email addresses. It should be able to construct it's own appropriate MultiValueField form field which should in turn construct it's own appropriate MultiWidget field.

Community
  • 1
  • 1
Filip Dupanović
  • 32,650
  • 13
  • 84
  • 114
  • Thanks for the elaborate answer! The way you said it, I'm kinda convinced that this is the correct answer. Will try this out within the next few days to confirm it. :) – Nikki Erwin Ramirez Mar 17 '11 at 11:16
  • If it's not any bother, do you have any tips on how I should go about dynamically constructing the appropriate number of fields, say if I had no limit (or an incredibly large one)? – Nikki Erwin Ramirez Mar 21 '11 at 04:18
  • I did a partial solution. I made a PipedEmailField that splits a pipe-separated string and runs validation on each token. Didn't bother with the widget. In my front-end, I just had a hidden input field where I dump a pipe-separated string from the values of multiple text fields using JavaScript, before form submission. I'll accept this answer anyway, since it still proved to be very helpful. – Nikki Erwin Ramirez Apr 04 '12 at 07:20
1

Here is an example of saving a modelform in a view: http://themorgue.org/blog/2008/05/14/django-and-modelform/ You can get the extra fields manually using request.POST['fieldname'] Hope this helped.

endre
  • 1,363
  • 1
  • 11
  • 22