How to automatically get user in django admin through form - python

I have a form in my django website where the user requests coins and the information is sent to the admin for me to process. I want to automatically get the user who filled the form without them doing it themselves.
Here's the model.py file:
class Requestpayment (models.Model):
username= models.ForeignKey(User, on_delete= models.CASCADE, null=True)
useremail= models.CharField(max_length=100)
accountmail= models.CharField(max_length=100)
accountphonenumber=models.CharField(max_length=15)
coinsrequested=models.ForeignKey(Requestamount, on_delete= models.SET_NULL, null=True)
created= models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.accountmail
the forms.py:
class Requestpaymentform (ModelForm):
class Meta:
model = Requestpayment
fields = '__all__'
and the views.py:
#login_required(login_url='login')
def redeemcoins (request):
form = Requestpaymentform
if request.method =='POST':
form = Requestpaymentform(request.POST)
if form.is_valid():
form = form.save(commit=False)
username = request.user
form.save()
return redirect ('home')
I am pretty sure something is wrong but i don't know what it is (I'm very new at django) anyway the form always shows all the users in the website for the current user to pick who they are.
redeem coins page
I also tried excluding that part of the form but it didn't work it just shows up empty in the admin.
thank you.

You need to assign it to the instance wrapped in the form, so:
#login_required(login_url='login')
def redeemcoins(request):
form = Requestpaymentform()
if request.method == 'POST':
form = Requestpaymentform(request.POST)
if form.is_valid():
form.instance.username = request.user
form.save()
return redirect('home')
# …
It makes more sense however to name this field user than username. In the model you can also make the username field non-editable, such that it does not appear in the form:
from django.conf import settings
class Requestpayment(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL, editable=False, on_delete=models.CASCADE
)
# …
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.

When you use username= models.ForeignKey(User, on_delete= models.CASCADE, null=True), Django add a field named user_id in your database which allow django to find User object for Requestpayment.
You can use user_id field to add a User object in Requestpayment.
You don't need to pass username field in your fields list if you want to get user in view.
class Requestpaymentform (ModelForm):
class Meta:
model = Requestpayment
#fields = '__all__'
fields = ['useremail',
'accountmail',
'accountphonenumber',
'coinsrequested',
'created']
Now do this to get user in your view.
#login_required(login_url='login')
def redeemcoins(request):
form = Requestpaymentform()
if request.method == 'POST':
form = Requestpaymentform(request.POST)
if form.is_valid():
requestpayment = form.save(commit=False)
requestpayment.user_id = request.user.id
requestpayment.save()
return redirect('home')
And it's great to use user instead username because it's a User object and not a simple field.
Please for my English !!!

Related

How can I save a django Model Form in views for the logged in user

I am working on a project in Django where I have an Education(models.Model) with a OneToOneField to User Model as shown below:
class Education(models.Model):
applicant = models.OneToOneField(User, on_delete=models.CASCADE, null = True)
qualification = models.CharField(max_length=60, choices=INSTITUTE, blank=True, null=True)
institution = models.CharField(max_length=40, null=True)
reasons = models.CharField(max_length=100, null=True)
matnumber = models.CharField(max_length=255, null=True)
And a forms.ModelForm as shown below:
class AddEducationForm(forms.ModelForm):
class Meta:
model = Education
fields = ['qualification','instition', 'matnumber', 'reasons','refphone']
In my views.py file I want to save this AddEducationForm for the logged in user. Below is what I have tried but it is not saving but showing success message of save.
def AddEducation(request):
if request.method == 'POST':
form = AddEducationForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
messages.success(request, 'Education Added Successfully')
return redirect('user-bank')
else:
form = AddEducationForm()
context = {
'form':form,
}
return render(request, 'user/add_education.html', context)
The system is displaying the success message that the form has been saved for the logged in user but in reality it is not (when checked using Django Admin Login).
Someone should kindly help out with the solution to this problem. Remember each logged in user would save only one Education Form record. Thank in anticipation.
You add it to the instance of the form, so:
from django.contrib.auth.decorators import login_required
#login_required
def add_education(request):
if request.method == 'POST':
form = AddEducationForm(request.POST, request.FILES)
if form.is_valid():
form.instance.applicant = request.user
form.save()
messages.success(request, 'Education Added Successfully')
return redirect('user-bank')
else:
form = AddEducationForm()
context = {
'form':form,
}
return render(request, 'user/add_education.html', context)
Note: You can limit views to a view to authenticated users with the
#login_required decorator [Django-doc].
Note: Functions are normally written in snake_case, not PascalCase, therefore it is
advisable to rename your function to add_education, not addEducation.
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.

