Image not saving in UserProfileForm (Django) - python

I have a model form to update the user profile and everything is saving correctly except of them image. If I use admin it updates fine but when I use my form it just stays as the default profile image.
Here is my form:
class EditProfileForm(forms.ModelForm):
birth_date = forms.DateField(label='birth_date', input_formats=['%Y-%m-%d'])
class Meta:
model = UserProfile
fields = (
"image",
"bio",
"location",
"birth_date",
)
Here is my model:
class UserProfile(models.Model):
user = models.OneToOneField(User)
bio = models.TextField(max_length=500, blank=True)
location = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
image = models.ImageField(upload_to='profile_image', blank=True)
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)
Here is my view:
def edit_profile(request):
instance = get_object_or_404(UserProfile, user=request.user)
if request.method == 'POST':
form = EditProfileForm(request.POST, instance=instance)
if form.is_valid():
instance = form.save(commit=False)
instance.user = request.user
instance.save()
return redirect('/')
else:
form = EditProfileForm(instance=request.user)
return render(request, 'edit_profile.html', {'form': form})
And here is my html:
{% extends 'base.html' %}
{% block content %}
<h1>Edit Profile</h1>
<form method='POST' action=''>{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-outline-success">Save</button>
</form>
</body>
{% endblock %}

For file upload you need to specify form's enctype:
<form method='POST' action='' enctype="multipart/form-data">{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-outline-success">Save</button>
</form>
And you should pass request's files to form instance in view:
form = EditProfileForm(request.POST, request.FILES, instance=instance)
Check this doc for details.

Related

Model is not throwing(Saving) data to the backend in Django

This is function for updating user's info.
views.py
def UpdateProfile(request):
context = {}
user = request.User
if not user.is_authenticated:
return redirect('login')
if request.POST:
form = PersonalInfo(request.POST, instance=user)
if form.is_valid():
obj = form.Save(commit=False)
user = user.id
obj.user = user
obj.save()
return redirect('profile')
else:
#messages.error(request, ('Please correct the error below.'))
context['personal_form'] = form
else:
form = PersonalInfo(instance=user)
context['personal_form'] = form
return render(request, 'admission/signup.html', context)
This is the model I have created for storing user info.
models.py:
class ApplicantInfo(models.Model):
infield = models.AutoField(primary_key=True)
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=20)
profile_pic = models.ImageField(upload_to='media/', blank= True, null= True)
father_name = models.CharField(max_length=30)
user = models.OneToOneField(User, on_delete=models.CASCADE)
This is the form class I have created.
forms.py:
from .models import Applicant, ApplicantInfo
from django import forms
class PersonalInfo(forms.ModelForm):
class Meta:
model = ProfileInfo
fields = [
'first_name',
'last_name',
'profile_pic',
#'date_birth',
'father_name',
'street_adr',
'city',
'zip_code',
]
This is the frontend template which I have created, this is working fine.
Template
{%block content%}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<form method="POST">
{% csrf_token %}
{% for field in personal_form %}
<p>
{{field.label_tag}}
{{field}}
{% if field.help_text %}
<small style="color:gray">{{field.help_text}}</small>
{% endif %}
</p>
{% endfor %}
{% for field in personal_form %}
<p>
{% for error in field.errors %}
<p style="color:red">{{error}}</p>
{% endfor %}
</p>
{% endfor %}
<button type="submit">Submit</button>
</form>
</body>
</html>
{% endblock content %}
The app has been able to load the form without any trouble but it just not throwing data to the backend.
Updated function for UpdateProfile
views.py
def UpdateProfile(request, id=None):
context = {}
user_obj = request.user
if not user_obj.is_authenticated:
return redirect('login')
if request.method == "POST":
form = PersonalInfo(request.POST)
if form.is_valid():
obj = form.save()
user_id = Applicant.objects.filter(app_id = user_obj.app_id).first()
obj.user = user_id
obj.save()
return redirect('profile')
else:
#messages.error(request, ('Please correct the error below.'))
context['personal_form'] = form
elif request.method == 'GET':
form = PersonalInfo(instance=user_obj)
context['personal_form'] = form
return render(request, 'admission/signup.html', context)
Updated code for forms method, only add #def cleaned_data function
forms.py
class PersonalInfo( forms.ModelForm):
class Meta:
model = ProfileInfo
fields = [
'first_name',
'last_name',
'profile_pic',
#'date_birth',
'father_name',
'street_adr',
'city',
'zip_code',
]
def clean(self):
if self.is_valid():
first_name = self.cleaned_data['first_name']
last_name = self.cleaned_data['last_name']
father_name = self.cleaned_data['father_name']
street_adr = self.cleaned_data['street_adr']
city = self.cleaned_data['city']
zip_code = self.cleaned_data['zip_code']
And model does not need to be change, you have choice either to add and autofield(PrimaryKey) or use the default one
The problem was in view.py where i just removed instance attribute from the form object, then I called user_id from user model which is in this case #Applicant model, then assigned to the obj object and saved obj.
Thanks to all of you who has spent precious time in this problem.
Cheers!!!

How to place default value in to dropdown form field in django

I'm building a post-comment model in one view, one page, something like facebook. I have two forms in my home.html and view.py: new post and new comment. In each post container, there is a new comment form.
I have a problem because I don't know how to relate comment to post - specifically how to pass post.id to my comment form.
Is it possible to pass my {{ post.id }} to my {{newCommentForm.field }}? That each comment has a default value of post's id?
My home.html:
{% for post in posts %}
<div class="container">
<a class="user" href="#">{{ post.author }}</a>, {{ post.date_posted }}
<img src="{{ post.author.profile.image.url }}" alt="{{ post.author }}"style="width:100%;">
<p>{{ post.content }}</p>
<form METHOD="POST" class="new_post">
{% csrf_token %}
{{ newCommentForm.content }}
{{ newCommentForm.post }}
<button type="submit" name="newCommentSubmit">Add</button>
</form>
</div>
{% endfor %}
models.py
class Post(models.Model):
content = models.TextField(max_length=1000)
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.content
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
author = models.ForeignKey(User, on_delete=models.CASCADE)
content = models.TextField(max_length=500)
date = models.DateTimeField(default=timezone.now)
def add_coment(self):
self.date = timezone.now()
self.save()
def __str__(self):
return self.content
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='default.jpg', upload_to='profile_pics')
def __str__(self):
return f'{self.user.username}'
views.py
#login_required()
def home(request):
newPostForm = newPost()
newCommentForm = newComment()
if request.method == 'POST':
if 'newPostSubmit' in request.POST:
newPostForm = newPost(request.POST, prefix='newpost')
if newPostForm.is_valid():
instance = newPostForm.save(commit=False)
instance.author = request.user
instance.date_posted = timezone.now()
instance.save()
newCommentForm = newComment(prefix='newcomment')
elif 'newCommentSubmit' in request.POST:
newCommentForm = newComment(request.POST, prefix='newcomment')
if newCommentForm.is_valid():
instance = newCommentForm.save(commit=False)
instance.author = request.user
instance.date_posted = timezone.now()
instance.save()
newPostForm = newPost(prefix='newpost')
else:
newPostForm = newPost(prefix='newpost')
newCommentForm = newComment(prefix='newcomment')
context = {
'newPostForm': newPostForm,
'newCommentForm': newCommentForm,
'posts': Post.objects.all().order_by('-date_posted'),
'comments': Comment.objects.all()
}
return render(request, 'blog/home.html', context)
def about(request):
return render(request, 'blog/about.html')
My model is working now, comments are added, but I need to choose my post (post.id) manually from the default dropdown field witch all posts.
Add your post to comment like this:
if newCommentForm.is_valid():
instance = newCommentForm.save(commit=False)
instance.author = request.user
instance,=.post = request.post
instance.date_posted = timezone.now()
instance.save()
And send post in request!

