upload file using django form - python

Can anyone help me find my mistake.I am new to django.I want to upload a image using form.
#forms.py
class ProfileFormSt(forms.Form):
image_url = forms.FileField(required=False)
#views.py
class UpdateProfileStView(FormView):
template_name = "home/member_st_form.html"
def get(self, request, id):
user = User.objects.get(id=self.kwargs['id'])
profile = StudentProfile.objects.get(user=user)
form = ProfileFormSt(initial={
'image_url': profile.propic,
})
return render(request, self.template_name, {'form': form})
def post(self, request, id):
user = User.objects.get(id=self.kwargs['id'])
form = ProfileFormSt(request.POST, request.FILES)
profile = StudentProfile.objects.get(user=user)
if request.POST.get('image_url'):
profile.propic = request.POST.get('image_url')
profile.save()
return redirect('home:member-profile-st', id)
#member_st_form.html
<form action="" method="post" enctype="multipart/form-data">{% csrf_token %} {{ form.as_p }}
<button type="submit">update</button>
</form>
#models.py
class StudentProfile(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
propic = models.FileField(default="profile-icon.png")
request.POST.get('image_url') always returns empty...cant find what I did wrong...

Your image_url is a file field, so it should be present in request.FILES
if request.FILES['image_url']:
profile.propic = request.FILES['image_url']

Related

redirect on the same post_id after edit post

I have created a forum website in Django where users can post Questions/Answers and edit them.
After editing the reply I want to redirect the user to the currently edited post page. like if user
edit reply which has been posted on the question with id 4 (which url is (http://127.0.0.1:8000/discussion/4)) then after edited it should redirect to the same URL. After editing, and deleting the reply I am redirecting the user to the forum homepage but I want to redirect to the /discussion/{post_id} URL(which is URL of the particular post on which reply being edited and deleted)
urls.py
app_name = "dashboard"
urlpatterns = [
path('', views.index, name="index"),
path('user_home', views.user_home, name="user_home"),
path('admin_home', views.admin_home, name="admin_home"),
path("forum", views.forum, name="forum"),
path("discussion/<int:myid>", views.discussion, name="discussion"),
path("showallusers", views.show_all_users, name="showallusers"),
path('delete_user/<int:pk>', views.delete_user, name="delete_user"),
path('delete_post/<int:pk>', views.delete_post, name="delete_post"),
path('delete_reply/<int:pk>', views.delete_reply, name="delete_reply"),
path('upload_notes', views.upload_notes, name='upload_notes'),
path('view_mynotes', views.view_mynotes, name='view_mynotes'),
path('delete_mynotes/<int:pk>/', views.delete_mynotes, `name='delete_mynotes'), `
path('pending_notes', views.pending_notes, name='pending_notes'),
path('assign_status/<int:pk>', views.assign_status, name='assign_status'),
path('accepted_notes', views.accepted_notes, name='accepted_notes'),
path('rejected_notes', views.rejected_notes, name='rejected_notes'),
path('all_notes', views.all_notes, name='all_notes'),
path('delete_notes/<int:pk>', views.delete_notes, name='delete_notes'),
path('delete-records/', views.delete_notes, name='delete_notes'),
path('view_allnotes', views.view_allnotes, name='view_allnotes'),
path('notessharing', views.notessharing, name='notessharing'),
path('edit_post/<int:pk>/', views.edit_post, name='edit_post'),
path('edit_reply/<int:pk>/', views.edit_reply, name='edit_reply'),
]
delete_reply code
def delete_reply(request, pk=None):
reply = Replie.objects.filter(id=pk)
reply.delete()
return redirect('/forum')
After deleting a reply from a post I want to redirect to the same post.
models.py
class Post(models.Model):
user1 = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
post_id = models.AutoField
post_content = models.TextField(max_length=5000,verbose_name="")
timestamp= models.DateTimeField(default=now)
image = models.ImageField(upload_to="images",default="")
def __str__(self):
return f'{self.user1} Post'
class Replie(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
reply_id = models.AutoField
reply_content = models.TextField(max_length=5000,verbose_name="")
post = models.ForeignKey(Post, on_delete=models.CASCADE, default='')
timestamp= models.DateTimeField(default=now)
image = models.ImageField(upload_to="images",default="")
def __str__(self):
return f'{self.user1} Post'
views.py
def forum(request):
user = request.user
profile = Profile.objects.all()
if request.method=="POST":
form=PostContent(request.POST)
if form.is_valid():
user = request.user
image = request.user.profile.image
content = request.POST.get('post_content','')
post = Post(user1=user, post_content=content, image=image)
post.save()
messages.success(request, f'Your Question has been posted successfully!!')
return redirect('/forum')
else:
form=PostContent()
posts = Post.objects.filter().order_by('-timestamp')
form= PostContent()
context={
'posts':posts,
'form':form
}
return render(request, "forum.html",context)
def discussion(request, myid):
post = Post.objects.filter(id=myid).first()
replies = Replie.objects.filter(post=post)
if request.method=="POST":
form=ReplyContent(request.POST)
if form.is_valid():
user = request.user
image = request.user.profile.image
desc = request.POST.get('reply_content','')
post_id =request.POST.get('post_id','')
reply = Replie(user = user, reply_content = desc, post=post, image=image)
reply.save()
messages.success(request, f'Your Reply has been posted successfully!!')
return redirect(f'/discussion/{post_id}')
else:
form=ReplyContent()
form= ReplyContent()
return render(request, "discussion.html", {'post':post, 'replies':replies,'form':form})
def edit_reply(request, pk):
reply = Replie.objects.get(id=pk)
if request.method == 'POST':
form = UpdateReplyForm(request.POST, instance=reply)
if form.is_valid():
form.save()
messages.success(request,"Reply updated successfully!")
return redirect('/forum')
else:
form = UpdateReplyForm(instance=reply)
context = {
'form': form
}
return render(request, 'edit_reply.html', context)
edit_post view
def edit_post(request, pk):
post = Post.objects.get(id=pk)
if request.method == 'POST':
form = UpdatePostForm(request.POST, instance=post)
if form.is_valid():
form.save()
messages.success(request, "Post updated successfully!")
return redirect('/forum')
else:
form = UpdatePostForm(instance=post)
context = {
'form': form
}
return render(request, 'edit_post.html', context)
Currently, after editing the reply, I am redirecting the user to the post home page but I want to redirect to /discussion/{post_id}.
Template code:
edit_reply.html
{% load static %}
{% block body %}
{% load crispy_forms_tags %}
<div class="container ">
<form method="POST">
<div class="form-group">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4 mt-4 f2" >Update Reply</legend>
</fieldset>
<label style="font-size:1rem; font-weight:bold;">Reply Content</label>
{{form|crispy}}
<input type="hidden" name="post_id" value="{{post_id}}">
<div class="form-group">
<button href="" class="btn btn-primary" type="Update">
Update
</button>
</div>
</div>
</form>
</div>
{% endblock body %}
You can redirect it to discussion view with its pk by passing args=[reply.post.id] in edit_reply view.
Try this:
views.py
from django.shortcuts import render, redirect
from django.urls import reverse
def edit_reply(request, pk):
reply = Replie.objects.get(id=pk)
if request.method == 'POST':
form = UpdateReplyForm(request.POST, instance=reply)
if form.is_valid():
form.save()
messages.success(request, "Reply updated successfully!")
return redirect(reverse('dashboard:discussion', args=[reply.post.id]))
else:
form = UpdateReplyForm(instance=reply)
context = {
'form': form
}
return render(request, 'home/edit_reply.html', context)
Note: Forms in django required Form to be the suffix, so it will be better if it changed to PostContentForm and ReplyContentForm from PostContent and ReplyContent respectively.
It must be return f'{self.user} Post' not
return f'{self.user`} Post'
As it is not any field in Replie model.
Note: ForeignKey's names are generally written in its own name and that too in snake_case, it will be better if you change user1 to user in Post model.
For better understanding:
If table name is PizzaTopingCategory so while creating ForeignKey you should name it as pizza_toping_category=models.ForeignKey(PizzaTopingCategory, on_delete=models.CASCADE)
Edit:
You need to find out post_id, so you can send it through:
Try this in the delte_reply view:
def delete_reply(request, pk=None):
reply = Replie.objects.filter(id=pk)
reply_instance = get_object_or_404(Replie,id=pk)
post_pk=reply_instance.post.id
reply.delete()
return redirect(reverse('dashboard:discussion', args=[post_pk]))
For passing pk in discussion view, you should write return redirect(reverse('dashboard:discussion', args=[reply.post.id])) in edit_post view:
views.py
def edit_post(request, pk):
post = Post.objects.get(id=pk)
if request.method == 'POST':
form = UpdatePostForm(request.POST, instance=post)
if form.is_valid():
form.save()
messages.success(request, "Post updated successfully!")
return redirect(reverse('dashboard:discussion', args=[post.id]))
else:
form = UpdatePostForm(instance=post)
context = {
'form': form
}
return render(request, 'home/edit_post.html', context)

how I can insert and update (edit) latitude and long using (form.py) python Django

I want to insert latitude and long using python Django. I use code but does not work when click on the button it shows null in DB.
models.py
class UserLocation(models.Model):
map_id = models.AutoField(primary_key=True)
map_u_address = models.CharField(max_length=250, null=True)
latitude = models.DecimalField(max_digits=11, decimal_places=7, null=False, blank=True)
longitude = models.DecimalField(max_digits=11, decimal_places=7, null=False, blank=True)
view.py
def save_location(request):
if request.method == 'POST':
form = request.POST
latitude = form.get('latitude')
longitude = form.get('longitude')
user_id = request.session['user_id']
insert_data = UserLocation.objects.create( latitude=latitude,longitude=longitude,
)
if insert_data:
json_data = {'msg': "Insert data successfully", 'state_val': 1}
return JsonResponse(json_data)
else:
json_data = {'msg': "Data not saved", 'state_val': 2}
return JsonResponse(json_data)
else:
return render(request, 'map_1.html')
how I can do an update (edit) for latitude and long using (form.py) python Django?
In forms.py
from django.forms import ModelForm
# Import your UserLocation model
from .models import UserLocation
# Create your forms here
class UserLocationForm(ModelForm):
class Meta:
model = UserLocation
fields = ('latitude', 'longitude')
In views.py
from .forms import UserLocationForm
def save_location(request):
form = UserLocationForm()
context = {}
context['form'] = form
if request.method == 'POST':
form = UserLocationForm(request.POST)
user_id = request.session['user_id']
if form.is_valid():
insert_data = form.save()
if insert_data:
json_data = {'msg': "Insert data successfully", 'state_val': 1}
return JsonResponse(json_data)
else:
json_data = {'msg': "Data not saved", 'state_val': 2}
return JsonResponse(json_data)
else:
# Update form in context dictionary
context['form'] = form
# Re-render page with prefilled data
return render(request, 'map_1.html', context)
else:
return render(request, 'map_1.html', context)
In template
<form action="" method="post">
{% csrf_token %}
{{ form }}
<input type="submit">
</form>
For Updating location
In views.py
def update_location(request, location_id):
try:
# Get location from db for location_id
location = UserLocation.objects.get(id=location_id)
except UserLocation.DoesNotExist:
return # redirect user back as the location id is invalid
# Populate the form with data of requested instance
form = UserLocationForm(instance=location)
context = {}
context['form'] = form
if request.method == 'POST':
form = UserLocationForm(request.POST)
user_id = request.session['user_id']
if form.is_valid():
form.save()
return # Redirect user to somewhere
# When the posted data is invalid
else:
# Update form in context dictionary
context['form'] = form
# Re-render page with prefilled data
return render(request, 'update_location.html', context)
else:
return render(request, 'update_location.html', context)
In update_location.html
{% block body %}
<div class="container-fluid">
<form method="POST" action="">
{% csrf_token %}
{{ form }}
<input type="submit" value="Upload" class="btn btn-primary">
</form>
</div>
{% endblock body %}
In urls.py
path('update_location/<int:location_id>/', views.update_location, name="update-location"),

How to Update ImageField in Django?

i am new in Django. i am having issue in updating ImageField.i have following code
in models.py
class ImageModel(models.Model):
image_name = models.CharField(max_length=50)
image_color = models.CharField(max_length=50)
image_document = models.ImageField(upload_to='product/')
-This is My forms.py
class ImageForm(forms.ModelForm):
class Meta:
model = ImageModel
fields = ['image_name', 'image_color' , 'image_document']
in Html file (editproduct.html)
<form method="POST" action="/myapp/updateimage/{{ singleimagedata.id }}">
{% csrf_token %}
<input class="form-control" type="text" name="image_name" value="{{ singleimagedata.image_name}}">
<input class="form-control" type="file" name="image_document">
<button type="submit" class="btn btn-primary">UPDATE PRODUCT</button>
</form>
-myapp is my application name. {{singleimagedata}} is a Variable Containing all fetched Data
-urls.py
urlpatterns = [
path('productlist', views.productlist, name='productlist'),
path('addproduct', views.addproduct, name='addproduct'),
path('editimage/<int:id>', views.editimage, name='editimage'),
path('updateimage/<int:id>', views.updateimage, name='updateimage'),
]
and Here is My views.py
def productlist(request):
if request.method == 'GET':
imagedata = ImageModel.objects.all()
return render(request,"product/productlist.html",{'imagedata':imagedata})
def addproduct(request):
if request.method == 'POST':
form = ImageForm(request.POST, request.FILES)
if form.is_valid():
form.save()
messages.add_message(request, messages.SUCCESS, 'Image Uploaded')
return redirect('/myapp/productlist')
else:
imageform = ImageForm()
return render(request, "product/addproduct.html", {'imageform': imageform})
def editimage(request, id):
singleimagedata = ImageModel.objects.get(id=id)
return render(request, 'product/editproduct.html', {'singleimagedata': singleimagedata})
def updateimage(request, id): #this function is called when update data
data = ImageModel.objects.get(id=id)
form = ImageForm(request.POST,request.FILES,instance = data)
if form.is_valid():
form.save()
return redirect("/myapp/productlist")
else:
return render(request, 'demo/editproduct.html', {'singleimagedata': data})
My image Upload is working fine.i can not Update image while updating data.rest of the data are updated.i don't know how to update image and how to remove old image and put new image into directory.
I think you missed the enctype="multipart/form-data", try to change:
<form method="POST" action="/myapp/updateimage/{{ singleimagedata.id }}">
into;
<form method="POST" enctype="multipart/form-data" action="{% url 'updateimage' id=singleimagedata.id %}">
Don't miss also to add the image_color field to your html input.
Because, in your case the image_color field model is designed as required field.
To remove & update the old image file from directory;
import os
from django.conf import settings
# your imported module...
def updateimage(request, id): #this function is called when update data
old_image = ImageModel.objects.get(id=id)
form = ImageForm(request.POST, request.FILES, instance=old_image)
if form.is_valid():
# deleting old uploaded image.
image_path = old_image.image_document.path
if os.path.exists(image_path):
os.remove(image_path)
# the `form.save` will also update your newest image & path.
form.save()
return redirect("/myapp/productlist")
else:
context = {'singleimagedata': old_image, 'form': form}
return render(request, 'demo/editproduct.html', context)
I had a similar issue while updating the profile_pic of user. I solved this with the following code I think this might help:
Models.py
class Profile(models.Model):
# setting o2o field of user with User model
user_name = models.OneToOneField(User, on_delete=models.CASCADE, blank=True, null=True)
first_name = models.CharField(max_length=70, null=True, blank=True)
last_name = models.CharField(max_length=70, null=True, blank=True)
profile_pic = models.ImageField(upload_to="images", blank=True, null=True,)
def __str__(self):
return str(self.user_name)
forms.py
class ProfileEditForm(ModelForm):
class Meta:
model = Profile
fields = '__all__'
# excluding user_name as it is a one_to_one relationship with User model
exclude = ['user_name']
views.py
#login_required(login_url='login')
def edit_profile(request, id):
username = get_object_or_404(Profile, id=id)
extended_pro_edit_form = ProfileEditForm(instance=username)
if request.method == "POST":
extended_pro_edit_form = ProfileEditForm(request.POST, request.FILES, instance=username)
if extended_pro_edit_form.is_valid():
extended_pro_edit_form.save()
next_ = request.POST.get('next', '/')
return HttpResponseRedirect(next_)
context = {'extended_pro_edit_form': extended_pro_edit_form}
return render(request, 'edit_profile.html', context)
edit-profile.html
<form action="" method="post"
enctype="multipart/form-data">
{% csrf_token %}
{{ extended_pro_edit_form.as_p }}
{{ extended_pro_edit_form.errors }}
<!--To redirect user to prvious page after post req-->
<input type="hidden" name="next" value="{{ request.GET.next }}">
<button type="submit">UPDATE</button>
</form>
Answer from #binpy should solve your problem. In addition to your second answer, you could do:
def updateimage(request, id): #this function is called when update data
data = ImageModel.objects.get(id=id)
form = ImageForm(request.POST,request.FILES,instance = data)
if form.is_valid():
data.image_document.delete() # This will delete your old image
form.save()
return redirect("/myapp/productlist")
else:
return render(request, 'demo/editproduct.html', {'singleimagedata': data})
Check delete() method on django docs.
some times something like cached old image is not replaced in the front-end so you might just need to forces refresh by pressing CTRL + F5 or clear your browsing history.
the answer given by #binpy is a needed update so that the files are passed to the back-end.

ModelForm won't create instance of model

I am trying to create a frontend form in my Django site that will allow users to add entries to my SQL database.
But when I use the form nothing happens in my database. What am I doing wrong?
I thought the right way would be to use the ModelForm technique.
My models looks like this:
class Actor(models.Model):
name = models.CharField(max_length=200)
wage = models.IntegerField(default=3100)
def __str__(self):
return self.name
So I wrote this in my forms.py:
from django import forms
from .models import Actor
class ActorForm(forms.ModelForm):
class Meta:
model = Actor
fields = ['name', 'wage']
form = ActorForm()
I then added this to my views.py:
def get_actor(request):
if request.method == 'POST':
form = ActorForm(request.POST)
if form.is_valid():
return HttpResponseRedirect('/scenes/thanks/')
else:
form = ActorForm()
return render(request, 'scenes/actor.html', {'form': form})
def thanks(request):
return render(request, 'scenes/thanks.html',)
And this in a template called actors.html
<form action="/scenes/actor/" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
You have to call the model form's save() method after checking that it's valid:
def get_actor(request):
if request.method == 'POST':
form = ActorForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/scenes/thanks/')
else:
form = ActorForm()
return render(request, 'scenes/actor.html', {'form': form})

Files not uploading in Django form

So I've got a model with several fields, two of them being a photo and a video field. They are both of type FileField. I've already made a form before using the FileField type and everything worked correctly, but for some reason this time it is not. The settings.py is configured correctly, because I can upload a file through another form.
I can go into the Django admin and from there add an image and video for the photo and video field and the new directory is made and the image and video is stored and can be accessed with no problem. I'm a little stumped on this one. Thanks in advance.
Here is my model:
def get_image_path(instance, filename):
return os.path.join('images', str(instance.id), filename)
def get_video_path(instance, filename):
return os.path.join('videos', str(instance.id), filename)
class User(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
email = models.EmailField()
photo = models.FileField(upload_to=get_image_path, blank=True)
video = models.FileField(upload_to=get_video_path, blank=True)
def __unicode__(self):
return self.first_name + ' ' + self.last_name + ' - ' + self.email
Here is my form, which is a ModelForm:
class UserForm(forms.ModelForm):
class Meta:
model = User
And here is the view:
def index(request):
latest_poll_list = Poll.objects.order_by('-pub_date')[:5]
pollform = PollForm()
choiceform = ChoiceForm()
userform = UserForm()
all_users = User.objects.all()
if request.method == 'POST':
pollform = PollForm(request.POST, request.FILES)
choiceform = ChoiceForm(request.POST)
userform = UserForm(request.POST)
if pollform.is_valid():
pollform.comments = pollform.cleaned_data['comments']
pollform.save()
else:
pollform = PollForm()
if choiceform.is_valid():
choiceform.save()
else:
choiceform = ChoiceForm()
if userform.is_valid():
userform.save()
else:
userform = UserForm()
context = {'latest_poll_list': latest_poll_list, 'pollform': pollform,
'choiceform': choiceform, 'userform': userform, 'all_users': all_users}
return render(request, 'polls/index.html', context)
Here is the form associated with the ModelForm:
<form action="{% url 'polls:index' %}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ userform.as_p }}
<input type="submit" value="Submit">
</form>
Make sure you have enctype="multipart/form-data" as an attribute in your form tag.
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
<your form code>
</form>
Some other answers (i.e. this one) indicate you need to pass request.FILES to your Form if you're using a FileField. Is this your problem?
I.e. change this line:
userform = UserForm(request.POST)
to:
userform = UserForm(request.POST, request.FILES)
EDIT:
Django docs here.

Categories