Handling images using django forms - python

I'm trying to upload image using django forms, and then assign it to my model object image field.
forms.py
class MemberRegistrationForm(forms.ModelForm):
birthday=forms.DateField(input_formats=settings.DATE_INPUT_FORMATS)
class Meta:
model=Member
fields=('birthday','photo',)
models.py
class Member(models.Model):
user=models.OneToOneField(settings.AUTH_USER_MODEL,on_delete=models.CASCADE)
birthday=models.DateField(blank=True,null=True)
photo=models.ImageField(upload_to='account/%Y/%m/%d',blank=True)
def __str__(self):
return "{} /'s profile ".format(self.user.username)
urls.py
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT)
Parsing form page
<form class="" action="." method="post">
{{form.as_p}}
{{form_member.as_p}}
{% csrf_token %}
<input type="submit" name="" value="Create my account">
</form>
Display page
<img width="90px;" height="180px;"src="{{member.photo.url}}" alt="">
views.py
I guess problem is here.I can not extract the uploaded image from form and assign it to my model object field
def user_signup(request):
if request.method == 'POST':
form = UserRegistrationForm(request.POST)
form_member=MemberRegistrationForm(request.POST,request.FILES)
if form.is_valid() and form_member.is_valid():
user=form.save(commit=False)
user.set_password(
form.cleaned_data['password']
)
user.save()
member=Member.objects.create(user=user,
photo=request.FILES['photo'], #HERE I'M NOT SURE IF THIS THE RIGHT WAY OR NOT
birthday=form_member.cleaned_data['birthday'])
return render(request,
'account/registeration_done.html',
{'user':user,
'member':member,
'form':form,
'form_member':form_member,
})

You have to specify enctype="multipart/form-data" in your html markup.
Also, you can find the work example upload form here
https://github.com/miletskiy/FortyTwoTestTask/blob/master/apps/hello/templates/edit_applicant.html#L20

Related

How can I view the pdf file in Django?

