image not saved while updating userprofile in django - python

I am trying to update a userprofile model that i used to save additional information over the inbuilt User model, now when i am trying to update it , the image does not gets saved. I need help to resolve this issue
# In views.py
#login_required(login_url=LOGIN_REDIRECT_URL)
def update_user_profile(request):
userobj = get_object_or_404(UserProfile, user=request.user)
form = UserProfileForm(data = request.POST or None,files= request.FILES or None, instance=userobj)
if request.method=='POST':
print(form.is_valid())
if form.is_valid():
profile = form.save(commit=False)
profile.picture = form.cleaned_data['picture']
profile.about = form.cleaned_data['about']
profile.save()
else:
print("NO picure")
return HttpResponseRedirect("/blog/profile/")
return render(request, "blog/post_update.html", {'form':form})
#models.py
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
about = models.CharField(max_length=200, null=True, blank=True)
picture = models.ImageField(upload_to="profile_images/", blank=True)
def __str__(self):
return str(self.user)
#In forms.py
class UserProfileForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(UserProfileForm, self).__init__(*args, **kwargs)
self.fields['about'].widget.attrs.update({'class': 'form-control '})
self.fields['picture'].widget.attrs.update({'class': 'form-control-file'})
class Meta:
model = UserProfile
fields = ('about', 'picture')
# userprofileform.html
{% extends 'base.html' %}
{% block content %}
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" class="btn btn-primary" value="Create Profile">
</form>
{% endblock %}
please take a look at the code and help. while registering if the image was uploaded it get's saved , but when i try to update the userprofile directly in profile section image does not get changed and shows the same as one saved while user registration else it shows None.

I did some changes on templates in settings.py and got my project runnning. Issue was that i was not mentioning the Templates directory properly

Related

Django ModelForm not saving data to database, Form.save is not working?

List item
Hello I am django beginner having tough time could someone please help me I don't know what am I doing wrong ?
I am trying to create a form and saving some data through it by using form.save(). And I am new to here also so don't mind any mistakes.
Here is my model:
from django.db import models
from stores.models import Store
class Category(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=30)
def __str__(self):
return self.name
class Product(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=30)
price = models.DecimalField(max_digits=5, decimal_places=5)
image = models.ImageField(upload_to='upload_to/')
category = models.ForeignKey(Category, default='Default', on_delete=models.CASCADE, blank=False, null=False)
store = models.ForeignKey(Store, on_delete=models.CASCADE, blank=False, null=False)
Here is my view:
from django.shortcuts import render, redirect
from .forms import NewPro
def pro(request):
if request.method == 'POST':
form = NewPro(request.POST)
if form.is_valid():
form.save()
return redirect('stores_list')
else:
form = NewPro()
return render(request, "default/add_product.html", {'form': form})
def product_list(request):
return render(request, 'default/product_list.html')
Here is my form:
from django import forms
from .models import Product
class NewPro(forms.ModelForm):
class Meta:
model = Product
fields = ('name', 'price', 'image','category', 'store',)
default/add_product.html :
{% extends 'default/base.html' %}
<html>
<head><title>E-Commerce App</title></head>
{% block content %}
<h1>Add Product details</h1>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Add Product</button>
</form>{% endblock %}
</html>
Settings.py settings
MEDIA_ROOT = '/home/saifi/Saif_project/final_project/MEDIA_ROOT/upload_to'
I can see some indentation issues in the view - but I'll guess that's just formatting when copying into Stackoverflow.
the form.is_valid() check will validate all your form fields and will only write to the database if all the input fields are valid. If it's not saving, the first place I'd check would be for form errors.
In your template you can render the errors with {{form.errors}} and it will list each field and error.
You forgot request.FILES in your pro view function, you have an image file after all.
def pro(request):
if request.method == 'POST':
form = NewPro(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('stores_list')
else:
form = NewPro()
return render(request, "default/add_product.html", {'form': form})
Try using the form this way:
<form action="YOUR_URL_HERE" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Add Product</button>
</form>
I hope this will help. Welcome aboard ;)
Your indentation is wrong, the else should be for first 'if'
def pro(request):
form = NewPro()
if request.method == 'POST':
form = NewPro(request.POST)
if form.is_valid():
form.save()
return redirect('stores_list')
else:
form = NewPro()
return render(request, "default/add_product.html", {'form': form})

Django form are not showing in html template

