Cannot create profile automatically with django-registration - django

I'm new to Django and try to create a userprofile along with any user that registers through django-registration module. Here is my UserProfile module:
class UserProfile(models.Model):
username = models.OneToOneField(User)
bio = models.CharField(max_length=500)
location = models.CharField(max_length=20)
User.profile = property(lambda u:UserProfile.objects.get_or_create(username=u)[0])
def __unicode__(self):
return self.user.username
I have also this in settings.py
AUTH_PROFILE_MODULE = 'userprofile.UserProfile'
When users are created they are refered to this view to fill their profile form:
def add_profile(request):
if request.method == 'POST':
form = UserProfileForm(request.POST,request.FILES)
if form.is_valid():
f = form.save(commit = False)
f.username_id= request.user.id
form.save()
return render_to_response('userprofile/ok.html',
context_instance=RequestContext(request))
else:
print form.errors
else:
form = UserProfileForm()
return render_to_response('userprofile/add_profile.html', {'form': form},
context_instance=RequestContext(request))
but when they submit the form, they get this error:
TypeError at /profile/add/sara/
add_profile() got an unexpected keyword argument 'username'
I know that there are many similar questions on SO and I tried many of the suggestions but none work for me. So appreciate your hints

Related

Django. Populate user name or ID when user saving a model from web pages

