Not able to upload image in Django Model.
I have installed Pillow , added MEDIA_URL and MEDIA_ROOT to my settings, added
static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) to my urls.py .
forms.py:
class PostForm(forms.ModelForm) :
class Meta :
model = Post
fields = ['name', 'image', 'description', 'age', 'cost', 'address', 'seller', 'phone', ]
post_edit.html:
{% extends 'blog/base.html' %}
{% block content %}
<h2>New post</h2>
<form method="POST" class="post-form">{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-default">Save</button>
</form>
{% endblock %}
models.py:
image = models.ImageField(upload_to='images/', null=True, blank=True)
urls.py:
path('edit/', views.post_edit, name='post_edit'),
views.py:
#login_required
def post_edit(request, pk) :
post = get_object_or_404(Post, pk=pk)
if request.method == "POST" :
form = PostForm(data=request.POST, files=request.FILES, instance=post)
if form.is_valid() :
post = form.save(commit=False)
post.save()
return redirect('post_detail', pk=post.pk)
else :
form = PostForm(instance=post)
return render(request, 'blog/post_edit.html', {'form' : form})
If I add an image to a new object , the image is not uploaded to media/images/ .
With my modest level of understanding ,I'm not able to find the mistake . Can anyone help me please?
You need to add enctype="multipart/form-data" form attribute to your template:
<form method="POST" class="post-form" enctype="multipart/form-data">{% csrf_token %}
From the doc:
Note that request.FILES will only contain data if the request method
was POST and the that posted the request has the attribute
enctype="multipart/form-data"
Related
I was getting that same error while click the like button, But the error was solved..
again after creating comment view and its other staff I'm getting that error again...When I click the comment button then the error appears..I'm very new to Django,,, help me please..
My project models.py, template page, urls.py, views.py are attached herewith
**models.py**
from email.policy import default
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Blog(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=200, verbose_name="Put a Title")
blog_content = models.TextField(verbose_name="What is on your mind")
blog_image = models.ImageField(upload_to="blog_images", default = "/default.png")
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
class Comment(models.Model):
blog = models.ForeignKey(Blog, on_delete=models.CASCADE, related_name = "blog_comment" )
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name = "user_comment")
comment = models.TextField()
comment_date = models.DateField(auto_now_add=True)
def __str__(self):
return self.comment
class Like(models.Model):
blog = models.ForeignKey(Blog, on_delete=models.CASCADE, related_name = "blog_liked")
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name = "user_liked")
class Unlike(models.Model):
blog = models.ForeignKey(Blog, on_delete=models.CASCADE, related_name = "blog_unliked")
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name = "user_unliked")
**blog_page.html**
{% extends "main.html" %}
{% load static %}
{% load crispy_forms_tags %}
{% block content %}
<div style="text-align:center;">
<h2>{{blog.title}}</h2>
<img src="{{blog.blog_image.url}}" alt="" width="630px" height="300px">
</div>
<div style="text-align:center;">
{{blog.blog_content|linebreaks}}
</div>
{% if not liked and not unliked %}
<h4> Like </h4>
<h4>Unlike</h4>
{% elif unliked %}
<h4> Like </h4>
{% elif liked %}
<h4>Unlike</h4>
{% endif %}
<div>
<h4>
Comments:
</h4>
{% for comment in comments %}
<div>
{{ user }} <br>
<h5>{{ comment }}</h5>
</div>
{% endfor %}
<!-- <h6>Add your comment:</h6> -->
<form action="" method="POST">
{% csrf_token %}
{{form|crispy}} <br>
<a class="btn btn-sm btn-info" href="{% url 'comment' %}">Comment</a>
</form>
</div>
{% endblock content %}
**urls.py**
from django.urls import path
from blog_app import views
urlpatterns = [
path("", views.home, name='home'),
path("blog_page/<str:pk>/", views.blog_view, name='blog_page'),
path("like/<str:pk>/", views.like, name="like"),
path("unlike/<str:pk>/", views.unlike, name="unlike"),
path("comment/", views.comment, name="comment"),
]
**views.py**
from django.shortcuts import render
from . models import Blog, Comment, Like, Unlike
from . forms import CommentForm
# Create your views here.
def home(request):
blogs = Blog.objects.all()
context = {'blogs': blogs}
return render(request, 'blog_app/home.html', context)
def blog_view(request, pk):
blog = Blog.objects.get(id=pk)
form = CommentForm()
comments = Comment.objects.filter(blog=blog)
context = {"blog": blog, "comments": comments, "form":form}
return render(request, 'blog_app/blog_page.html', context)
def like(request, pk):
blog = Blog.objects.get(id=pk)
user = request.user
liked, like = Like.objects.get_or_create(blog=blog, user=user)
context = {"liked" : liked, "blog": blog }
return render(request, "blog_app/blog_page.html", context)
def unlike(request, pk):
blog = Blog.objects.get(id=pk)
user = request.user
unliked, unlike = Unlike.objects.get_or_create(blog=blog, user=user)
context = {"unliked" : unliked, 'blog': blog}
return render(request, "blog_app/blog_page.html", context)
def comment(request):
form = CommentForm()
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
form.save()
context = {}
return render(request, "blog_app/blog_page.html", context)
Your comment button is just a link, is it normal ? I think, you want to submit your form when you click on?
<div>
<h4>
Comments:
</h4>
{% for comment in comments %}
<div>
{{ user }} <br>
<h5>{{ comment }}</h5>
</div>
{% endfor %}
<!-- <h6>Add your comment:</h6> -->
<form action="{% url 'comment' %}" method="POST">
{% csrf_token %}
{{form|crispy}} <br>
<button type="submit" class="btn btn-sm btn-info">Comment</button>
</form>
</div>
And i think, your problem occured because you dispolay this template from comment view without set blog in context data.
def blog_view(request, pk):
blog = Blog.objects.get(id=pk)
form = CommentForm()
comments = Comment.objects.filter(blog=blog)
context = {"blog": blog, "comments": comments, "form":form}
return render(request, 'blog_app/blog_page.html', context)
def comment(request):
form = CommentForm()
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
form.save()
return redirect("blog_page", pk=form.instance.blog.pk)
return HttpResponse(status_code=400) # error case
else:
return HttpResponse(status_code=501) # try to GET page
Better solution is to pass blog pk in the url for being able to render page with error:
path("blog/<int:pk>/comment/", views.comment, name="comment")
<form action="{% url 'comment' blog.pk %}" method="POST">
{% csrf_token %}
{{form|crispy}} <br>
<button type="submit" class="btn btn-sm btn-info">Comment</button>
</form>
def comment(request, pk):
blog = get_object_or_404(Blog, pk=pk)
form = CommentForm()
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
form.save()
return redirect("blog_page", pk=blog.pk)
return render(request, "...", {"blog": blog, "form": form})
I am trying to build a CRM in Django and in doing so I am trying to add a place to add comments to a lead. I created a form and upon submitting a comment I get directed to the 401 page where I am greeted with an error. On the 401 page it references my form.save() in my views. Please help.
401 Error
"Field 'id' expected a number but got 'some'."
. I will post my code below
Below is my info view which is used to display information about a particular lead
def info(request, pk):
info = lead.objects.get(id=pk)
form = lead_comment()
if request.method == 'POST':
form = lead_comment(request.POST)
if form.is_valid():
form.save()
return redirect('info.html')
context={'info':info, 'form': form}
return render(request, 'info.html', context)
My URLS
from django.urls import path
from . import views
urlpatterns = [
path('', views.dashboard, name='dashboard'),
path('leads/', views.leadsPage, name='leads'),
path('docs/', views.docsPage, name='docs'),
path('add-lead/', views.addLead, name='add-lead'),
path('leads/<str:pk>/', views.info, name='description'),
]
My info.html
{% include 'navbar.html' %}
<body class="dash">
<div class="navdash">
<div class="container-lead">
<div class="lead-space">
<h2>{{ info.first }} {{ info.last }}</h2>
<h5>Phone number: {{ info.phnum }}</h5>
<h5>Email: {{ info.email }}</h5>
</div>
<body>
<form method="POST" action="">
{% csrf_token %}
{{ form }}
<input type = "submit" value = "Submit" />
</form>
</body>
</div>
</div>
</body>
My lead model where I have am initializing comment
class lead(models.Model):
first=models.CharField(max_length=20)
last=models.CharField(max_length=20)
email=models.CharField(max_length=30)
phnum=models.CharField(max_length=10)
associate=models.ForeignKey(agent, on_delete=models.CASCADE, default='some' )
comment=models.CharField(max_length=500, blank=True, null=True)
def __str__(self):
return self.first + ' ' + self.last
My Form
class lead_comment(ModelForm):
class Meta:
model=lead
fields=['comment']
Try adding the following lines to your info views:
def info(request, pk):
i = lead.objects.get(id=pk)
form = lead_comment(instance=i)
if request.method == 'POST':
form = lead_comment(request.POST, instance=i)
if form.is_valid():
form.save()
return redirect('info.html')
context={'i':i, 'form': form}
return render(request, 'info.html', context)
This is the error I get when clicking on Edit post under any one of the posts. Would appreciate any help as all this django stuff is confusing me but trying my best to learn. My new post function works and clicking blog/posts to go to the overview page for the blog or to look at all the posts works as well.
NoReverseMatch at /edit_post/1/
Reverse for 'posts' with arguments '(1,)' not found. 1 pattern(s) tried: ['posts/$']
Error during template rendering
In template C:\Users\seng\Desktop\Python projects\c19\nineteen_one\blogs\templates\blogs\base.html, error at line 0
urls.py
"""Defines url paterns for blogs"""
from django.urls import path
from . import views
app_name = 'blogs'
urlpatterns =[
#Home page
path('', views.index, name='index'),
# Page that shows all posts/
path('posts/', views.posts, name='posts'),
#Page for adding a new blogpost
path('new_post/', views.new_post, name='new_post'),
#Page for editing a post
#maybe remove the id?
path('edit_post/<int:post_id>/', views.edit_post, name='edit_post'),
]
views.py
from django.shortcuts import render, redirect
from .models import BlogPost
from .forms import BlogPostForm
# Create your views here.
def index(request):
"""The home page for blogs"""
return render(request, 'blogs/index.html')
def posts(request):
"""Show all blogposts"""
posts = BlogPost.objects.order_by('date_added')
context = {'posts': posts}
return render(request, 'blogs/posts.html', context)
def new_post(request):
"""Add a new blogpost"""
if request.method != 'POST':
#No data submitted; create a blank form.
form = BlogPostForm()
else:
#POST data submitted, process data
form = BlogPostForm(data=request.POST)
if form.is_valid():
form.save()
return redirect('blogs:posts')
#Display a blank or invalid form
context = {'form': form}
return render(request, 'blogs/new_post.html', context)
def edit_post(request, post_id):
"""Edit existing post"""
post = BlogPost.objects.get(id=post_id)
if request.method != "POST":
#Initial request, pre-fill form with the current post
form = BlogPostForm(instance=post)
else:
#Post data submitted, process data
form = BlogPostForm(instance=post, data=request.POST)
if form.is_valid():
form.save()
return redirect('blogs:posts', post_id=post.id)
context = {'post':post, 'form':form}
return render(request, 'blogs/edit_post.html', context)
forms.py
from django import forms
from .models import BlogPost
class BlogPostForm(forms.ModelForm):
class Meta:
model = BlogPost
fields = ['text', 'title']
labels = {'text':'This is the text box', 'title' :"Title here"}
edit_post.html
{% extends "blogs/base.html" %}
{% block content %}
<p>{{ post }}</p>
<p>Edit post:</p>
<form action="{% url 'blogs:edit_post' post.id %}" method='post'>
{% csrf_token %}
{{ form.as_p }}
<button name="submit">Save changes</button>
</form>
{% endblock content %}
posts.html
{% extends "blogs/base.html" %}
{% block content %}
<p>Posts</p>
<ul>
{% for post in posts %}
<li>
<p>{{ post }}</p>
<p>
Edit post
</p>
</li>
{% empty %}
<li>No posts have been added yet.</li>
{% endfor %}
</ul>
Add a new post
{% endblock content %}
new_post.html
{% extends "blogs/base.html" %}
{% block content %}
<p>Add a new post:</p>
<form action="{% url 'blogs:new_post' %}" method='post'>
{% csrf_token %}
{{ form.as_p }}
<button name="submit">Add post</button>
</form>
{% endblock content %}
The issue is with this line in edit_post.html:
<p>{{ post }}</p>
If you are editing the post with id 1, then this link is to the url /posts/1. But that has no match in your urls.py file.
Either you need to remove the post.id parameter from the link, or create a view and a corresponding path in urls.py for this link.
I am using a modelformset_factory method with forms containing only an ImageField. The Model the forms are based on contains a user field that has a many-to-one relationship with a User Model that extends AbstractUser(See Extending User Model with Abstract User). Currently, each instance of a user has a correlating User Profile, but I would also like to allow the user to upload a gallery of images to their profile.
models.py
class Gallery(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
image = models.ImageField(upload_to='user_gallery', blank=True, null=True)
def create_gallery(sender, **kwargs):
if kwargs['created']:
user_gallery = Gallery.objects.create(user=kwargs['instance'])
user_gallery.save();
post_save.connect(create_gallery, sender=User)
forms.py
class GalleryForm(forms.ModelForm):
image = forms.ImageField(label='FormImage')
class Meta:
model = Gallery
fields = ['image']
views.py
def EditProfile(request):
GalleryFormSet = modelformset_factory(Gallery, form=GalleryForm, extra=3, max_num=3)
if request.method == "POST":
formset = GalleryFormSet(request.POST, request.FILES)
if formset.is_valid():
for form in formset.cleaned_data:
my_image = form['image']
photo = Gallery(user=request.user, image=my_image)
photo.save()
return render(request, 'user_handler/editprofile.html', {'formset': formset})
else:
formset = GalleryFormSet()
return render(request, 'user_handler/editprofile.html', {'formset': formset})
Template
<form id="post_form" method="post" action="" enctype="multipart/form-data">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
{{form.image}}
<img src="{{form.image.url}}"/>
{% endfor %}
<input type="submit" name="submit" value="Submit" />
</form>
The problem I'm have is that using {{ form.image }} produces this result:
... and using {{ form.image.url }} within an image's source tag produces absolute nothing at all. When I inspect the element I contain it in, it states the source is unknown. Obviously, the images are being saved in the DB as I'd like, but I can't get the .url functionality to work. And YES, I do have the media root an all defined:
settings.py
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'HighlightPage_Project/media')
urls.py
urlpatterns = [
url(r'^$', views.Login_Redirect),
url(r'^account/', include('user_handler_app.urls')),
url(r'^admin/', admin.site.urls),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Try to replace your code with the following code:
<img src="{{form.image.url}}"/>
with:
<img src="{{form.instance.image.url}}"/>
Try to replace your code with the following code:
views.py
def EditProfile(request):
GalleryFormSet = modelformset_factory(Gallery, form=GalleryForm, extra=3, max_num=3)
if request.method == "POST":
formset = GalleryFormSet(request.POST, request.FILES)
if formset.is_valid():
for form in formset.cleaned_data:
my_image = form['image']
photo = Gallery(user=request.user, image=my_image)
photo.save()
return render(request, 'user_handler/editprofile.html', {'formset': formset})
else:
user_images = Gallery.objects.filter(user=request.user)
initial_images = [{'image': i.image, 'image_url': i.image.url} for i in user_images if i.image]
formset = GalleryFormSet(initial=initial_images)
return render(request, 'user_handler/editprofile.html', {'formset': formset})
Template
<form id="post_form" method="post" action="" enctype="multipart/form-data">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
{{form.image}}
<img src="{{form.initial.image_url}}"/>
{% endfor %}
<input type="submit" name="submit" value="Submit" />
I cannot add a file in Django. When I click the "save" button, it does not save the database.
This is my view.py:
def add_product(request):
if request.method == "POST":
form = PostForm(request.POST, request.FILES)
if form.is_valid():
post = form.save(commit=False)
post.userprofile = request.user
post.save()
return redirect('kerajinan.views.add_product', pk=post.pk)
else:
form = PostForm()
return render(request, 'kerajinan/add_product.html', {'form': form})
add_product.html:
{% block content %}
<h1>New Product</h1>
<from method="POST" class="post-form" enctype="multiple/form-data">{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-default">Save</button>
</from>
{% endblock %}
forms.py:
class PostForm(forms.ModelForm):
class Meta:
model = Product
fields = ('category','title', 'price','image', 'description')
and urls.py:
url(r'^add_product/$', views.add_product, name='add_product'),
Can you help me solve my problem?
You need to change your enctype to: enctype="multipart/form-data"
Your current value (multiple/form-data), is not a valid method of encoding.
From the docs:
Note that request.FILES will only contain data if...the <form> that posted the request has the attribute enctype="multipart/form-data". Otherwise, request.FILES will be empty.