I have created an extended user model that I use on my sign-up page. The two custom models are "Cristin" and a many-to-many field named "Rolle" (the person's role in the organization).
After I added the many-to-many field, I get the following error message: ValueError at /accounts/signup/ –"Userextended: username_that_I_registered_with" needs to have a value for field "id" before this many-to-many relationship can be used.
I have googled for three hours now, and it seems that the solution is to use commit=False on the User ID before saving the model. However, I'm new to Django and Python and have trouble pinpointing where I should write the code and my attempts has so far been unsuccessful. If you can help me solving this problem, please provide the solution through code as well.
My models.py file:
class User(auth.models.User,auth.models.PermissionsMixin):
def __str__(self):
return "@{}".format(self.username)
class Personrolle(models.Model):
id = models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')
persrolle = models.CharField(max_length = 30, verbose_name="Role")
def __str__(self):
return self.persrolle
class Userextended(models.Model):
id = models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')
user = models.OneToOneField(User, on_delete=models.CASCADE)
cristin = models.IntegerField(blank=True, null=True)
rolle = models.ManyToManyField(Personrolle)
def __str__(self):
return self.user.username
...
My forms.py file:
...
from django import forms
from django.contrib.auth.models import User
from accounts.models import Userextended
from accounts.models import Personrolle
from django.contrib.auth.forms import UserCreationForm
class UserCreateForm(UserCreationForm):
cristin = forms.IntegerField(required=False)
rolle = forms.ModelChoiceField(queryset=Personrolle.objects.all())
class Meta():
fields = ('first_name','last_name','username','email','password1','password2')
model = User
labels = {'username': 'Email',
'first_name': 'First name',
'last_name': 'Last name',
'email': 'Confirm email',
'password1': 'Password',
'password2': 'Confirm password',
'cristin': 'Cristin-ID',
'rolle': 'Rolle'}
def save(self, commit=True):
if not commit:
raise NotImplementedError("Can't create User and Userextended without database save")
user = super(UserCreateForm, self).save(commit=True)
user_profile = Userextended(user=user,cristin=self.cleaned_data['cristin'],rolle=self.cleaned_data['rolle'])
user_profile.save()
return user
...
More detailed description of the error
Exception Value: "Userextended: username_that_I_registered_with" needs to have a value for field "id" before this many-to-many relationship can be used.
Exception Location: .../anaconda/envs/myEnv/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py in init, line 830
Python Executable: .../anaconda/envs/myEnv/bin/python
My traceback:
File ".../anaconda/envs/myEnv/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
41. response = get_response(request)
File ".../anaconda/envs/myEnv/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
187. response = self.process_exception_by_middleware(e, request)
File ".../anaconda/envs/myEnv/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
185. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File ".../anaconda/envs/myEnv/lib/python3.6/site-packages/django/views/generic/base.py" in view
68. return self.dispatch(request, *args, **kwargs)
File ".../anaconda/envs/myEnv/lib/python3.6/site-packages/django/views/generic/base.py" in dispatch
88. return handler(request, *args, **kwargs)
File ".../anaconda/envs/myEnv/lib/python3.6/site-packages/django/views/generic/edit.py" in post
217. return super(BaseCreateView, self).post(request, *args, **kwargs)
File ".../anaconda/envs/myEnv/lib/python3.6/site-packages/django/views/generic/edit.py" in post
183. return self.form_valid(form)
File ".../anaconda/envs/myEnv/lib/python3.6/site-packages/django/views/generic/edit.py" in form_valid
162. self.object = form.save()
File "…PROJECT/accounts/forms.py" in save
57. user_profile = Userextended(user=user,cristin=self.cleaned_data['cristin'],rolle=self.cleaned_data['rolle'])
File ".../anaconda/envs/myEnv/lib/python3.6/site-packages/django/db/models/base.py" in __init__
566. _setattr(self, prop, kwargs[prop])
File ".../anaconda/envs/myEnv/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py" in __set__
536. manager = self.__get__(instance)
File ".../anaconda/envs/myEnv/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py" in __get__
513. return self.related_manager_cls(instance)
File ".../anaconda/envs/myEnv/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py" in __init__
830. (instance, self.pk_field_names[self.source_field_name]))
Exception Type: ValueError at /accounts/signup/
Exception Value: "<Userextended: [email protected]>" needs to have a value for field "id" before this many-to-many relationship can be used.
You just need to edit your save method in your form,
def save(self, *args, **kwargs):
if not commit:
raise NotImplementedError("Can't create User and Userextended without database save")
user = super().save(*args, **kwargs)
user_profile = Userextended(user=user, cristin=self.cleaned_data['cristin'])
user_profile.save()
user_profile.rolle.add(self.cleaned_data['rolle'])
user_profile.save()
return user
You need to save your UserExtended
model first, then add the Rolle
instances to the many to many relation.
If you're using DRF you can use the validate method:
instead of this
def create(self, validated_data):
validated_data['slug'] = slugify(validated_data['name'])
return budgets.models.BudgetCategory.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.slug = slugify(validated_data['name'])
instance.save()
return instance
do this
def validate(self, data):
data['slug'] = slugify(data['name'])
return data
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With