Django - how to make a CloudinaryField not mandatory and how to allow user to delete their uploaded image?

Hej, I am just beginning to learn Django and I want my users to be able to upload a profile picture, so I extended the User model with a Profile model, however, so far I have not figured out how to make the image upload non-mandatory. And when the user has added a picture, I would like them to be able to remove it as well.
Screenshot - Not able to Submit without adding file
Screenshot - Not able to remove the added file
models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField()
profile_image = CloudinaryField('profile_image')
def __str__(self):
return self.user.username
forms.py
class ProfileForm(ModelForm):
class Meta:
model = Profile
fields = ('bio', 'profile_image',)
views.py
#login_required(login_url='login')
def createPost(request):
form = PostForm()
if request.method == "POST":
form = PostForm(request.POST, request.FILES)
# request.FILES necessary so that file is submitted
# also required to add enctype to the form
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.save()
return redirect('home')
context = {'form': form}
return render(request, 'my8gag/post_form.html', context)
Couldn't find anything about this in the documentation or here on SO, so would appreciate any kind of help/hints! Thanks in advance.
Allow the field to be null
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField()
profile_image = CloudinaryField('profile_image', null=True, default=None, blank=True)
def __str__(self):
return self.user.username

Django, link a model field with an admin model field with ForeignKey

I'm trying to link a "normal" model field with an admin model field, for example I have a table "Post" and I want to add the admin username as a ForeignKey to the field "Author" of the table Post.
I mean :
class Post(models.Model):
title = models.CharField(max_length=50)
body = RichTextField(blank=True, null=True)
date = models.DateTimeField('date_posted')
username = models.ForeignKey(admin.username, on_delete=models.CASCADE)
Where admin.username refers the username of auth_user admin model
Thanks for your help
As the referencing the user model section of the documentation says, you can make use of settings.AUTH_USER_MODEL to obtain a reference to the user model that is used. You can use the to_field=… [Django-doc] to specify to what field of the model it should refer, so:
from django.conf import settings
class Post(models.Model):
title = models.CharField(max_length=50)
body = RichTextField(blank=True, null=True)
date = models.DateTimeField('date_posted')
author = models.ForeignKey(
settings.AUTH_USER_MODEL,
to_field='username'
on_delete=models.CASCADE,
editable=False
)
By specifying editable=False [Django-doc] it will not automatically show up in ModelForms.
In views, you can then set the logged in user as author by specifing the author attribute. For example:
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect
#login_required
def some_view(request):
if request.method == 'POST':
form = PostForm(request.POST)
if form.is_valid():
form.instance.author = request.user
form.save()
return redirect('name-of-some-view')
else:
form = PostForm()
return render(request, 'some_template.html', {'form': form})
Note: A ForeignKey does not store the string representation (or name) of the
referenced object in the column, it stores the primary key of the record it
references in a column with an _id suffix to a ForeignKey field. Therefore
ForeignKeys usually do not end with a _name suffix. You might want to
consider renaming the username field to author.
How about something like this?
class Post(models.Model):
title = models.CharField(max_length=50)
body = RichTextField(blank=True, null=True)
date = models.DateTimeField('date_posted')
user = models.ForeignKey(auth_user, on_delete=models.CASCADE)
#property
def username(self): return self.user.username
Usage:
some_post = Post.objects.get(id='the_post_id')
print(some_post.username) # prints some_post.user.username

How do I add username of logged in user to model field in django

