I'm trying to upload profile picture for Django user but it does not work, the other field (website) is working just fine. I tried several solutions found here but I can't find any that worked for me. I don't know what is wrong, I'm just new to Django. I hope you can help me.
models.py
class UserProfile(models.Model):
user = models.OneToOneField(User)
website = models.URLField(blank=True)
picture = models.ImageField(upload_to='profile_images', blank=True)
def __unicode__(self):
return self.user.username
User.profile = property(lambda u: UserProfile.objects.get_or_create(user=u)[0])
views.py
#login_required
def edit_profile(request):
context = RequestContext(request)
if request.method == "POST":
form = UserProfileForm(request.POST,request.FILES, instance=request.user.profile)
if form.is_valid():
form.save()
return HttpResponseRedirect('/rango/profile/')
else:
user = request.user
profile = user.profile
form = UserProfileForm(instance=profile)
return render_to_response('rango/profile_registration.html', {'form':form}, context)
Make sure you have set your MEDIA_ROOT in settings, something like this
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
# Absolute filesystem path to the directory that will hold user-uploaded files.
# Example: "/home/media/media.lawrence.com/media/"
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash.
# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
MEDIA_URL = '/media/'
Also make sure that you created first the MEDIA_ROOT directory. Hope it helps.
Do you created a folder "media" in the root-path of your Django-project?
Here is some information about static files in Django: Django-static-files
In one of my projects I have the following entries in my settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR, "static"),
)
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
And I also created both foldes in the projects root directory.
Otherwise if this does not work, pleas provide more information about your error-log.
Include enctype="multipart/form-data" in your form where you want your users to upload picture.
<form class="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{form.as_table}}
<input type="submit" name="" value="submit">
</form>
I also had the same requirement as yours and this helped.
Related
I've been trying to upload and display the image but it doesn't show the image.
In models.py
class upload(models.Model):
Comments = models.CharField(max_length=200)
img = models.ImageField(upload_to='images/',blank=True)
forms.py
class upl(ModelForm):
class Meta:
model= upload
fields= ['Comments','img']
views.py
def home(request):
form=upl()
if request.method=='POST':
form = upl(request.POST, request.FILES)
if form.is_valid():
Comments = form.cleaned_data['Comments']
img = form.cleaned_data['img']
p=upload(Comments=Comments,img=img)
p.save()
return render(request,'home.html',{'form':form,'up':upload.objects.all(), })
in template
<form method="POST">
{% csrf_token %}
{{form.as_p}}
<br>
<BUTTON TYPE ="SUBMIT">Submit</BUTTON><br>
<br>
</form>
{%for i in up %}
{{i.Comments}}
<img src ="{{i.img}}", alt="">
{%endfor%}
So this is showing comments but not image. I don't know why the image is not showing.
OK. There are a few things going on here.
The models.py and forms.py are fine.
The views.py needs to look like this. I have commented out your code and added a single line. Basically, I think what is going wrong here is that you are instantiating the model 'upload' and saving, this only saves the 'Comments' field and does not handle the file. Executing the .save() method on the form object resolves this issue.
def imagetest(request):
form=upl()
if request.method=='POST':
form = upl(request.POST, request.FILES)
if form.is_valid():
form.save()
# Comments = form.cleaned_data['Comments']
# img = form.cleaned_data['img']
# p=upload(Comments=Comments,img=img)
# p.save()
return render(request,'home.html',{'form':form,'up':upload.objects.all(), })
Now on to displaying the images. Firstly, you will need to modify your settings to recognise Media files. Modify your settings.py file to define values for the media file location and presentation.
Add these lines to the bottom.
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'mediafiles')
You can, of course, pick any location you like for these files.
See this link for more information on MEDIA_URL and MEDIA_ROOT
For the views.py you need to make 2 changes.
Add enctype="multipart/form-data" to the form statement. This is required to ensure the File object is submitted along with the POST.
Change {{i.img}} to {{i.img.url}} Adding the .url method outputs the correct relative url for the image (in simple terms in pre-appends the Media Root value.
<form enctype="multipart/form-data" method="POST">
{% csrf_token %}
{{form.as_p}}
<br>
<BUTTON TYPE ="SUBMIT">Submit</BUTTON><br>
<br>
</form>
{%for i in up %}
{{i.Comments}}
<img src ="{{i.img.url}}", alt="">
{%endfor%}
Assuming you are running this using the internal development server you will need to make the following changes to your urls.py.
Add this entries to the top of the file.
from django.conf import settings
from django.conf.urls.static import static
Add a pattern to allow the server to find the image files.
... + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns = [
path('', views.home, name="home"),
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Hope this helps. Happy to do follow up in necessary.
I'm actually new to django and I found a problem when loading my images, I did the settings like the docs said and it saves my images to the right folder. Just the loading part does not work as I want it to.
# the settings.py
STATIC_URL = '/static/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
# the Model
class Legend(models.Model):
name = models.CharField(max_length=100)
description = models.CharField(max_length=300)
creator = models.ForeignKey(User, on_delete=models.CASCADE)
created = models.DateTimeField(auto_now=True)
published = models.DateTimeField(null=True, blank=True)
available = models.BooleanField(default=False)
image = models.ImageField(upload_to='gallery', blank=True, null=True)
# the template where i use the img field
{% for instance in object_list %}
<img style="width: 245px; height: 247px;" src="{{ instance.image.url }}" alt="legend image"">
{% endfor %}
the upload is working as expected. Saves all images to the media folder (which is on the applevel)
so: media/gallery/name.jpg.
running the server doesnt show the image but the source seems fine:
http://127.0.0.1:8000/media/gallery/gto.jpg
There seems to be a problem with serving files locally when debugging, but all i could find were for older django versions. Iam using django --version 2.2.
I appreciaty any help
When you are running django under DEBUG = True, you should also add media urls:
Add this to end of your main urls.py:
from django.conf import settings
from django.conf.urls.static import static
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
# and this one to serve static files:
#urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
I'm trying to wrap my head around images and Form handling with class-based views. So i'm playing with this simple model. When using CreateView do I have to overwrite it with a custom form using form_class in order to successfully upload/save and image?
I can't figure out why I'm getting this:
Exception Type: TypeError
Exception Value: expected str, bytes or os.PathLike object, not tuple
The whole thing is barebones, right out of stock.
models.py
class Post(models.Model):
headline = models.CharField(max_length=80, blank=True, null=True)
cover_image = models.ImageField('hero image', upload_to='images/', blank=True, null=True)
slug = models.SlugField(max_length=80, blank=True, null=True, unique=True)
def get_absolute_url(self):
return reverse('details', args=[str(self.slug)])
views.py
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import CreateView
class PostCreateView(LoginRequiredMixin, CreateView):
model = Post
fields = ['headline', 'cover_image', 'slug']
news/templates/news/post_form.py
<form enctype="multipart/form-data" method="post" action="">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Save"/>
</form>
Can anyone help me understand?
As requested
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.0/howto/static-files/
STATIC_URL = '/static/'
STATICFILES_DIRS = (os.path.join(BASE_DIR, 'static'),)
MEDIA_ROOT = (os.path.join(BASE_DIR, 'media'),)
MEDIA_URL = '/media/'
LOGIN_REDIRECT_URL = 'home'
You've set MEDIA_ROOT to a tuple, but it should be a string.
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
Settings.py
STATIC_URL = '/static/'
MEDIA_ROOT='/home/akanksha/bookepdia/media/'
MEDIA_URL = '/media/'
TEMPLATE_DIRS = ('/home/akanksha/bookepdia/templates',)
Model.py
class Image(models.Model):
title = models.CharField(max_length=255)
photo = models.ImageField(upload_to='/home/akanksha/bookepdia/media/images/')
Url.py
urlpatterns = patterns('',
url(r'^$', 'bookepdia.views.home', name='home'),
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Views.py
def home(request):
photos = Image.objects.all()
return render_to_response('display.html', {'photos' : photos})
display.html
<html>
<h3>Images of books</h3>
<img src="/media/images/image_name" />
{% for p in photos %}
<img src="{{p.photo.url}}" />
{% endfor %}
</html>
Now,my problem is when I have added /media/images/image_name the image is displayed but when I use {{p.photo.url}} the image is displayed as broken icon.
I found out it is taking the path as /home/akanksha/bookepdia/media/images/image_name.
Now,I want to edit this for every url so that it works as /media/images/image_name.
You shouldn't give absolute path into upload_to in ImageField, it should be path relative to your MEDIA_ROOT.
upload_to attribute of ImageField is not absolute path, it is relative to MEDIA_ROOT setting.
In your case it should be like this:
photo = models.ImageField(upload_to='images')
See documentation: https://docs.djangoproject.com/en/1.8/ref/models/fields/#django.db.models.FileField.upload_to
FileField.upload_to
A local filesystem path that will be appended to your MEDIA_ROOT setting to determine the value of the url attribute.
So far I made it to the part where a user uploads an image but how can I use those images which are located in my media folder? Here is what I tried :
my view:
#I even tried to import MEDIA_ROOT to use it in my template...
#from settings import MEDIA_ROOT
def home(request):
latest_images = Image.objects.all().order_by('-pub_date')
return render_to_response('home.html',
#{'latest_images':latest_images, 'media_root':MEDIA_ROOT},
{'latest_images':latest_images,},
context_instance=RequestContext(request)
)
my model:
class Image(models.Model):
image = models.ImageField(upload_to='imgupload')
title = models.CharField(max_length=250)
owner = models.ForeignKey(User)
pub_date = models.DateTimeField(auto_now=True)
my template:
{% for image in latest_images %}
<img src="{{ MEDIA_ROOT }}{{ image.image }}" width="100px" height="100px" />
{% endfor %}
and my settings.py MEDIA_ROOT and URL:
MEDIA_ROOT = '/home/tony/Documents/photocomp/photocomp/apps/uploading/media/'
MEDIA_URL = '/media/'
So again here is what I am trying to do: Use those images in my templates!
If you use the url attribute, MEDIA_URL is automatically appended. Use name if you want the path without MEDIA_URL. So all you need to do is:
<img src="{{ some_object.image_field.url }}">
On development machine, you need to tell the devserver to serve uploaded files
# in urls.py
from django.conf import settings
if settings.DEBUG:
urlpatterns += patterns('',
url(r'^media/(?P<path>.*)$', 'django.views.static.serve', {
'document_root': settings.MEDIA_ROOT,
}),
)
{# in template, use sorl-thumbnail if your want to resize images #}
{% with image.image as img %}
<img src="{{ img.url }}" width="{{ img.width }}" height="{{ img.height }}" />
{% endwith %}
# furthermore, the view code could be simplified as
from django.shortcuts import render
def home(request):
latest_images = Image.objects.order_by('-pub_date')
return render(request, 'home.html', {'latest_images':latest_images})
On production environment using normal filesystem storage, ensure the webserver has permission to write to MEDIA_ROOT. Also configure the webserver to read /media/filename from correct path.
ImageField() has an url attribute so try:
<img src="{{ MEDIA_URL }}{{ image.image.url }}" />
You could also add a method to your model like this to skip the MEDIA_ROOT part:
from django.conf import settings
class Image(...):
...
def get_absolute_url(self):
return settings.MEDIA_URL+"%s" % self.image.url
Also I'd use upload_to like this for sanity:
models.ImageField(upload_to="appname/classname/fieldname")
Try these settings:
import socket
PROJECT_ROOT = path.dirname(path.abspath(__file__))
# Dynamic content is saved to here
MEDIA_ROOT = path.join(PROJECT_ROOT,'media')
if ".example.com" in socket.gethostname():
MEDIA_URL = 'http://www.example.com/media/'
else:
MEDIA_URL = '/media/'
# Static content is saved to here
STATIC_ROOT = path.join(PROJECT_ROOT,'static-root') # this folder is used to collect static files in production. not used in development
STATIC_URL = "/static/"
STATICFILES_DIRS = (
('', path.join(PROJECT_ROOT,'static')), #store site-specific media here.
)
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
)
For Django version 2.2., try the following:
#You need to add the following into your urls.py
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
Your URL mapping
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) #add this
# And then use this in your html file to access the uploaded image
<img src="{{ object.image_field.url }}">
You have to make the folder containing the uploaded images "web accessible", i.e. either use Django to serve static files from the folder or use a dedicated web server for that.
Inside your template code, you have to use proper MEDIA_URL values.