I am new to django and I started a new project. shortly, I want to register different type of users (Teacher, Student, Stuff) with their profile picture. I made a one to one field from user to profile and below is my code and I get the following error. if you have any suggestion for my registration purpose, I want to register a different type of user with a profile picture.
models.py
from django.db import models
from django.contrib.auth.models import User,AbstractUser
from django.conf import settings
from django.dispatch import receiver
from django.db.models.signals import post_save
class User(AbstractUser):
USER_TYPE_CHOICES = (
(1,'Student'),
(2,'Teacher'),
(3,'Stuff')
)
profile = models.OneToOneField(on_delete=models.CASCADE, related_name='user')
user_type = models.PositiveSmallIntegerField(choices=USER_TYPE_CHOICES)
class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL,on_delete=models.CASCADE, related_name='profile')
photo = models.ImageField(upload_to='users/%Y/%m/%d/')
def __str__(self):
return 'Profile {}'.format(self.user.username)
its the form
from django import forms
from django.contrib.auth.models import User
from .models import Profile
class UserCreationForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput, label='Password')
password2 = forms.CharField(widget=forms.PasswordInput, label='Repeat Password')
class Meta:
model = User
fields = ('username', 'first_name', 'last_name')
def clean_password(self):
cd = self.cleaned_data
if cd['password']!=cd['password2']:
raise forms.ValidationError('password no match')
return cd['password2']
class ProfileCreationForm(forms.ModelForm):
class Meta:
model = Profile
fields = ('photo',)
its my view module
from django.shortcuts import render
from .forms import ProfileCreationForm, UserCreationForm
from .models import Profile
from django.http import HttpResponse
def sign_up(request):
if request.method == 'POST':
user_form = UserCreationForm(instance=request.user,data=request.POST)
profile_form = ProfileCreationForm(instance=request.user.profile,data=request.POST,
files=request.FILES)
if user_form.is_valid() and profile_form.is_valid():
new_user = user_form.save(commit=False)
new_user.set_password(user_form.cleaned_data['password'])
new_user.save()
Profile.objects.create(user=new_user)
return HttpResponse('user created')
else:
user_form = UserCreationForm()
profile_form = ProfileCreationForm()
return render(request, '',{'user_form':user_form, 'profile_form':profile_form})
here is the error:
Traceback (most recent call last):
File "manage.py", line 15, in <module>
execute_from_command_line(sys.argv)
File "C:\Users\Mahdi\AppData\Local\Programs\Python\Python37\lib\site-packages\django\core\management\__init__.py", line 381, in execute_from_command_line
utility.execute()
File "C:\Users\Mahdi\AppData\Local\Programs\Python\Python37\lib\site-packages\django\core\management\__init__.py", line 357, in execute
django.setup()
File "C:\Users\Mahdi\AppData\Local\Programs\Python\Python37\lib\site-packages\django\__init__.py", line 24, in setup
apps.populate(settings.INSTALLED_APPS)
File "C:\Users\Mahdi\AppData\Local\Programs\Python\Python37\lib\site-packages\django\apps\registry.py", line 112, in populate
app_config.import_models()
File "C:\Users\Mahdi\AppData\Local\Programs\Python\Python37\lib\site-packages\django\apps\config.py", line 198, in import_models
self.models_module = import_module(models_module_name)
File "C:\Users\Mahdi\AppData\Local\Programs\Python\Python37\lib\importlib\__init__.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
File "<frozen importlib._bootstrap>", line 983, in _find_and_load
File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 728, in exec_module
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File "C:\Users\Mahdi\PycharmProjects\MyProject\accounts\models.py", line 7, in <module>
class User(AbstractUser):
File "C:\Users\Mahdi\PycharmProjects\MyProject\accounts\models.py", line 13, in User
profile = models.OneToOneField(on_delete=models.CASCADE, related_name='user')
TypeError: __init__() missing 1 required positional argument: 'to'
In your model you forgot to specify to which model the OneToOneField
of the User
model should point (a Profile
), since that profile is defined later in the Python file, you can not use an identifier, you can however use a string literal that contains the name of the model:
class User(AbstractUser):
USER_TYPE_CHOICES = (
(1,'Student'),
(2,'Teacher'),
(3,'Stuff')
)
profile = models.OneToOneField('Profile', on_delete=models.CASCADE, related_name='user')
user_type = models.PositiveSmallIntegerField(choices=USER_TYPE_CHOICES)
You will need to make migrations, and migrate in order to add a table that corresponds to your model in the database.
Since you reference to the Profile
, that means you will need to first construct a Profile
before saving the User
(since otherwise the profile
will be NULL
, which is not allowed here):
from django.shortcuts import render
from .forms import ProfileCreationForm, UserCreationForm
from .models import Profile
from django.http import HttpResponse
def sign_up(request):
if request.method == 'POST':
user_form = UserCreationForm(instance=request.user,data=request.POST)
profile_form = ProfileCreationForm(instance=request.user.profile,data=request.POST,
files=request.FILES)
if user_form.is_valid() and profile_form.is_valid():
profile = profile_form.save()
new_user = user_form.save(commit=False)
new_user.set_password(user_form.cleaned_data['password'])
new_user.profile = profile
new_user.save()
return HttpResponse('user created')
else:
user_form = UserCreationForm()
profile_form = ProfileCreationForm()
return render(request, 'my_template.html',{'user_form':user_form, 'profile_form':profile_form})
You also forgot to specify the template. Furthermore it is advicable to return a redirect(..)
to a view, since otherwise if the user refreshes the browser, a second POST request will be made, and this can thus trigger creating another user.