How to add username of currently logged in user to field in my model? For example, I need to store info about user like name, email and so on in model, other than default Django user model, but I still use default one to store credentials. I want to establish relationship between those, so I created username field in my model. How do I fill it with current user's username upon saving the corresponding form?
My model
class ApplicantProfile(models.Model):
name = models.CharField(max_length = 50)
dob = models.DateField()
email = models.EmailField()
description = models.TextField()
username = <something>
What do I change <something> with?
My form
class ApplicantProfileEdit(forms.ModelForm):
class Meta:
model = ApplicantProfile
fields = [
'name',
'dob',
'email',
'description',
]
My view
def ApplEditView(request):
form = ApplicantProfileEdit(request.POST or None)
if form.is_valid():
form.save()
form = ApplicantProfileEdit()
context = {
'form':form
}
return render(request, "applProfileEdit.html", context)
P.S. I tried to import models straight to my views.py, and assign request.user.username to username field of the model in my view, but it didn't work, just left that field empty. I had username as CharField when I tried this.
It is not a good idea to save the username itself, or at least not without a FOREIGN KEY constraint. If later a user changes their name, then the username now points to a non-existing user, if later another user for example changes their username to thatusername, then your ApplicantProfile will point to the wrong user.
Normally one uses a ForeignKey field [Django-doc], or in case each ApplicantProfile points to a different user, a OneToOneField [Django-doc]:
from django.conf import settings
from django.db import models
class ApplicantProfile(models.Model):
name = models.CharField(max_length = 50)
dob = models.DateField()
email = models.EmailField()
description = models.TextField()
# maybe a OneToOneField
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
In the view:
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect
#login_required
def appl_edit_view(request):
if request.method == 'POST':
form = ApplicantProfileEdit(request.POST)
if form.is_valid():
form.instance.user = request.user
form.save()
return redirect('some-view-name')
else:
form = ApplicantProfileEdit()
context = {
'form':form
}
return render(request, 'applProfileEdit.html', context)
Note: In case of a successful POST request, you should make a redirect
[Django-doc]
to implement the Post/Redirect/Get pattern [wiki].
This avoids that you make the same POST request when the user refreshes the
browser.
Note: You can limit views to a view to authenticated users with the
#login_required decorator [Django-doc].

Can't update user profile in my Django app Django

I have created a Edit Profile form in my Django app but it doesn't save in the database.
This is the profile model:
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='profile', primary_key=True) #Each User is related to only one User Profile
city_search_text = models.CharField(blank=True, max_length=300)#user picks a city from autocomplete and in the view I get or create a City object
city = models.ForeignKey(City, blank=True, null=True, related_name='city') #Each User Profile must be related to one city.
prof_pic = models.ImageField(blank=True, upload_to='profile_pictures')
dob = models.DateField(blank=True, null=True)
def __str__(self):
return self.user.first_name
This is the form:
class EditProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ('dob',)#I'm testing to update this field only
def save(self, commit=True):
profile = super(EditProfileForm, self).save(commit=False)
if commit:
profile.save()
return profile
This is the view:
def editprofile(request):
if request.method == 'POST':
edit_profile_form = EditProfileForm(request.POST, instance=request.user)
if edit_profile_form.is_valid():
profile = edit_profile_form.save(commit=False)
profile.save()
if 'next' in request.GET:
return redirect(request.GET['next'])
else:
print (profile_form.errors)
else:
edit_profile_form = EditProfileForm(instance=request.user.profile)
return render(request, 'excurj/editprofile.html', {'edit_profile_form':edit_profile_form,})
After I submit the form it forwards me to index page okay but the values remain the same in the user's profile.
Seems like
if edit_profile_form.is_valid():
isn't getting called at all, and your data is not saved. That means your form has invalid data, and you should check for form errors to detect those.
Also, you are trying to print form errors if the request isn't POST, which makes no sense and won't help you printing form errors. Try using this way;
if edit_profile_form.is_valid():
profile = edit_profile_form.save(commit=False)
profile.save()
else:
print (profile_form.errors)
And check your form for errors.
I figured it out eventually. In the view I should have passed an instance of the profile not the User object. So it needs to be like this:
edit_profile_form = EditProfileForm(request.POST, instance=request.user.*profile*)

Categories