Django media upload not working when uploading image through code - python

I have created a Django application in which i have a signup page which asks a user to upload their profile picture.
When I'm uploading the profile picture through the Django admin panel, the images are being uploaded to the correct path and are being displayed in the website. However, the error comes when I directly select the image to upload when signing up and then When I click on the uploaded image in Django admin it shows page not found and the path to the image is being showed as C:\Users\hp\Workspace\findem\media\image.jpg
Settings.py
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'findem/static')
]
# media folder settings
MEDIA_ROOT = os.path.join(BASE_DIR , 'media').replace('\\', '/')
MEDIA_URL = '/media/'
User Model
class UserProfile(AbstractBaseUser, PermissionsMixin):
"""Represents a user profile inside our system"""
email = models.EmailField(max_length=255, unique=True)
name = models.CharField(max_length=255, default=profile_pic)
profile_picture = models.ImageField(upload_to='photos/profile_pictures/', default='photos/User.jpg')
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
highest_degree_earned = models.CharField(max_length=255, blank=False)
college_name = models.CharField(max_length=255, blank=False)
graduation_year = models.IntegerField(default=2020, blank=False)
Template :
<form class="needs-validation" novalidate autocomplete="off"
action="{% url 'signup' %}", method="POST" >
{% csrf_token %}
<div id="Personal_Information">
<h5 class="loginSignup">Personal Information</h5>
<div class="form-group row">
<label for="inputprofile" class="col-sm-2 col-form-label">Profile Picture</label>
<div class="col-sm-5">
<div class="input-group">
<div class="custom-file">
<input type="file" accept="image/png, image/jpeg, image/gif" class="custom-file-input" id="inputprofile" name="inputprofile">
<label class="custom-file-label" for="inputprofile" aria-describedby="inputprofile">Choose file</label>
</div>
</div>
</div>
</div>
<div class="form-group required row">
<label for="inputname" class="col-sm-2 col-form-label">Full Name <span id="required-field">*
</span>
</label>
<div class="col-sm-5">
<input type="text" class="form-control" name="inputname" id="inputname" placeholder="Enter Your Full Name" required>
<div class="valid-feedback">Looks good!</div>
<div class="invalid-feedback">Please enter your full name.</div>
</div>
</div>
<div class="form-group row">
<label for="inputemal" class="col-sm-2 col-form-label">Email <span id="required-field">*</span></label>
<div class="col-sm-5">
<input type="email" class="form-control" id="inputEmail" name="inputEmail" placeholder="Enter a Valid Email Address" required>
<div class="valid-feedback">Looks good!</div>
<div class="invalid-feedback">Please provide a valid email.</div>
</div>
</div>
<div class="form-group row">
<label for="inputPassword" class="col-sm-2 col-form-label">Password <span id="required-field">*</span></label>
<div class="col-sm-5">
<input type="password" class="form-control" id="inputPassword" name="inputPassword" placeholder="Choose a Password" required>
<div class="valid-feedback">Looks good!</div>
<div class="invalid-feedback">Please chose a valid password.</div>
</div>
</div>
<button type="submit" class="btn btn-success mt-3" id="loginButton">Sign Up</button>
</form>
view :
def signup(request):
"""View for Signing-up into the system"""
if request.method == 'POST':
# Get form value
profile_picture = request.POST.get('inputprofile')
name = request.POST.get('inputname')
email = request.POST['inputEmail']
password = request.POST['inputPassword']
highest_degree_earned = request.POST['inputDegree']
college_name = request.POST['CollegeName']
graduation_year = request.POST['inputGradYear']
skill_1 = request.POST['upload_skill1']
skill_2 = request.POST.get('upload_skill2', '')
skill_3 = request.POST.get('upload_skill3', '')
skill_4 = request.POST.get('upload_skill4', '')
skill_5 = request.POST.get('upload_skill5', '')
skill_6 = request.POST.get('upload_skill6', '')
join_date = datetime.now()
# Check Username
if UserProfile.objects.filter(name=name).exists():
messages.error(request, "That Name already taken")
return redirect('signup')
# Check email
else:
if UserProfile.objects.filter(email=email).exists():
messages.error(request, "That email is being used")
return redirect('signup')
else:
# Looks Good
user = UserProfile.objects.create_user(profile_picture=profile_picture, name=name, email=email,
password=password, highest_degree_earned=highest_degree_earned, college_name=college_name,
graduation_year=graduation_year, skill_1=skill_1, skill_2=skill_2, skill_3=skill_3, skill_4=skill_4,
skill_5=skill_5, skill_6=skill_6, join_date=join_date)
# #Login after register
# auth.login(request, user)
user.save()
messages.success(request, "You are now registered and can log in")
return redirect('login')
else:
return render(request, 'pages/signup.html')

