# Create a new user, manually

**URL:** <https://forum.djangoproject.com/t/create-a-new-user-manually/8335>\
**Category:** Using Django\
**Created:** [June 14, 2021, 2:38am UTC](https://forum.djangoproject.com/t/create-a-new-user-manually/8335 "2021-06-14T02:38:03Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![typonaut](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/typonaut/32/2316_2.png) [@typonaut](https://forum.djangoproject.com/u/typonaut)\
**Post date:** [June 14, 2021, 2:38am UTC](https://forum.djangoproject.com/t/create-a-new-user-manually/8335/1 "2021-06-14T02:38:03Z")

</div>

I am trying to build an admin page where an admin user can create a new user. Although it seems simple enough to have the user create their own account, or to create such through the Django Admin interface, I am really struggling to work out how to build my custom admin to allow creation of new users.

I am using `django_allauth` for users creeating their own accounts, but the project also requires that an admin can create new accounts (in fact it will probably and up with admins creating all accounts).

While I can create views and forms to create other new elements, I cannot work out how to do this for users. Are there special `CreateUser` views or forms?

Any pointers appreciated.

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [June 14, 2021, 2:57am UTC](https://forum.djangoproject.com/t/create-a-new-user-manually/8335/2 "2021-06-14T02:57:59Z")

</div>

It’s going to be more helpful if you would describe in more detail exactly what isn’t working for you when you’re trying to create a user.  
Are you using the standard User class? If so, you can look at the [create\_user](https://docs.djangoproject.com/en/3.2/topics/auth/default/#creating-users) helper method in the docs to see one way of doing it.  
If you’re using a custom user object, we’ll probably need to see that Model along with the view you’re using to create the user.

---

<div class="post-metadata">

**Author:** ![typonaut](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/typonaut/32/2316_2.png) [@typonaut](https://forum.djangoproject.com/u/typonaut)\
**Post date:** [June 14, 2021, 3:26am UTC](https://forum.djangoproject.com/t/create-a-new-user-manually/8335/3 "2021-06-14T03:26:22Z")

</div>

I have a Profile model:

```auto
class Profile(models.Model):
    id = models.BigAutoField(primary_key=True)
    #id = models.CharField(primary_key=True, default=shortuuid.uuid, max_length=26)
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    account = models.ForeignKey('Account', verbose_name=_('account'), on_delete=models.CASCADE)
    home_phone = PhoneNumberField(_('Home phone'), max_length=30, null=True, blank=True, help_text=_('If outside the UK include country code (eg: "+39", "+353", "+33"…)'))
    work_phone = PhoneNumberField(_('Work phone'), max_length=30, null=True, blank=True, help_text=_('If outside the UK include country code (eg: "+39", "+353", "+33"…)'))
    mobile_phone = PhoneNumberField(_('Mobile phone'), max_length=30, null=True, blank=True, help_text=_('If outside the UK include country code (eg: "+39", "+353", "+33"…)'))
    receive_news = models.BooleanField(_('Receive news'), default=True, db_index=True)
    
    createdate = models.DateTimeField(auto_now_add=True, db_index=True)
    moddate = models.DateTimeField(auto_now=True, db_index=True)

    @staticmethod
    def get_or_create_for_user(user):
        if hasattr(user, 'profile'):
            return user.profile
        else:
            return Profile.objects.create(user=user)

```

And in settings.py:

```auto
AUTHENTICATION_BACKENDS = (
    'django.contrib.auth.backends.ModelBackend',
    'allauth.account.auth_backends.AuthenticationBackend',
)

```

Which is what I think links the `Profile` to the `User`.

I put together a simple view:

```auto
class ControlProfileCreateView(CreateView):
	model = get_user_model()
	template_name = 'manageit/control/profile_edit.html'
	form_class = ControlProfileForm
	success_url = reverse_lazy('admin-control')

```

and form:

```auto
class ControlProfileForm(forms.ModelForm):
	
	class Meta:
		model = Profile
		fields = (
			'home_phone',
			'work_phone',
			'mobile_phone',
			'receive_news'
		)

```

I can get an empty form in a browser, but when I save the form I get an error that the `Column 'user_id' cannot be null`. I know this is a MySQL error, and I understand why (because the `user` field in `Profile` needs an id to link it to `auth_user` table).

No real idea how to get around that.

I tried searching for queires others had posted about this subject, and found some notes on allauth, which used this form:

```auto
class ControlProfileForm(forms.Form):
    model = get_user_model()
    first_name = forms.CharField(max_length=30, label='First name')
    last_name = forms.CharField(max_length=30, label='Last name')
    email = forms.CharField(max_length=30, label='E-mail')
    #home_phone = forms.CharField(max_length=20, label='Home phone')
    #work_phone = forms.CharField(max_length=20, label='Work phone')
    #mobile_phone = forms.CharField(max_length=20, label='Mobile phone')

    def signup(self, request, user):
        user.first_name = self.cleaned_data['first_name']
        user.last_name = self.cleaned_data['last_name']
        user.email = self.cleaned_data['email']
        # Replace 'profile' below with the related_name on the OneToOneField linking back to the User model
        #up = user.profile
        #up.home_phone = self.cleaned_data['home_phone']
        user.save()
        #up.save()

```

But on calling the form in a browser I get an error:

` __init__ () got an unexpected keyword argument 'instance'`

Which is buried in `django/views/generic/edit.py`

I want the admin user to be able to create the `Profile`/`auth_user` rows, on a form, but not in the Django Admin interface.

Sorry, this keeps saving before I finish!

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [June 14, 2021, 12:51pm UTC](https://forum.djangoproject.com/t/create-a-new-user-manually/8335/4 "2021-06-14T12:51:51Z")

</div>

First, I’m a little confused - are you trying to create both the User and the Profile in the same view? Or are you looking to have a form that just collects / creates Profile data to be associated with a User?

(The reason I’m asking is because your `ControlProfileCreateView` has a `model` attribute of User and not Profile, so your intent is not clear to me.)

Also, you wrote:

> [@typonaut](#):
>
> ```auto
> AUTHENTICATION_BACKENDS = (
> 'django.contrib.auth.backends.ModelBackend',
> 'allauth.account.auth_backends.AuthenticationBackend',
> )
> 
> ```
> 
> Which is what I think links the `Profile` to the `User` .

No, that’s not correct - what links your Profile to the User is precisely this:

> [@typonaut](#):
>
> ```auto
> user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
> 
> ```

So in general, what this means is that you need the PrimaryKey of the User object when you’re trying to create your profile.

If you’re create both objects in the same view, the general pattern is:

```auto
new_user = YourUserForm.save()
new_profile = YourProfileForm.save(commit=False)
new_profile.user = new_user
new_profile.save()

```

Otherwise, if this is a second view for just the Profile, you need to pass the PK of the referenced user in as a parameter. Then, when you’re creating the form, use that Id to initialize the `user` field.

---

<div class="post-metadata">

**Author:** ![typonaut](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/typonaut/32/2316_2.png) [@typonaut](https://forum.djangoproject.com/u/typonaut)\
**Post date:** [June 14, 2021, 2:50pm UTC](https://forum.djangoproject.com/t/create-a-new-user-manually/8335/5 "2021-06-14T14:50:08Z")

</div>

> Are you trying to create both the User and the Profile in the same view?

Yes, as they are intrinsically linked, and I don’t want the admin to have to create a user, and then create a profile.

I think with `ControlProfileCreateView` I tried it with both `User` and `Profile` as the model. Same result.

Sorry, what I meant about the `AUTHENTICATION_BACKENDS` was that this is what sets-up allauth to manage the `auth_user`, of course the relationship between `User` and ``Profile``` is as you write.

Hmm, so maybe a formset would be in order?

While I’m here, you will notice that this line, above, is commented out:

`#id = models.CharField(primary_key=True, default=shortuuid.uuid, max_length=31)`

I would like to use UUIDs for at least some of the primary keys, but when using this form every time I run `makemigrations` it reports tha the `id` field has changed – when I know that it has not. Has anyone else recommendations for UUID/randomised ID generation in django?

Thanks

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [June 14, 2021, 5:05pm UTC](https://forum.djangoproject.com/t/create-a-new-user-manually/8335/6 "2021-06-14T17:05:44Z")

</div>

Ok, fair enough. You then have at least two options.

1. Create your view for _one_ of the two classes (the Generic Class-Based Views are designed to work with a single form for a single model). Then, add the fields needed for the _other_ model as additional fields in the form. When the form is submitted, manually create that other object from those supplied fields and save them both.

2. Create your own View class (or view function) with two forms, one for each model. Then save them both using the pattern I described earlier.

A formset isn’t the right answer here, because you’ve got two forms for two different classes. Formsets are designed to work with multiple instances of the same class.

(Sorry, no recommendations for your question about UUIDs.)

---

<div class="post-metadata">

**Author:** ![typonaut](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/typonaut/32/2316_2.png) [@typonaut](https://forum.djangoproject.com/u/typonaut)\
**Post date:** [June 14, 2021, 6:05pm UTC](https://forum.djangoproject.com/t/create-a-new-user-manually/8335/7 "2021-06-14T18:05:29Z")

</div>

Ok, so I started trying to save/create the `User`, with a `form.ModelForm`, but found that I needed a `username` which I think this project will never need - log-in will be with email address), and that the `password` was null when saved (no password field on the form).

As a test I randomised `username` and `password` with initial field values on the form, which saved, but the `password` is not hashed.

Because the admin never needs to see the `username` or `password` there is no point their being on the form, so I thought I could do something like this in the view:

```auto
class ControlProfileCreateView(CreateView):
	model = get_user_model()
	template_name = 'bjsc_manage/control/profile_edit.html'
	form_class = ControlUserForm
	success_url = reverse_lazy('admin-control')
	
	def form_valid(self, form):
		user = get_user_model()
		user.username = shortuuid.uuid()
		user.password = shortuuid.uuid()
		user.save

```

Would that be the right approach, and hash the password?

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [June 14, 2021, 6:15pm UTC](https://forum.djangoproject.com/t/create-a-new-user-manually/8335/8 "2021-06-14T18:15:42Z")

</div>

Yes, you **must** have a username. In your case, you can copy the email field to the username field.

Also, you’re right, you don’t save the password directly. See the create\_user method I referenced above - [Create a new user, manually - #2 by KenWhitesell](https://forum.djangoproject.com/t/create-a-new-user-manually/8335/2)

---

<div class="post-metadata">

**Author:** ![typonaut](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/typonaut/32/2316_2.png) [@typonaut](https://forum.djangoproject.com/u/typonaut)\
**Post date:** [June 16, 2021, 7:39pm UTC](https://forum.djangoproject.com/t/create-a-new-user-manually/8335/9 "2021-06-16T19:39:06Z")

</div>

I have resolved the creation of records, which turns out not to be that complicated, because you can reference `Profile` through `User` when committing the `.save`.

View:

```auto
@method_decorator(superuser_required(), name='dispatch')		
class ControlProfileCreateView(CreateView):
	#User = get_user_model()
	model = get_user_model()
	template_name = 'bjsc_manage/control/profile_edit.html'
	form_class = ControlProfileForm
	
	def form_valid(self, form):
		username = shortuuid.uuid()
		password = shortuuid.uuid()
		email = form.data['email']
		user = get_user_model().objects.create_user(username=username, email=email, password=password)

		for the_field in self.form_class.Meta.fields:			
			if type(getattr(user, the_field)) == bool:
				if the_field in form.data:
					setattr(user, the_field, True)
				else:
					setattr(user, the_field, False)
			else:
				setattr(user, the_field, form.data[the_field])
		
		for the_field in self.form_class.Meta.profile_fields:			
			if type(getattr(user.profile, the_field)) == bool:
				if the_field in form.data:
					setattr(user.profile, the_field, True)
				else:
					setattr(user.profile, the_field, False)
			else:
				setattr(user.profile, the_field, form.data[the_field])

		account = Account.objects.get(id=self.kwargs['account_id'])
		user.profile.account = account
		
		user.save()
		
		return HttpResponseRedirect(reverse_lazy('control-account-update', kwargs={'pk': self.kwargs['account_id']}))

```

Form:

```auto
class ControlProfileForm(forms.ModelForm):
	#add extra profile fields
	home_phone = PhoneNumberField(label=_('Home phone'), max_length=30, required=False, help_text=_('If outside the UK include country code (eg: "+39", "+353", "+33"…)'))
	work_phone = PhoneNumberField(label=_('Work phone'), max_length=30, required=False, help_text=_('If outside the UK include country code (eg: "+39", "+353", "+33"…)'))
	mobile_phone = PhoneNumberField(label=_('Mobile phone'), max_length=30, required=True, help_text=_('If outside the UK include country code (eg: "+39", "+353", "+33"…)'))
	receive_news = forms.BooleanField(label=_('Receive news'), required=False, initial=True)
	
	class Meta:
		model = get_user_model()
		
		fields = (
			'first_name',
			'last_name',
			'email',
		)
		
		profile_fields = (
			'home_phone',
			'work_phone',
			'mobile_phone',
			'receive_news'
		)

```

So, without having to touch the view, I can add fields in the form. Main complication with this is having to deal with `checkbox` input. It would be nice to be not to have the additional profile fields defined, and then in the `Meta` too. Any tips?

The other complication is that the `User` model does not have a `unique` contraint on the `email` field. While there are lots of tips on working around this, by far the easiest is to stick this in your `models` and run `makemigrations`, `migrate`.

```auto
from django.contrib.auth.models import User
User._meta.get_field('email')._unique = True
User._meta.get_field('email').null = False
User._meta.get_field('email').blank = False

```

In this case I have also fixed `email` so it is not `null` or `blank`.

The remaining issue is editing the `user` and `profile` after creation. If I set up a view to do this I just have the `user` elements populated on the form, the `profile` elements are empty, and if I do fill them in they do not save.

```auto
@method_decorator(superuser_required(), name='dispatch')		
class ControlProfileUpdateView(UpdateView):
	model = get_user_model()
	template_name = 'bjsc_manage/control/profile_edit.html'
	form_class = ControlProfileForm
	success_url = '/control/'

```

How to populate the `profile` elements?

Thanks
