0

I'm a total Django newbie and apologize in advance if I'm not using the correct terminology.

I'm using django-registration to register user on my web-app. I've successfully adapted it work with my custom user model GeneralUser.

Conceptually, each GeneralUser has a Business, another model that I've defined. Whether this is the correct decision or not, I've decided that I never want to register a user without a related Business object.

I've read countless threads on customizing django form, and finally after a few days of unsuccessful attempts, came upon an answer that helped reach a solution. However, I am unsure that my code is correct/safe. This is my adaptation, followed by the linked-answer:

my adaptation:

class GeneralUserForm(UserCreationForm):
    business_name = forms.CharField(required=True)

    class Meta:
        model = GeneralUser
        fields = ['username', 'email', 'password1',
                  'password2', 'business_name']

    def save(self, commit=True):
        user = super(UserCreationForm, self).save(commit=True)
        business = Business(name=user.business_name, owner=user)

        # notice: no if-block
        user.save()
        business.save()
        # notice: returning only a user-instance
        return user

This code successfully creates a user and a business object, and creates the relationship. Looking at the original answer code though, I wonder if there isn't something critical I'm missing:

Answer I based my code on:

class UserCreateForm(UserCreationForm):
    job_title = forms.CharField(max_length=100, required=True)
    age = forms.IntegerField(required=True)

    class Meta:
        model = User

    def save(self, commit=True):
        if not commit:
            raise NotImplementedError("Can't create User and UserProfile without database save")
        user = super(UserCreateForm, self).save(commit=True)
        user_profile = UserProfile(user=user, job_title=self.cleaned_data['job_title'], 
            age=self.cleaned_data['age'])
        user_profile.save()
        # notice: multiple returns
        return user, user_profile

A few questions about the differences:

  • Why doesn't my code work if I end it like this:

.

if commit:
        user.save()
        business.save()
        return user
  • I'm not using cleaned_data, is that okay?

  • What is the purpose of the if not commit block in the original code?

  • Most importantly, is this a "legitimate way" to handle user registration that requires an automatic object-relation on creation?

Community
  • 1
  • 1
zerohedge
  • 3,185
  • 4
  • 28
  • 63

1 Answers1

1
  • cleaned_data is the dictionary of data after all validation in every field in that form. Now you can decide whether to rely on it or not(preferably you should).So as a pseudocode we could say cleaned_data + errors will be all fields.
  • commit is used to decide whether it should commit to db(write). From the above code, to add a related model object like profile, the original object(User) has to be created first.Thats why it make force commit.
  • To add a related object on object creation, there are multiple ways like post_save signals, override model save, override form save etc.So you are using one of good approach, I would say.
itzMEonTV
  • 19,851
  • 4
  • 39
  • 49
  • Thanks for taking the time to re-assure me. A little follow-up on `commit` if I may: It still isn't really clear to me why if I precede my two `save`s with `if commit:`, then it doesn't work. Isn't commit auto-set to be `True` in the definition? See this [this link](http://jessenoller.com/blog/2011/12/19/quick-example-of-extending-usercreationform-in-django) where the user creation `commit` is first set to False, and then there's an `if commit` block before `save()` – zerohedge May 10 '17 at 08:48
  • Also if I can squeeze one more question: The original code returns a tuple of `user, userprofile`, if I try to return `user, business` then I get an error. Where is this return used? and why does it throw me an error? – zerohedge May 10 '17 at 08:50
  • These answers you need to check.But check with `super`. You are calling `super(UserCreationForm)` . is it `super(GeneralUserForm)` ? in you first form – itzMEonTV May 10 '17 at 08:53