Change your form tag to be be like this :
<form class="needs-validation" novalidate autocomplete="off"
action="{% url 'signup' %}", method="POST" enctype="multipart/form-data">
add request.FILES to profile_picture like that :
profile_picture = request.FILES.get('inputprofile') or None
Than in your create request you do that :
else:
if UserProfile.objects.filter(email=email).exists():
messages.error(request, "That email is being used")
return redirect('signup')
else:
# Looks Good
if profile_picture != None
user = UserProfile.objects.create_user(profile_picture=profile_picture, name=name, email=email,
password=password, highest_degree_earned=highest_degree_earned, college_name=college_name,
graduation_year=graduation_year, skill_1=skill_1, skill_2=skill_2, skill_3=skill_3, skill_4=skill_4,
skill_5=skill_5, skill_6=skill_6, join_date=join_date)
else:
user = UserProfile.objects.create_user(name=name, email=email,
password=password, highest_degree_earned=highest_degree_earned, college_name=college_name,
graduation_year=graduation_year, skill_1=skill_1, skill_2=skill_2, skill_3=skill_3, skill_4=skill_4,
skill_5=skill_5, skill_6=skill_6, join_date=join_date)
For the default picture try to change it to this :
profile_picture = models.ImageField(upload_to='photos/profile_pictures/', default='/media/photos/User.jpg')

In the HTML form, you need to use.
enctype="multipart/form-data"
Without that, the file is not sent to the server.
Add this tag to your form
<form method="post" enctype="multipart/form-data">
....
</form>
and to get the files at django part use request.FILES.get('filename') in your view
profile_picture = request.FILES.get('inputprofile')

Related

How to validate form by getting exact value on integer field