I'm trying to create a form in Django template but it is just not showing the fields
here is my files
models.py where i created the desired table
class ReportMessage(models.Model):
sender = models.ForeignKey(UserModel, related_name="report_message_sender", on_delete='CASCADE')
message = models.ForeignKey(Message, on_delete='CASCADE')
created_at = models.DateTimeField(auto_now=True)
reason = models.TextField(max_length=1500)
is_read = models.BooleanField(default=False)
forms.py where i created the form to edit only one field in the table
class ReportMessageForm(forms.Form):
class Meta:
model = ReportMessage
fields = ['reason', ]
views.py where i created the view for the form
#login_required
def report_message(request, pk):
current_user = request.user
reported_message = get_object_or_404(Message, pk=pk)
if request.method == "POST":
report_message_form = ReportMessageForm(request.POST)
if report_message_form.is_valid():
model_instance = report_message_form.save(commit=False)
model_instance.sender = current_user
model_instance.message = reported_message
model_instance.save()
return redirect('report_confirm')
else:
report_message_form = ReportMessageForm()
context = {
'report_message_form': report_message_form,
}
return render(request, 'fostania_web_app/report_message.html', context)
def report_confirm(request):
return render(request, 'fostania_web_app/report_confirm.html')
and urls.py where the urls i used for the views
path('report/messages/<int:pk>/', views.report_message, name="report_message"),
path('report/confirm', views.report_confirm, name="report_confirm"),
and finally that is how i used the form in the html template
{% extends 'fostania_web_app/base.html' %}
{% block content %}
{% load static %}
<form action="" method="post" name="ReportMessageForm" align="right">
{% csrf_token %}
{{ report_message_form }}
<input type="submit" class="btn btn-success" style="width: 100px;" value="إرسال" />
</form>
{% endblock %}
and then all what i see in the html page is the submit button and there is no form labels or input or anything.
In your forms.py if you are not using ModelForm then you have to explicitly declare the fields for the forms
reason = forms.Charfield()
Or you can use ModelForm which inherits from the model you specify.
You should specify the model in the Meta class while using ModelForm.You can also specify required fields from the Model in the fields list in Meta class
Class myform(forms.ModelForm)
Class Meta:
model = your_model_name
fields= [reason,]
Cheers
:)
I think that your problem is in your model form because you are using forms.Form and you need to use forms.ModelForm
class ReportMessageForm(forms.ModelForm):
class Meta:
model = ReportMessage
fields = ['reason', ]
def report_confirm(request):
return render(request, 'fostania_web_app/report_confirm.html', context) #add the context
You need to pass in the "context" so that it shows in the template

Django - Tango With Django upload picture

I'm on chapter 9 in Tango With Django - creating user authentication. In the registration page I have the option of uploading a picture. In my admin file everything looks good after I register myself. I show up in the User Profiles, and it even shows the image I uploaded:
Picture: Currently: profile_images/earth.jpeg Clear. However when I click on that picture this is the error message I get:
Page not found (404)
Request Method: GET
Request URL: http://localhost:8000/admin/rango/userprofile/1/change/profile_images/earth.jpeg/change/
Raised by: django.contrib.admin.options.change_view
user profile object with primary key u'1/change/profile_images/earth.jpeg' does not exist.
You're seeing this error because you have DEBUG = True in your Django settings file. Change that to False, and Django will display a standard 404 page.
models.py:
from __future__ import unicode_literals
from django.db import models
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
class Category(models.Model):
name = models.CharField(max_length=128, unique=True)
views = models.IntegerField(default=0)
likes = models.IntegerField(default=0)
slug = models.SlugField(unique=True)
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
super(Category, self).save(*args, **kwargs)
class Meta:
verbose_name_plural = 'categories'
def __str__(self):
return self.name
class Page(models.Model):
category = models.ForeignKey(Category)
title = models.CharField(max_length=128)
url = models.URLField()
views = models.IntegerField(default=0)
def __str__(self):
return self.title
class UserProfile(models.Model):
user = models.OneToOneField(User)
website = models.URLField(blank=True)
picture = models.ImageField(upload_to='profile_images', blank=True)
def __str__(self):
return self.user.username
views.py - only the register():
def register(request):
registered = False
if request.method == 'POST':
user_form = UserForm(data=request.POST)
profile_form = UserProfileForm(data=request.POST)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save()
user.set_password(user.password)
user.save()
profile = profile_form.save(commit=False)
profile.user = user
if 'picture' in request.FILES:
profile.picture = request.FILES['picture']
profile.save()
registered = True
else:
print user_form.errors, profile_form.errors
else:
user_form = UserForm()
profile_form = UserProfileForm()
return render(request, 'rango/register.html',
{'user_form': user_form,
'profile_form': profile_form,
'registered': registered}
)
finally, my register.html file:
{% extends 'rango/base.html' %}
{% load staticfiles %}
{% block title_block %}
Register
{% endblock %}
{% block body_block %}
<h1>Register with Rango</h1>
{% if registered %}
Rango says: <strong>thank you for registering!</strong>
Return to the homepage<br/>
{% else %}
Rango says: <strong>register here!</strong>
Click here to go to the homepage<br/>
<form id="user_form" method="post" action="/rango/register/" enctype="multipart/form-data">
{% csrf_token %}
{{ user_form.as_p }}
{{ profile_form.as_p }}
<input type="submit" name="submit" value="Register" />
</form>
{% endif %}
{% endblock %}
user profile object with primary key u'1/change/profile_images/earth.jpeg' does not exist.
It looks like one of your URL patterns may be off; it probably just wants to capture that 1 to use as the PK for a lookup, but instead is capturing 1/change/profile_images/earth.jpeg.