My UserImg Model has a user field that has editable=False.
I want this field to be automatically filled in with the user name when the user is saved from web page.
model.py
def upload_myimg_path(instance, filename):
return 'documents/{0}/{1}'.format(instance.created_by.username, filename)
class UserImg(models.Model):
user = models.ForeignKey(User, verbose_name=_('Created by'), on_delete=models.CASCADE, editable=False, null=True, blank=True)
name = models.CharField(max_length=100, default='')
image = models.ImageField(upload_to=upload_myimg_path, verbose_name=_('File'))
def __str__(self):
return str(self.user)
forms.py
class UserImgForm(forms.ModelForm):
class Meta:
model = UserImg
fields = '__all__'
views.py
def createuserimg(request):
if request.method == 'POST':
form = UserImgForm(request.POST or None)
if form.is_valid():
form.save()
return redirect('/accounts/users')
else:
return redirect('/accounts/')
else:
form = UserImgForm
return render(request, 'accounts/user_form.html', {'form': form})
Update your view function to include current logged in user and make use of #login_required decorator to ensure that only logged in users can access this view :
from django.contrib.auth.decorators import login_required
#login_required
def createuserimg(request):
if request.method == 'POST':
form = UserImgForm(request.POST, request.FILES)
if form.is_valid():
obj = form.save(commit=False) # <-- commit=False does not save to database
obj.user = request.user # <-- this allows you to specify the user for your post
obj.save()
return redirect('/accounts/users')
# if the form did not validated, stay on the same page to display errors to your user
else:
form = UserImgForm()
return render(request, 'accounts/user_form.html', {'form': form})
correct answer commit=False allows you to modify the resulting object before it is actually saved to the database. It`s works for me.
Thank you very much for your help
from django.contrib.auth.decorators import login_required
#login_required
def createuserimg(request):
if request.method == 'POST':
form = UserImgForm(request.POST, request.FILES)
if form.is_valid():
link = form.save(commit=False)
link.user = request.user
link.save()
return redirect('/accounts/users')
# if the form did not validated, stay on the same page to display errors to your user
else:
form = UserImgForm()
return render(request, 'accounts/user_form.html', {'form': form})

Seller object has no attribute profile

I am developing a django website where seller can open their accounts and update their profiles,so while while creating seller account I want to create a profile objects,my code of user registration form is given below,
class UserRegisterForm(UserCreationForm):
email = forms.EmailField(required=True)
date_of_birth = forms.DateField(required=True,
input_formats=settings.DATE_INPUT_FORMATS)
class Meta:
model = User
fields = ['username', 'email', 'date_of_birth', 'password1',
'password2']
def save(self, commit=True):
date_of_birth = self.cleaned_data.pop('date_of_birth', None)
user = super(UserRegisterForm, self).save(commit)
seller = Seller.objects.create(name=user.username,
date_of_birth=date_of_birth, created_by=user)
profile = Profile.objects.create(seller=seller)
return user
my code for become_seller in views.py is,
def become_seller(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
if form.is_valid():
form.save()
return redirect('seller_dashboard')
else:
form = UserRegisterForm()
return render(request, 'become_seller.html',{'form':form})
all of this is working fine,but when I go for edit profile,my code for edit in views.py is,
#login_required
def edit(request):
if request.method == 'POST':
profile_form =
ProfileEditForm(instance=request.user.seller.profile,
data=request.POST, files=request.FILES)
if profile_form.is_valid():
profile_form.save()
else:
profile_form =
ProfileEditForm(instance=request.user.seller.profile)
return render(request, 'profile_edit.html',
{'profile_form':profile_form})
so,while working for this I found the following error message
AttributeError at /seller/edit/ 'Seller' object has no attribute 'profile'
can anyone help me to sort out this issue please
try register also ListingAdmin like admin.site.register(Listing, ListingAdmin) instead of trying to register only model class
ListingAdmin is not registered in admin.site.register()
The issue is solved by using related_name = profile

Django - cannot assign - must be an instance

I tried phrasing this question recently and got totally confused. I've extended the default user model with this in my models.py:
class Biography(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
biography = models.TextField(max_length=500, blank=True,default='Details')
I've included this in the forms.py:
class EditProfileForm(forms.Form):
first_name = forms.CharField(label='First Name')
last_name = forms.CharField(label='Last Name')
biography = forms.CharField(label='Biography', widget=Textarea(attrs={'rows': 5}))
I have a view to edit the profile and want to add "biography" to it, but have absolutely no clue where to start. Here's the view:
def edit_profile(request):
user = request.user
products = Product.objects.filter(user=user)
form = EditProfileForm(request.POST or None, initial={'first_name':user.first_name, 'last_name':user.last_name})
if request.method == 'POST':
if form.is_valid():
user.first_name = request.POST['first_name']
user.last_name = request.POST['last_name']
user.save()
return render(request, 'profile.html', {'user':user, 'products':products})
context = {"form": form}
return render(request, "edit_profile.html", context)
I tried to replicate what is already there with this:
def edit_profile(request):
user = request.user
products = Product.objects.filter(user=user)
biography = Biography(user=user)
form = EditProfileForm(request.POST or None, initial={'first_name':user.first_name, 'last_name':user.last_name, 'biography':user.biography})
if request.method == 'POST':
if form.is_valid():
user.first_name = request.POST['first_name']
user.last_name = request.POST['last_name']
user.biography = request.POST['biography']
user.save()
return render(request, 'profile.html', {'user':user, 'products':products})
context = {"form": form}
return render(request, "edit_profile.html", context)
I definitely missed the point somehow. The last time I asked this question I was somewhat chastised for not knowing how to solve it. In all honesty I'm really new to Django and am amazed I got this far, but I'm stuck. I 'think' I need to create an instance but am not sure how.
What you should do differently:
Create Biography instance if it does not exist, or get from db.
Instantiate separate forms for different request methods
Use cleaned_data as input validation is one of the main purposes of forms
Always redirect after POST
Save User and Biography instances separately
And you don't need related products in form view. If only you are not going to somehow update them here.
For example:
def edit_profile(request):
user = request.user
biography, created = Biography.objects.get_or_create(user=user)
form = EditProfileForm(initial={
'first_name': user.first_name,
'last_name': user.last_name,
'biography': biography.biography
})
if request.method == 'POST':
form = EditProfileForm(data=request.POST)
if form.is_valid():
user.first_name = form.cleaned_data['first_name'] # use cleaned_data
user.last_name = form.cleaned_data['last_name']
biography.biography = form.cleaned_data['biography']
biography.save() # save Biography object
user.save() # save User object
return redirect(biography) # always redirect after successful POST. In this case Biography must have get_absolute_url() method
context = {'form': form}
return render(request, 'edit_profile.html', context)
Read more in documentation.
user.biography is an instance of Biography model, so what you should do here is get that instance and edit its attributes, like this:
bio = user.biography
bio.biography = request.POST['biography']
bio.save()

ValueError at /new_topic/ Cannot assign "<SimpleLazyObject: <django......>": "Topic.owner" must be a "User" instance

*Any time i insert data the above error occurred! *
# my views
def new_topic(request):
"""Add a new topic."""
if request.method != 'POST':
# No data submitted; create a blank form.
form = TopicForm()
else:
# POST data submitted; process data.
form = TopicForm(request.POST or None, request.FILES or None)
if form.is_valid():
new_topic = form.save(commit=False)
new_topic.owner = request.user #this where i think, i'm messing up!
new_topic.save()
return HttpResponseRedirect(reverse('learning_logs:topics'))
context = {'form': form}
return render(request, 'learning_logs/new_topic.html', context)
*model representing each Topic *
from django.contrib.auth.models import User
def upload_location(instance, filename):
return "%s/%s" %(instance.id, filename)
class Topic(models.Model):
"""A topic the user is learning about"""
text = models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)
image = models.ImageField()
height_field = models.IntegerField(default=0)
width_field = models.IntegerField(default=0)
owner = models.ForeignKey(User)
def __str__(self):
"""Return a string representation of the model."""
return self.text
Any help please!
Setting new_topic.owner = request.user should be fine if the user is logged in. However if the user is not logged in, then trying to assign an anonymous user would cause problems.
You can prevent this by using the login_required decorator, so that only logged-in users can access the view.
#login_required
def new_topic(request):
...

RelatedObjectDoesNotExist while using custom User model in Django

I have an account app in which I have created a Profile model by extending the custom user model. I have created a view which allows the user to edit his profile info and also I have corresponding UserEditForm and ProfileEditForm. As of now, no user has a profile so when I open the edit form I get an error: "RelatedObjectDoesNotExist at /account/edit/".
" User has no profile "
I tried to create the profile using admin , then the error goes away. How can I correct this in my views.py file.
views.py
#login_required
def edit(request):
if request.method =='POST':
user_form = UserEditForm(instance=request.user,data=request.POST)
profile_form = ProfileEditForm(instance=request.user.profile,data=request.POST,files=request.FILES)
if user_form.is_valid() and profile_form.is_valid():
user_form.save()
profile_form.save()
messages.success(request,'Profile updated successfully')
else:
messages.error(request,'Error updating your profile')
else:
user_form = UserEditForm(instance=request.user)
profile_form = ProfileEditForm(instance=request.user.profile)
context = {
'user_form':user_form,
'profile_form': profile_form
}
return render(request,'account/edit.html',context)
models.py
CATEGORY_CHOICES = (
('SA','School Admin'),
('T','Teacher'),
('S','Student'),
('P','Parent'),
)
class Profile(models.Model):
eduser = models.OneToOneField(settings.AUTH_USER_MODEL)
photo = models.ImageField(upload_to='users/%Y/%m/%d',blank=True)
about_me = models.TextField(max_length=200,blank=True)
category = models.CharField(max_length=1,choices=CATEGORY_CHOICES,blank=True)
date_of_birth = models.DateField(blank=True,null=True)
def __str__(self):
return 'Profile for user {}'.format(self.eduser.username)
forms.py
class UserEditForm(forms.ModelForm):
class Meta:
model = User
fields = ('first_name','last_name','email')
class ProfileEditForm(forms.ModelForm):
class Meta:
model = Profile
fields = ('category','date_of_birth','about_me','photo')
You need to catch the error. You can do it at the top of the function:
try:
profile = request.user.profile
except ObjectDoesNotExist:
profile = Profile(user=request.user)
and pass that profile into the ProfileEditForm in both if branches.