Note:
My model table consists of id field and File field which will be pdf.
I am inserting data into the model using django admin.(I have no custom upload form)
I am trying to view the pdf in the browser(as it normally opens in chrome).
I am trying to find the file by taking the id field(by user) in a custom HTML template using a form(Please look at the codes mentioned below.)
I am attaching the urls.py, index.html, views.py, models.py and forms.py codes below. Please patiently go through and let me the know the problem and the solution.
I think my code should work but I am getting a Suspicious File Operation Error.
urls.py
urlpatterns = [
path('',views.index),
path('admin/', admin.site.urls),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
views.py
def index(request):
if request.method == "POST":
form = Form(request.POST)
if form.is_valid():
id=request.POST.get("id")
ans = query.objects.get(id=id)
response=ans.repo
if ans is None:
return redirect("index.html")
else:
#return render (request,"ans.html",{'ans':response})
return redirect(response)
else:
form = Form()
return render(request,"index.html",{'form':form})
forms.py
class Form(forms.Form):
id = forms.CharField(label="Report ID", max_length=100)
models.py
class query(models.Model):
id=models.IntegerField(primary_key=True)
repo=models.FileField(upload_to='documents/')
index.html
<!-- Search Form -->
<form id="signup-form" method="POST" action="">
{% csrf_token %}
{{form}}
<input type="submit" value="Check" />
</form>
The URL for a file field is in the url attribute, so you need to use ans.repo.url.

Django - Comment form in an existing template. How to define it in views.py?

I have 4 models: Post, Comment, Blogger and User.
I have an post_description template, in below of that, I have placed a comment form.
But how to define it in views? My problem is - to get its username, like the user who is logged in will be stored as "posted_by" and in which blog post he post will be stored as "topic" of the blog.
How to store these information, so they get automatically added?
Form that i has described in post_desc.html
{% if user.is_authenticated %}
<form method="post">
{% csrf_token %}
<input type="text" name="comment" style="width: 800px; height: 145px;">
<button type="submit">Submit Comment</button>
</form>
{% else %}
<p>Login to comment</p>
{% endif %}
Current view of that post_desc:
def post_desc(request, pk):
post = get_object_or_404(Post, pk=pk)
return render(request, 'post_desc.html', {'post': post})
Now the user can be accessed as follows in the views:
user = request.user
And about the Topic, maybe you could add a hidden input in your form to get blog id , as you are already passing the post in the form template. :
<form method="post">
{% csrf_token %}
<input type="text" name="comment" style="width: 800px; height: 145px;">
<input type="hidden" name="topic" value="{{ post.id }}">
<button type="submit">Submit Comment</button>
And when posted in the view you can get blog by:
post_id = request.POST.get('topic')
post = get_object_or_404(Post, pk=post_id)
And then finally proceeding with your actual flow.
I think what you need here is basic model form setup.
I am hoping there is a blog entry and comments associated with it and you want a commenting functionality on each post.
This is rough quick answer.
Your models.py looks like this:
from django.db import models
from django.conf import settings
class Comments(models.Model):
posted_by = models.ForeignKey(settings.AUTH_USER_MODEL)
topic = models.ForeignKey(Blog)
comment = models.TextField()
last_modified = models.DateTimeField(auto_now=True)
created_on = models.DateTimeField(auto_now_add=True)
You setup a model form in your forms.py
from django.forms import ModelForm
from .models import Comments
class CommentForm(ModelForm):
class Meta:
model = Comments
fields = ['comment']
You setup a model form post view.
#login_required
#require_http_methods(["POST"])
def post_comments_controller(request, identifier):
from .forms import CommentForm
comment_form = CommentForm(request.POST or None)
if comment_form.is_valid():
comment_obj = comment_form.save(commit=False)
topic = Blog.objects.get(id=identifier)
comment_obj.posted_by = request.user
comment_obj.item = topic
comment_obj.save()
return HttpResponse("Done")
else:
return HttpResponseBadRequest()
You setup a entry point in your urls.py
from django.conf.urls import patterns, url
from django.conf import settings
urlpatterns = patterns('',
url(r'^/blog/(?P<identifier>[d]+)/comment$',
'views.post_comments_controller', name='post_comment')
)
And your finally the html form
{% if user.is_authenticated %}
<form method="POST" action="{% url 'post_comment' blog.id %}">
{% csrf_token %}
<input type="text" name="comment" style="width: 800px; height: 145px;">
<button type="submit">Submit Comment</button>
</form>
{% else %}
<p>Login to comment</p>
{% endif %}
This is not tested overall. Let me know.
From Django docs you can use FormMixin with DetailView like this:
class AuthorInterestForm(forms.Form):
message = forms.CharField()
class AuthorDetail(FormMixin, DetailView):
model = Author
form_class = AuthorInterestForm
def get_success_url(self):
return reverse('author-detail', kwargs={'pk': self.object.pk})
def post(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return HttpResponseForbidden()
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
# Here, we would record the user's interest using the message
# passed in form.cleaned_data['message']
return super().form_valid(form)

Cannot upload profile picture in django model

I want the user to upload the profile picture on the profile page but it is not storing it in the media/documents folder, and yes, I have put enctype="multipart/form-data" in the html form and the method is post. I'm new to django so please provide a simple solution
models.py
class User(models.Model):
first_name=models.CharField(max_length=20)
last_name=models.CharField(max_length=20)
username=models.CharField(max_length=25, primary_key=True)
password=models.CharField(max_length=15)
email_id=models.CharField(max_length=30, default='NULL')
profile_pic=models.ImageField(upload_to='profilepics/%Y/%m/%d/',height_field=200,width_field=200,default='')
forms.py
class ProfilePicForm(forms.ModelForm):
class Meta:
model=User
fields=['username','profile_pic']
views.py
def upload(request):
if request.method == 'POST':
username=request.POST['username']
m=User(username=username)
m.profile_pic=request.FILES['profile_pic']
m.save()
return render(request,'LoginPage/done.html')
else:
pic=ProfilePicForm()
return render(request,'AfterLogin/profile.html')
html file
<form method="POST" enctype="multipart/form-data" action="{% url 'LoginPage:upload' %}">
{% csrf_token %}
<p>Upload your profile photo</p><br>
<input id="id_image" type="file" class="" name="image">
<input type="hidden" name="username" value="{{ username }}">
<input type="submit" value="Submit"/>
</form>
Have a look at this:
Need a minimal Django file upload example
Also, try sharing the error you are getting when trying to upload picture.
I think it would be better for you to use the standard User model created by Django which already has the fields first_name, last_name, username, password and email. Then you create a new model with a OneToOneField with the model user.
If the image uploads and if you get a 404 when going directly to the image url when running the server, then you have forgotten to serve the image, which you have to do when you are in production phase.
urlpatterns = [
...patterns...
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Something like this should work:
modles.py
from django.contrib.auth.models import User
class UserPicture(models.Model):
user = models.OneToOneField(User, on_delete = models.CASCADE)
picture = models.ImageField(upload_to='...')
forms.py
class ProfilePicForm(forms.ModelForm):
class Meta:
model = UserPicture
fields=['profile_pic']
views.py
def your_view(request):
...
if request.method == 'POST':
form = UserPicture(request.POST, request.FILES)
if form.is_valid():
userprofile = form.save()
userprofile.user = request.user
userprofile.save()
...
You don't have to define own User model since Django has it's own: https://docs.djangoproject.com/en/1.10/ref/contrib/auth/#user-model
And as Jonatan suggested - post error code. If there's none, remove this try ... except: pass.

Image not being uploaded//something wrong with python code in my views.py probably

Hello I followed steps here;Need a minimal Django file upload example I'm not sure what I did wrong. I'm trying to add a feature that user to be able to post pictures as well. Here's my try
settings.py
MEDIA_ROOT = os.path.join(os.path.dirname(BASE_DIR), "static_in_env", "media_root")
MEDIA_URL = '/media/'
models.py
class Category(models.Model):
image = models.ImageField(upload_to='images',blank=True, null=True)
forms.py
class CategoryForm(forms.ModelForm):
name = forms.CharField(max_length=128)
description = forms.CharField(max_length=300)
image = forms.ImageField()
class Meta:
model = Category
my views.py
#login_required
def add_category(request):
if not request.user.is_superuser and Category.objects.filter(author=request.user).exists():
return render(request,'main/category_already_exists.html')
if request.method == 'POST':
category = Category(author=request.user)
form = CategoryForm(request.POST, instance=category)
if form.is_valid():
form.save(commit=True)
return redirect('index')
else:
form = CategoryForm()
return render(request, 'main/add_category.html', {'form':form})
category.html
{% load staticfiles %}
{{category.image}}
I am assuming you are missing enctype form attribute in your template.
<form method="POST" enctype="multipart/form-data">
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
Also, in your views, instantiating your form should be
form = CategoryForm(request.POST, request.FILES, instance=category)

Django UpdateView / ImageField issue: not returning new uploaded image

model:
class Logo(models.Model):
media = models.ImageField(upload_to='uploads')
def __unicode__(self):
return self.media.url
view:
class LogoEdit(UpdateView):
model = Logo
template_name = 'polls/logo-edit.html'
success_url = '/polls/logos/'
def form_valid(self, form):
pdb.set_trace()
template:
<form id="my_form" action="" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Save Changes" />
</form>
selecting new image:
form
debug view:
existing image:
(Pdb) self.object
<Logo: media/uploads/DSCN0844.JPG>
form with new selected image (DSC_0021.JPG):
(Pdb) test = form.save()
(Pdb) test
<Logo: media/uploads/DSCN0844.JPG>
As you can see the original image remains in form!
If you are using UpdateView, you only need to add enctype="multipart/form-data" attribute to the form tag in your template. The rest will be handled by UpdateView class.
You need to save the form providing request.FILES:
if request.method == 'POST':
form = MyForm(request.POST, request.FILES)
if form.is_valid():
form.save()
And in your HTML form (since you have an <input type="file"> in the form):
<form method="POST" enctype="multipart/form-data">
just add to your template
<form method="POST" enctype="multipart/form-data">

Categories

Resources