Django users can't login

I made a custom UserCreationForm. I can signup but after that I can't login into my web app. I can only login as a superuser. I imported the LoginView() but when I try to login it tells me "Please enter a correct username and password. Note that both fields may be case-sensitive.".
[views.py]
#csrf_exempt
def signup(request):
if request.method == 'POST':
user_form = UserForm(data=request.POST)
profile_form = UserProfileInfoForm(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 'profile_pic' in request.FILES:
print('found it')
profile.profile_pic = request.FILES['profile_pic']
profile.save()
# registered = True
login(request, user, backend='django.contrib.auth.backends.ModelBackend')
return redirect('../')
else:
print(user_form.errors,profile_form.errors)
else:
user_form = UserForm()
profile_form = UserProfileInfoForm()
return render(request,'users/signup.html',
{'user_form':user_form,
'profile_form':profile_form,'registered':registered})
forms.py
class UserForm(UserCreationForm):
class Meta():
model = User
fields = ('username','email')
def __init__(self, *args, **kwargs):
super(UserCreationForm, self).__init__(*args, **kwargs)
for fieldname in ['username', 'password1', 'password2']:
self.fields[fieldname].help_text = None
class UserProfileInfoForm(forms.ModelForm):
class Meta():
is_photographer = forms.BooleanField()
model = UserProfileInfo
fields = ('portfolio_site','profile_pic', 'type_of_photography', 'is_photographer',)```
models.py
class UserProfileInfo(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
portfolio_site = models.URLField(blank=True)
profile_pic = models.ImageField(upload_to='profile_pics',blank=True)
is_photographer = models.BooleanField(default=False)
type_of_photography = models.CharField(max_length=120, blank=True)
def __str__(self):
return self.user.username
login.html
{% load staticfiles %}
{% block title %}
<title>Login</title>
<link rel="stylesheet" href="{% static 'css/login.css' %}"/>
{% endblock %}
{% block main %}
<div class="col-md-11 container login">
<div class="row">
<div class="col-md-7 left">
<div class="group">
<h1>Login</h1>
<h4>Welcome Back. Please login to your account.</h4>
<form enctype="multipart/form-data" method="POST">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" value = "login">Login</button>
</form>
</div>
</div>
<div class="col-md-5 right">
<div class="group">
<h1>Don't have an account?</h1>
<h4>Create one now!</h4>
<button>Sign up</button>
</div>
</div>
</div>
</div>
{% endblock %}

'ManagementForm data is missing or has been tampered with' error when loading multiple model forms django

views.py
#login_required(login_url='/account/login/')
def TaskCreateView(request,pk,todo_id):
if not request.user.is_authenticated:
return redirect('accounts:index')
else:
instance = get_object_or_404(Level, pk=pk)
qs = instance.todo_set.get(id = todo_id)
todo = Task.objects.filter(todo=qs, student=request.user)
if todo.exists():
messages.warning(request, 'You Already Completed This Task')
return HttpResponseRedirect(instance.get_absolute_url())
form = StudentTaskForm(request.POST or None, request.FILES or None)
if form.is_valid():
form.instance.user = User.objects.get(id=request.user.id)
obj = form.save(commit=False)
obj.student = request.user
obj.todo = qs
obj.level = instance
obj.save()
ImageFormSet = modelformset_factory(Images,
form=ImageForm, extra=3)
formset = ImageFormSet(request.POST, request.FILES,
queryset=Images.objects.none())
if request.method == 'POST':
if formset.is_valid():
for form in formset.cleaned_data:
image = form['image']
photo = Images(post=form, image=image)
photo.save()
return redirect('student:dashboard')
return render(request,'task_form.html',
{'form':form,"qs":qs,'formset':formset})
forms.py
class StudentTaskForm(forms.ModelForm):
title = forms.CharField(widget=forms.TextInput(attrs={'class':
'form-control',' type': "text",'placeholder':'Enter Title'}))
content = forms.CharField(widget=SummernoteWidget())
class Meta:
model = Task
fields = [
'title',
'content',
]
widgets = {
'content': SummernoteWidget(),
}
class ImageForm(forms.ModelForm):
image = forms.ImageField(label='Image')
class Meta:
model = Images
fields = ('image', )
I have two models Task and Images and I'm using two forms for the same.
Im trying to implement multiple image upload for the same. When I try to load the form I'm encountering this error. I have added the {{ formset.management_form }} in the template. The images model has a foreign key to the Task.
template:
<form id="post_form" action="" method="post"
enctype="multipart/form-data">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form %}
{{ field }} <br />
{% endfor %}
{{ formset.management_form }}
{% for form in formset %}
{{ form }}
{% endfor %}
<div class="panel-body">
<button type="submit" class="btn btn-primary m-t-10">Submit</button>
</div>
</form>
You should only instantiate the formset with request.POST for POST requests.
if request.method == 'POST':
formset = ImageFormSet(request.POST, request.FILES,
queryset=Images.objects.none())
...
else:
# GET request
formset = ImageFormSet(queryset=Images.objects.none())
...

Extended User model in django not saving profile image

Am trying to create a chat forum in django . but to do this i needed to extend the User Model, But after extending it the profile image does not save
This is my model
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
email = models.EmailField()
img = models.FileField(upload_to='media/', blank=True, null=True)
def __str__(self):
return self.user.username
#receiver(post_save, sender=User)
def update_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
instance.profile.save()
My View:
def signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
user = form.save()
user.refresh_from_db() # load the profile instance created by the signal
user.profile.email = form.cleaned_data.get('email')
user.profile.img = form.cleaned_data.get('img')
user.save()
raw_password = form.cleaned_data.get('password1')
user = authenticate(username=user.username, password=raw_password)
login(request, user)
return redirect('home')
else:
form = SignUpForm()
return render(request, 'tforum/signup.html', {'form': form})
My Forms.py
class SignUpForm(UserCreationForm):
email = forms.EmailField(help_text='Required.')
img = forms.FileField(help_text='Upload Image')
class Meta:
model = User
fields = ('username', 'email', 'img', 'password1', 'password2', )
Signup.html
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{% for field in form %}
<p>
{{ field.label_tag }}<br>
{{ field }}
{% if field.help_text %}
<small style="color: grey">{{ field.help_text }}</small>
{% endif %}
{% for error in field.errors %}
<p style="color: red">{{ error }}</p>
{% endfor %}
</p>
{% endfor %}
<button type="submit">Sign up</button>
settings.py
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
The problem is that the user is not created.
If i remove the img from the code the user saves.
I have stripped away most of the styling
you should create a profileForm
class ProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = ('email', 'img')
and update your signup.py
def update_signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
profile_form = ProfileForm(request.POST, instance=request.user.profile)
if form.is_valid() and profile_form.is_valid():
user = form.save()
user.refresh_from_db() # load the profile instance created by the signal
user.profile.email = form.cleaned_data.get('email')
user.profile.img = form.cleaned_data.get('img')
profile_form.save()
user.save()
raw_password = form.cleaned_data.get('password1')
user = authenticate(username=user.username, password=raw_password)
login(request, user)
return redirect('home')
else:
form = SignUpForm()
return render(request, 'tforum/signup.html', {'form': form})

Categories

Resources