1

When a user registers in my app, he must enter a full_name. The UserModel has no full_name field, but first_name and last_name, so I have a naive function which is good enough for my use case:

def split_full_name(full_name):
    if not full_name:
        first_name, last_name = None, None
    else:
        parts = full_name.split(' ')
        if len(parts) == 1:
            first_name = parts[0]
            last_name = None
        elif len(parts) == 2:
            first_name = parts[0]
            last_name = parts[1]
        else:
            first_name = parts[0]
            last_name = ' '.join(parts[1:])
    return first_name, last_name

I am overriding the registration form as explained here:

class MyRegistrationForm(RegistrationForm):

    full_name = forms.CharField(required=False)

    def clean_full_name(self):
        full_name = self.cleaned_data['full_name']
        first_name, last_name = split_full_name(full_name)
        self.cleaned_data['first_name'] = first_name
        self.cleaned_data['last_name'] = last_name
        return full_name

But the first_name and last_name from the cleaned_data are not saved to the model. What should I do to achieve that?

I have seen the use of hidden fields for that, but I would like something a bit less hacky. Can I manually populate some fields of the user instance during form validation / processing?

EDIT

Just to avoid confussion: I do not want to add a full_name field to the UserModel. I am just using the stock UserModel, but I want to simplify the form by allowing the user to enter full_name directly and then programatically generating first_name and last_name.

Community
  • 1
  • 1
blueFast
  • 41,341
  • 63
  • 198
  • 344
  • you can customize the user model https://docs.djangoproject.com/en/1.9/topics/auth/customizing/#specifying-a-custom-user-model – ofnowhere Dec 17 '15 at 10:12
  • @ofnowhereland: I don't need to customize the user model. It has everything I need. – blueFast Dec 17 '15 at 10:25
  • @Sayse: maybe I have not been clear enough. The `full_name` is just a form field, not a user model field. The fields in the user model are indeed `first_name` and `last_name` (as defined in the stock UserModel), and *not* `full_name`, so there is no duplication. I just don't want to force the user to fill in two separate fields in the form. – blueFast Dec 17 '15 at 10:31
  • Ah ok so this is purely an almost cosmetic front end thing (or usability anyway). I would have expected the form code you've provided to work....Do you get any errors with this (form invalid?)? (I've removed my previous comments to remove noise from your question) – Sayse Dec 17 '15 at 10:38
  • @Sayse: yes, I guess you can call it a usability thing. And no errors at all, but the model fields `first_name` and `last_name` are not populated. – blueFast Dec 17 '15 at 10:40
  • Possibly an issue in your actual form saving then... the only other thing I'd suggest is set breakpoints in the form `clean_first_name` / `last_name` methods and see what order they are populated in, its possible that your values are being overridden before you get anywhere – Sayse Dec 17 '15 at 10:45

1 Answers1

1

Try setting the first name and last name on the form's instance, instead of adding them to cleaned_data.

def clean_full_name(self):
    full_name = self.cleaned_data['full_name']
    first_name, last_name = split_full_name(full_name)
    self.instance.first_name = first_name
    self.instance.last_name = last_name
    return full_name

If that doesn't work, I would try overriding the form's save() method and set the values there.

As an aside, you might have issues assigning None to first_name and last_name. I would use the empty string '' instead.

Alasdair
  • 298,606
  • 55
  • 578
  • 516
  • Works great, thanks! I do not understand what are the roles of `cleaned_data` vs `instance` values. Is this documented somewhere? – blueFast Dec 17 '15 at 11:14
  • Every form has a clean methods that return `cleaned_data`. `ModelForm`s also have an `instance`, which is the (existing or new) object that is being edited. When the form is validated, the values from `cleaned_data` are used to update the `instance`. In your case, because the `RegistrationForm` does not have `first_name` and `last_name` fields, adding them to `cleaned_data` will not work, so we modify the instance directly. You might find the docs for [validation on a model form](https://docs.djangoproject.com/en/1.9/topics/forms/modelforms/#validation-on-a-modelform) useful. – Alasdair Dec 17 '15 at 11:42