I'm building a fake social network for a project in Django. I've implemented allowing users to 'follow' others if desired (or none at all if they choose). But so far every time I create a user, that user automatically 'follows' all other users in the database. I do not know how to fix this.
Here is the model:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
bio = models.CharField(max_length=200, blank=True)
followers = models.ManyToManyField('Profile',
related_name="followers_profile",
blank=True, symmetrical=False)
following = models.ManyToManyField('Profile',
related_name="following_profile",
blank=True, symmetrical=False)
avatar_thumbnail = ProcessedImageField(upload_to='profile_images',
processors=[ResizeToFill(320, 320)],
format='JPEG',
options={'quality': 40},
blank=True)
feed_type = models.CharField(max_length=8, choices=GENDER_CHOICES,
default='Both')
# #receiver(post_save, sender=User)
# def create_user_profile(sender, instance, created, **kwargs):
# if created:
# Profile.objects.create(user=instance)
#
# #receiver(post_save, sender=User)
# def save_user_profile(sender, instance, **kwargs):
# instance.profile.save()
def get_number_of_followers(self):
if self.followers.count():
return self.followers.count()
else:
return 0
def get_number_of_following(self):
if self.following.count():
return self.following.count()
else:
return 0
def __str__(self):
return self.user.username
Here is the View that constructs User and Profiles and the form that processes user creation data:
def signup(request):
form = UserCreateForm()
if request.method == 'POST':
form = UserCreateForm(request.POST)
if form.is_valid():
form.save()
user = User.objects.get(username=request.POST['username'])
user_profile = Profile(user=user)
user_profile.save()
new_user = authenticate(username=form.cleaned_data['username'],
password=form.cleaned_data['password1'])
login(request,new_user)
return redirect('index')
return render(request, 'userapp/signup.html', {
'form': form
})
Here's the UserCreationForm:
class UserCreateForm(UserCreationForm):
email = forms.EmailField(required=True)
class Meta:
model = User
fields = {"username", "email", "password1","password2"}
def save(self, commit=True):
user = super(UserCreateForm, self).save(commit=False)
user.email =self.cleaned_data["email"]
if commit:
user.save()
return user
Related
I have this sign up form where I am taking values from the user about his username and password and also his proile. I have separately created two forms UserForm and ProfileForm. When the user is signing up for his account how do I connect profile to the user.
This is what I have
forms.py
class SignUpForm(UserCreationForm):
email = forms.EmailField(required=True,
label='Email',
error_messages={'exists': 'Oops'})
class Meta:
model = User
fields = ("username", "email", "password1", "password2")
def save(self, commit=True):
user = super(SignUpForm, self).save(commit=False)
user.email = self.cleaned_data["email"]
# user.status = self.cleaned_data["status"]
if commit:
user.save()
return user
class ProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['contact', 'whatsapp', 'gender', 'avatar']
models.py
class Profile(models.Model):
STATUS_CHOICES = (
(1, ("Permanent")),
(2, ("Temporary")),
(3, ("Contractor")),
(4, ("Intern"))
)
GENDER_CHOICES = (
(1, ("Male")),
(2, ("Female")),
(3, ("Not Specified"))
)
PAY_CHOICES = (
(1, ("Fixed")),
(2, ("Performance Based")),
(3, ("Not Assigned")),
)
user = models.OneToOneField(User, on_delete=models.CASCADE)
emp_type = models.IntegerField(choices=STATUS_CHOICES, default=1)
start_date = models.DateField(default=timezone.now)
end_date = models.DateField(null=True, blank=True)
user_active = models.BooleanField(default=True)
contact = models.CharField(max_length=13, blank=True)
whatsapp = models.CharField(max_length=13, blank=True)
gender = models.IntegerField(choices=GENDER_CHOICES, default=3)
pay_type = models.IntegerField(choices=PAY_CHOICES, default=3)
pay = models.IntegerField(default=0)
avatar = models.ImageField(upload_to='users/images', default='users/images/default.jpg')
title = models.CharField(max_length=25, unique=False)
#manager_username = models.ForeignKey(User, blank=True, null=True, to_field='username',related_name='manager_username', on_delete=models.DO_NOTHING)
def __str__(self):
return self.user.username
#receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.profile.save()
views.py
def createAccount(request):
if(request.method == 'POST'):
u_form = SignUpForm(request.POST) # fill it with user details
p_form = ProfileForm(request.POST, request.FILES)
if u_form.is_valid() and p_form.is_valid():
u_form.save()
profile = p_form.save(commit=False)
profile.user = u_form.user
p_form.save()
messages.success(request, f'Account Updated')
return redirect('createAccount')
return render(request, 'mainapp/createAccount.html')
When I am creating a new user with his profile information. I am getting an error
AttributeError at /create
'SignUpForm' object has no attribute 'user'
Request Method: POST
Request URL: http://localhost:8000/create
Django Version: 2.1
Exception Type: AttributeError
Exception Value:
'SignUpForm' object has no attribute 'user'
Exception Location: C:\Users\Himanshu Poddar\Desktop\ATG IInternship\INTRANET\atg-intranet\Intranet\users\views.py in createAccount, line 23
Python Executable: C:\Users\Himanshu Poddar\AppData\Local\Programs\Python\Python36-32\python.exe
Python Version: 3.6.2
I think this is the part where I am going wrong, My question is how do I connect the user to his profile while signing up.
u_form.save()
profile = p_form.save(commit=False)
profile.user = u_form.user
How can I resolve this?
profile.user = u_form.user is indeed causing problems here.
You try to access the user created by the SignupForm, but it is not set as a property of the form, but returned by the save method.
To fix this, you'll need to capture the user created by the SignUpForms's save method. Change the block where you create the user and profile to this:
...
user = u_form.save()
profile = p_form.save(commit=False)
profile.user = user
...
I have a site where I need to update my UserProfileInfo model, which is how I am extending the User model.
However, whenever I save the User model, the UserProfileInfo does not, meaning in the admin, the User model has the first_name and last_name variables filled out, however the UserProfileInfo does not.
Here is some code.
MODELS.PY
class UserProfileInfo(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,max_length=30)
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
description = models.TextField(max_length=150)
website = models.URLField(max_length=200,blank=True,null=True)
image = ProcessedImageField(upload_to='profile_pics',
processors=[ResizeToFill(150, 150)],
default='default.jpg',
format='JPEG',
options={'quality': 60})
joined_date = models.DateTimeField(blank=True,null=True,default=timezone.now)
verified = models.BooleanField(default=False)
moderator = models.BooleanField(default=False)
tags = TaggableManager()
def __str__(self):
return f'{self.user.username} Profile'
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
#receiver(post_save, sender=User)
def create_or_update_user_profile(sender, instance, created, **kwargs):
if created:
UserProfileInfo.objects.create(user=instance)
else:
instance.userprofileinfo.save()
In the receiver, I want to update both, but it is not.
FORMS.PY
class UserProfileInfoForms(UserCreationForm):
email = forms.EmailField()
class Meta():
model = User
fields = ['username','first_name','last_name','email']
class UserUpdateForm(forms.ModelForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username','email']
class ProfileUpdateForm(forms.ModelForm):
class Meta:
model = UserProfileInfo
fields = ['image','description','tags','website']
And finally here is the view
VIEWS.PY
#login_required
def profile_update(request):
if request.method == 'POST':
u_form = UserUpdateForm(request.POST, instance=request.user)
p_form = ProfileUpdateForm(request.POST,
request.FILES,
instance=request.user.userprofileinfo)
if u_form.is_valid() and p_form.is_valid():
u_form.save()
p_form.save()
messages.success(request, f'Your account has been updated!')
return redirect('mainapp:profile')
else:
u_form = UserUpdateForm(instance=request.user)
p_form = ProfileUpdateForm(instance=request.user.userprofileinfo)
context = {
'u_form': u_form,
'p_form': p_form
}
return render(request,'mainapp/profile_update.html',context)
So here, I'm saving both the UserUpdateForm and ProfileUpdateForm
And finally here are my signals
SIGNALS.PY
#receiver(post_save, sender=User)
def create_or_update_user_profile(sender, instance, created, **kwargs):
if created:
UserProfileInfo.objects.create(user=instance)
else:
instance.userprofileinfo.save()
#receiver(post_save,sender=User)
def save_profile(sender,instance,**kwargs):
instance.userprofileinfo.save()
I have also included my signals.py in the apps.py file, so it is working.
So how can I make it so that the UserProfileInfo model is updated when the User model is updated? I am having trouble figuring this out, so any help would is appreciated
def profile_update(request):
if request.method == "POST":
if u_form.is_valid() and p_form.is_valid():
p_form.instance.user=request.user
p_form.instance.first_name=request.user.first_name
p_form.instance.last_name=request.user.last_name
p_form.instance.email=request.user.email
u_form.save()
p_form.save()
return redirect('mainapp:profile')
context = {
'u_form': u_form,
'p_form': p_form,
}
return render(request, 'mainapp/profile_update.html', context)
I am trying to submit 2 forms at a time to create my student user in Django. I have been struggling for a while now, but I think I'm finally closing to an end on how to manage 2 forms at a time for my users to register. But when I fill in the data from my view, I get the error:
[Errno 22] Invalid argument: "C:\\Users\\danny\\Desktop\\Projects\\bachelor_thesis\\eve\\templates\\{'form1': <UserForm bound=False, valid=Unknown, fields=(username;email;first_name;last_name;password)>, 'form2': <StudentForm bound=False, valid=Unknown, fields=(phone;student_ID;photo)>}"
Here are my files:
#csrf_protect
def student_register(request):
if request.method == 'POST':
form1 = UserForm(request.POST, prefix="user")
form2 = StudentForm(request.POST, prefix="profile")
if form1.is_valid() and form2.is_valid():
# create initial entry for user
username = form1.cleaned_data["username"]
password = form1.cleaned_data["password"]
new_user = User.objects.create_user(username, password)
new_user.save()
# create entry for UserProfile (extension of new_user object)
profile = form2.save(commit=False)
profile.user = new_user
profile.save()
return HttpResponseRedirect("index")
else:
form1 = UserForm(prefix="user")
form2 = StudentForm(prefix="profile")
c = {
'form1': form1,
'form2': form2,
}
c.update(request)
return render(request, "student_signup_form.html", c)
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ('username', 'email', 'first_name', 'last_name', 'password')
class StudentForm(forms.ModelForm):
class Meta:
model = Student
fields = ('phone', 'student_ID', 'photo')
class User(AbstractUser):
pass
class Student(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
student_ID = models.CharField(unique=True, max_length=14,
validators=[RegexValidator(regex='^.{14}$',
message='The ID needs to be 14 characters long.')])
photo = models.ImageField(upload_to='students_images')
phone = models.CharField(max_length=15, )
def __str__(self):
return self.user.username
#receiver(post_save, sender=User)
def create_user_student(sender, instance, created, **kwargs):
if created:
Student.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_user_student(sender, instance, **kwargs):
instance.profile.save()
Also, when I open registration form, password is seeable. Also, how do I add a confirmation password fields? Thanks.
Here is the traceback: https://pastebin.com/b90muPZY
This issue is bothering me for a while.
I have form.py with class RegistrationForm and everything works fine but the extra details like email, first and last name, roles is not saved to my account/User profiles but first and last name + emails is saved under AUTHENTICATION AND AUTHORIZATION/Users
I been trying to figure our if I made some mix up with model, form or views.
What could be the problem? Using python 3 with latest django
2nd
3rd
Models.py
class UserProfile(models.Model):
STUDENT = 1
TOURIST = 2
BUSINESS = 3
ADMIN = 4
ROLE_CHOICES = (
(STUDENT, 'Student'),
(TOURIST, 'Tourist'),
(BUSINESS, 'Business'),
(ADMIN, 'Admin'),
)
user = models.OneToOneField(User, on_delete=models.CASCADE)
# first_name = models.CharField(max_length=100, default='')
# last_name = models.CharField(max_length=100, default='')
email = models.EmailField()
phone = models.IntegerField(default=0)
image = models.ImageField(upload_to='image_profile', blank=True)
role = models.PositiveSmallIntegerField(choices=ROLE_CHOICES, null=True, blank=True)
# admin = UserProfileManager()
def __str__(self):
return self.user.username
def create_profile(sender, **kwargs):
if kwargs['created']:
user_profile = UserProfile.objects.create(user=kwargs['instance'])
post_save.connect(create_profile, sender=User)
forms.py
ROLES = ((0, 'Student'), (1, 'Tourist'), (2, 'Business'))
class RegistrationForm(UserCreationForm):
email = forms.EmailField(required=True)
role = forms.ChoiceField(choices=ROLES)
class Meta:
model = User
fields = (
'username',
'first_name',
'last_name',
'email',
'role',
'password1',
'password2'
)
def save(self, commit=True):
user = super(RegistrationForm, self).save(commit=False)
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.role = self.cleaned_data['role']
user.email = self.cleaned_data['email']
if commit:
user.save()
return user
views.py
def register(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
form.save()
messages.success(request, 'Your account has been created!')
return redirect(reverse('city:home'))
else:
form = RegistrationForm()
args = {'form': form}
return render(request, 'account/register_form.html', args)
Admin.py
class UserProfileAdmin(admin.ModelAdmin):
list_display = ('user', 'role', 'email')
def user_info(self, obj):
return obj.role
def get_queryset(self, request):
queryset = super(UserProfileAdmin, self).get_queryset(request)
queryset = queryset.order_by('email')
return queryset
role.short_description = 'User Type'
admin.site.register(UserProfile, UserProfileAdmin)
By given screen shots i think you are using allauth library. If you want to use allauth and modify user model then you have to import AbstractUser class of allauth
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
phone = models.CharField(_('Telephone'), blank=True, max_length=20)
address = models.CharField(_('Address'), blank=True, max_length=255)
When my users create a profile, their image gets saved fine but when they update it it doesn't get saved. I also don't know how to pull the pic so that they can see it before updating it.
This is the form:
class UpdateProfileForm(forms.ModelForm):
city = models.ForeignKey(City)
class Meta:
model = UserProfile
fields = ('city', 'profilepic')
def save(self, commit=True):
profile = super(UpdateProfileForm, self).save(commit=False)
if commit:
profile.save()
return profile
This is the view:
def updateprofile(request):
if request.method == 'POST':
update_user_form = UpdateUserForm(request.POST, instance=request.user)
update_profile_form = UpdateProfileForm(request.POST, request.FILES, instance=request.user.profile)
if update_user_form.is_valid() and update_profile_form.is_valid():
update_user_form.save()
'''************************************************'''
profile = update_profile_form.save(commit=False)
if 'profilepic' in request.FILES:
profile.profilepic = request.FILES['profilepic']
profile.save()
'''************************************************'''
return HttpResponseRedirect(reverse('index'))
else:
update_user_form = UpdateUserForm(instance=request.user)
update_profile_form = UpdateProfileForm(instance=request.user.profile)
return render(request, 'updateprofile.html', {'update_user_form' : update_user_form, 'update_profile_form' : update_profile_form})
And this is model:
# this is model for user
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='profile')
hobbies = models.ManyToManyField(Hobby)
languages = models.ManyToManyField(Language)
profilepic = models.ImageField(upload_to='static/images/Profile Pictures', blank=True)
city = models.ForeignKey(City)
slug = models.SlugField(unique=True)
average_rating = models.IntegerField(default=0)
ratings_count = models.IntegerField(default=0)
def save(self, *args, **kwargs):
# Uncomment if you don't want the slug to change every time the name changes
self.slug = slugify(self.user.username)
super(UserProfile, self).save(*args, **kwargs)
def __unicode__(self):
return self.user.username
Thank you.
Add request.FILES to the form:
update_profile_form = UpdateProfileForm(request.POST, request.FILES,
instance=request.user)
By default django doesn't includes files in request.POST
Also, I think instance for UserProfile model should be request.user.profile instead of request.user or am I missing something here?
Follow instructions from django-docs