I am new in Django, I am trying to validate a form to get the particular value, if value is not exact validate error. For example, i have a field in a model (cot_code), the field has a integer value (12345). I have created a form for this field, i want if the user enter 12345 in form, the form will be valid as success "code is correct", but when user enter a wrong code (55777) the form will raise a validator error "Wrong code". I do not know how to go on with the views.
Model:
class CotCode(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
cot_code = models.IntegerField(default='0', blank=True) # I have set this field as 12345 in model.
date = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = 'CotCode'
verbose_name_plural = 'CotCode'
ordering = ['-date']
def __str__(self):
return self.user.username
Forms:
class CotCodeForm(forms.ModelForm):
class Meta:
model = CotCode
fields = ('cot_code',)
Views:
#login_required
def TransferCOTView(request):
#Don't know how to go on here
return render(request, 'transfer_cotcode.html')
Template:
<form method="POST" action="" class="text-center needs-validation" novalidate>
{% csrf_token %}
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="inputGroup-sizing-default">C.O.T</span>
</div>
<input type="text" class="form-control" aria-label="Sizing example input" aria-describedby="inputGroup-sizing-default" placeholder="Enter your COT Code" required>
<div class="invalid-feedback">
Please enter your C.O.T code.
</div>
</div>
<input type="submit" class="btn btn-primary btn-block btn-sm wave-effect my-2" value="{% trans 'Enter' %}" style="box-shadow:none;font-weight:500;"/>
</form>

Uploading an image file to database

I am making a social media app and i am adding a edit profile function to it. But for some reason, the profile image which the user chooses is not being uploaded to the database. Please help me to do so.
My views.py
def edit_profile(request):
user = request.user
user_profile = profile.objects.get(user__username=user)
Profile = user_profile
myuser = User.objects.get(username=user)
if request.method == 'POST':
try:
username = request.POST['username']
name = request.POST['name']
email = request.POST['email']
image = request.FILES['img']
myuser.username = username
myuser.first_name = name
myuser.email = email
myuser.save()
Profile.user = myuser.username
Profile.name = myuser.first_name
Profile.img = image
Profile.save()
return redirect('/')
except:
return redirect('/')
else:
context = {
'user':user_profile,
'myuser':myuser,
}
return render(request, 'edit_profile.html', context)
my tempateview
<form action="/users/edit_profile/" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<center>
<img src="{{user.img.url}}" style="border-radius: 50%; widows: 150px;height:150px; margin-left:-50px" onclick="document.getElementById('image').click()"><br>
<span class="click" onclick="document.getElementById('image').click()">Change Profile Picture</span>
</center>
<input type="file" name="img" id="image" accept="image/*" style="display:none"><br><br>
<label> Username </label><br>
<input type="text" name="username" class="edit" value="{{user.user}}" spellcheck="false"><br><br>
<label> Name </label><br>
<input type="text" name="name" class="edit" value="{{user.name}}" spellcheck="false"><br><br>
<label> Email </label><br>
<input type="email" name="email" class="edit" value="{{myuser.email}}" spellcheck="false"><br><br><br>
<input type="submit" value="Save changes" style="width:40%; float:right; margin-right:120px">
</form>
my models.py
class profile(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
img = models.ImageField(default='default.png', upload_to='profile_pics')
def __str__(self):
return "Profile({})".format(self.user.username)
Everything is working. Only the image file cannot be uploaded. Please help. Thankyou in advance.
this was a problem for me too. i solved this by saving the object like so:
from django.core.files import File
Profile.img.save(image.name , File(image))
Profile.save()
hope it helped you.

To and From return the same email id in django send_mail()

Views.py
def contact(request):
if request.method == 'POST':
message_name = request.POST['message-name']
message_email = request.POST['message-email']
message = request.POST['message']
# send an email
send_mail(
'Message from ' + message_name, # subject
message, # message
message_email, # from email
['myEmailId#gmail.com'], # to email
)
settings.py
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = 'myEmailId#gmail.com'
EMAIL_HOST_PASSWORD = '<myaccount app password>'
EMAIL_USE_TLS = True
contact.html
<form action="{% url 'contact' %}" method="POST" class="bg-light p-5 contact-form">
{% csrf_token %}
<div class="form-group">
<input type="text" name="message-name" class="form-control" placeholder="Your Name">
</div>
<div class="form-group">
<input type="email" name="message-email" class="form-control" placeholder="Your Email">
</div>
<div class="form-group">
<textarea name="message" id="" cols="30" rows="7" class="form-control" placeholder="Message">
</textarea>
</div>
<div class="form-group">
<input type="submit" value="Send Message" class="btn btn-primary py-3 px-5">
</div>
</form>
I have created this code for the contact-me page. Now when user Submits the Contact Form which has the fields message-name, message-email and message, I receive the email where FROM and TO are both my email-id.
It is not retrieving the users email. But rest of the fields are working fine.
Even Tested with DebuggingServer and that works as expected. Seems like I am missing something in the setting.py because that is the one file I have changed.
I don't understand where I am going wrong. Any help appreciated.
You should not be using user's email address in from field. It should be the address that is in your control. By using user's email in from field, it implies that the email was sent by the user which is not the case, and should never happen.
Moreover, gmail would not allow you to send email from anyone else's email address from your account.
I would suggest you to use your own email address and have user's email address in the message.

Can "list_display" show users input on django admin page?

I need to see user's input display on django's admin page, from what i have read, I need to use list_display but there is nothing appearing on admin page. Maybe there is a problem in the views.py but everything looks good.
Here is my code:
Views.py
def process_e(request):
website_name = request.POST["website_name"]
product_name = request.POST["product_name"]
phone_number = request.POST["phone_number"]
website_details = request.POST["website_details"]
website_content = request.POST["website_content"]
created_objs = Enterprise.objects.create(website_name=website_name, product_name=product_name, phone_number=phone_number, website_details=website_details, website_content=website_content)
legth_of_todos = Enterprise.objects.all().count()
created_items = Enterprise.objects.all()
if request.method == 'POST':
if request.POST.get('website_name') and request.POST.get('product_name') and request.POST.get('phone_number') and request.POST.get('website_details') and request.POST.get('website_content'):
post=Enterprise()
post.title= request.POST.get('website_name')
post.content= request.POST.get('product_name')
post.content= request.POST.get('phone_number')
post.content= request.POST.get('website_details')
post.content= request.POST.get('website_content')
post.save()
return render(request, 'enterprise.html', {"created_items":created_items})
else:
pass
else:
return render(request,'enterprise.html')
Admin.py
from django.contrib import admin
from service.models import Enterprise
class PaymentsAdmin(admin.ModelAdmin):
list_display = ('website_name', 'product_name', 'phone_number', 'website_details',
'website_content')
admin.site.register(Enterprise, PaymentsAdmin)
Models.py
from django.db import models
class Enterprise(models.Model):
website_name = models.CharField(max_length=50)
product_name = models.CharField(max_length=200)
phone_number = models.CharField(max_length=200)
website_details = models.CharField(max_length=200)
website_content = models.CharField(max_length=200)
Html
<div class="form-group">
<label>Website name</label>
<input type="text" name="website_name" class="form-control" placeholder="First name">
</div>
<div class="form-group">
<label>Product name (if there is)</label>
<input type="text" name="product_name" class="form-control" placeholder="First name">
</div>
<div class="form-group">
<label>Phone number</label>
<input type="text" claa="phone_name" class="form-control" placeholder="First name">
</div>
<div class="form-group">
<label for="exampleFormControlTextarea1">What kind of content should your website upload?</label>
<textarea class="form-control" name="website_content" rows="3"></textarea>
</div>
<div class="form-group">
<label for="exampleFormControlTextarea1">Website details</label>
<textarea class="form-control" name="website_details" rows="3"></textarea>
</div>
Yes. list_display is used to show a model's fields in the ListView of a model. You also need at least one model instance.

How to make a Django contact me form with send_mail?

I tried to use 6 different tutorials to get this done, but all of them gave different variations so I'm really frustrated at the pace I'm making...
I think I'm nearing the last few steps but I need some help. Here is the code I have in my Django project:
# -- settings.py--
EMAIL_BACKEND = 'django.core.mail.backends.stmp.EmailBackend'
EMAIL_HOST = 'http://smtp.gmail.com/'
EMAIL_HOST_USER = 'a spare Gmail I have'
EMAIL_HOST_PASSWORD = 'the password'
EMAIL_USE_TLS = False
EMAIL_PORT = 465
..
# -- views.py --
# (assumed relevant imports are imported)
class ContactView(FormView):
template_name = 'CONTACT.html'
form_class = ContactForm
success_url = 'Success!'
context_vars = {
'example_name_f': 'Adam',
'example_name_l': 'Smith',
'example_email': 'smith.a#gmail.com',
'example_subject': 'Sales proposal',
'example_text': 'Hi Mark, I have a sales proposal for you!',
}
def get(self, request):
return render(request, 'CONTACT.html', ContactView.context_vars)
def contact(self, request):
if request.method == 'POST':
form = self.form_class(data=request.POST)
if form.is_valid():
time = request.POST.get('time', '')
first_name = request.POST.get('first_name', '')
last_name = request.POST.get('last_name', '')
email_address = request.POST.get('email_address', '')
subject = request.POST.get('subject', '')
text = request.POST.get('text', '')
send_mail(subject, text, email_address,
['999#outlook.com'], fail_silently=False)
return redirect('CONTACT-done.html') # CONTACT-done is a temporary success screen
return render(request, 'CONTACT.html', ContactView.context_vars)
The relevant portion of HTML:
<div class="container-fluid" style="width: 100%; height: 100%">
<form action="" method="post">
<label for="first-name">First Name</label>
<input id="first-name" name="first-name" type="text" placeholder="{{ example_name_f }}">
<!-- Note: placeholder vs value attributes similar -->
<!-- id is for HTML, name is for views.py -->
<label for="last-name">Last Name</label>
<input id="last-name" name="last-name" type="text" placeholder="{{ example_name_l }}">
<!-- Its unnecessary to use context vars for placehoder text -->
<label for="email">Email Address</label>
<input id="email" name="email" type="email" placeholder="{{ example_email }}" required>
<label for="subject">Subject</label>
<input id="subject" name="subject" type="text" placeholder="{{ example_subject }}">
<label for="text">Message:</label>
<input id="text" name="text" type="text" placeholder="{{ example_text }}" required>
<input type="submit" value="Send">
</form>
</div>
Some tutorials recommended a {{ form.as_p }} approach in HTML but some just did the basic HTML style as I did above. Not sure what to do from here.
Clicking send on my website gives a 403 CSRF verification failed. Request aborted.
Please explain in as simple a way as possible, I'm not brand new to programming but I'm not a CS person either. Thanks.
you need the CSRF token:
<form ...>
{% csrf_token %}
...
</form>
As in this official documentation example:

Categories