Django ModelForm; User, this field is required

I am having some issues with a (model)form consisting of just a single button. When I try to submit the form this message is displayed:
user
This field is required.
The ModelForm looks like this:
from django.forms import ModelForm
from .models import HulpOproep
class HulpOproepForm(ModelForm):
class Meta:
model = HulpOproep
fields = ['user', ]
The Model looks like this:
class HulpOproep(models.Model):
user = models.ForeignKey(User)
time = models.DateTimeField(auto_now_add=True, verbose_name='Tijd')
def __str__(self):
return '%s %s' % (self.user.username, str(self.time))
def username(self):
return self.user.username
def first_name(self):
return self.user.first_name
def last_name(self):
return self.user.last_name
class Meta:
verbose_name = 'Hulp Oproep'
verbose_name_plural = 'Hulp Oproepen'
The View looks like this:
def verzend_oproep(request):
if request.method == 'POST':
form = HulpOproepForm(request.POST)
if form.is_valid():
oproep = form.save(commit=False)
oproep.user = request.user
oproep.save()
return redirect('portal/index/')
else:
form = HulpOproepForm()
return render(request, 'portal/verzend_oproep.html', {'form': form})
The Template:
{% extends "base.html" %}
{% block head %}
<title>Zorggroep | Hulp Oproep</title>
{% endblock %}
{% block body%}
<h1>Verstuur Hulpoproep</h1>
<form method="POST" class="post-form">{% csrf_token %}
{{ form.as_P }}
{{ form.errors }}
<button type="submit" class="save btn btn-default">Verstuur</button>
</form>
{% endblock %}
The 'user' in the HulpOproep model is a ForeignKey and should be the currently logged in user's User object. I tried to specify this using the line:
oproep.user = request.user
So what should happen is:
Get the current user's 'User' object and use it as the 'HulpOproepForm.user'. This way the 'HulpOproepForm.user' is the 'HulpOproep.user' and a Foreign Key.
I have followed multiple tutorials and have searched around, but I cannot find a solution. I'm sorry if the answer is logical, but I have been using Django for only 5 days and have 1.5 months of programming experience under my belt.
Thank you!
Thanks PatNowak and Radek!
I did not know the form was waiting for user input instead of code input. I managed to fix it by adding exclude to the ModelForm.
class HulpOproepForm(ModelForm):
class Meta:
model = HulpOproep
exclude = ['user', 'time']

Updating user in django

In my application, I used email and password for user authentication, which works fine. However, I want to offer the user the option of adding other information to their account like first names, last names, and dates of birth.
I have a change form in myapp.forms.py
class MyChangeForm(forms.ModelForm):
"""
Form for editing an account.
"""
first_name = forms.CharField(widget=forms.TextInput, label="First name")
last_name = forms.CharField(widget=forms.TextInput, label="Last name")
date_of_birth = forms.DateField(widget=forms.DateField, label="Date of birth")
class Meta:
model = MyUser
fields = ['first_name', 'last_name', 'date_of_birth']
def save(self, commit=True):
user = super(MyChangeForm, self).save(commit=False)
if commit:
user.save()
return user
in my views.py, I have the following method for updating
#login_required(login_url='/')
def update_user(request):
if request.method == 'POST':
form = MyChangeForm(request.POST, instance=request.user)
if form.is_valid():
user = form.save(commit=False)
user.save()
return HttpResponseRedirect('/')
else:
form = MyChangeForm(instance=request.user)
return render_to_response('update_user.html', context_instance=RequestContext(request))
and my update_user.html is as follows
{% extends 'user_base.html' %}
{% block content %}
<div class="col-sm-3 col-sm-offset-5">
<h1> Update User</h1>
<form method='POST' action='/update_user/'> {% csrf_token %}
<ul>
{{ form.as_table }}
</ul>
<input type='Submit' class='btn btn-primary btn-block'>
</form>
</div>
{% endblock %}
However, when I serve the file I see this:
As seen here, there's no way to enter my fields!
How can I fix this? It's probably easy, but I'm getting tunnel vision.
erip
Add form to the context, for example like this:
render('update_user.html', {'form': form})

Categories