DJANGO - upload image stored locally to model ImageField attribute - python

I have my images downloaded inside the subroot images in my media folder and I'm trying to generate new models which will contain the photo inside the images folder. This is what my model and my view look like:
class Post(models.Model):
...
image = models.ImageField(upload_to="images", blank=True, null=True)
def generate_posts(request):
for i in range(20):
title_ = f'title{i}'
body_ = f'text for post number : {i}'
author_ = f'author{i}'
network_ = randomize_social()
post = Post(title=title_, body=body_, author=author_, social_network=network_)
if randomize_picture():
post.image.save("logo.png", File("images/svante.jpg"), save=True)
else:
post.image = None
post.save()
areGenerated = True
return render(request, "posts/generate_posts.html", {'areGenerated':areGenerated})
The logo.png file is created inside the images folder, but it's blank, 0kb size and when I follow the /generateposts url, I receive this error message:
AttributeError at /generateposts
'str' object has no attribute 'read'
What can I do to solve this problem?

Did you make changes to your settings file? you need to make changes such as
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
and don't forget to add these to your urls:
from . import views, settings
from django.contrib.staticfiles.urls import static
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
urlpatterns += staticfiles_urlpatterns()
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Related

Django wont upload images to media directory

Today I tried to have images in my project and the idea is simple - create news with an image, title, and description.
I wonder why when I set up my media files
So I make my news in this view:
class NewsCreate(views.CreateView):
template_name = 'web/create_news.html'
model = News
fields = ('title', 'image', 'description')
success_url = reverse_lazy('home')
Here is the model:
class News(models.Model):
TITLE_MAX_LENGTH = 30
title = models.CharField(
max_length=TITLE_MAX_LENGTH
)
image = models.ImageField(
upload_to='news/',
blank=True
)
description = models.TextField()
Here is the set-up in settings.py:
MEDIA_ROOT = BASE_DIR / 'mediafiles'
MEDIA_URL = '/media/'
Here is the urls.py file:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('University_Faculty.web.urls')),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
I've noticed that when I try to go to none existing URL this happens : wrong ulr page showing media as a correct one
This is the result in my media folder after 10+ POST requests it shows in the database that it is actually creating the news, but the images won't go anywhere: no files media folder
You need to correct
MEDIA_ROOT = BASE_DIR / 'media'
Hope this will work for you.
add this to settings.py
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

Page returns 'Not Found' when opening URL to image in deployment but works in local machine. [Django Rest Framework]

My Django REST API supposedly is able to GET and POST images. During development, I was able to save the image into the database and retrieve the saved image via the URL of the image. However, when deployed to Heroku, the page returns 'Not Found' when I clicked the URL to the image.
requirements.txt
asgiref==3.2.10
dj-database-url==0.5.0
Django==3.0.8
django-heroku==0.3.1
djangorestframework==3.11.0
gunicorn==20.0.4
Pillow==7.2.0
psycopg2==2.8.5
pytz==2020.1
sqlparse==0.3.1
whitenoise==5.1.0
settings.py
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATIC_URL = '/static/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
django_heroku.settings(locals())
urls.py
from django.contrib import admin
from django.urls import path, include
from django.conf.urls.static import static
from django.conf import settings
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('element.urls')),
]+static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
models.py (Element App)
from django.db import models
# Create your models here.
class Element(models.Model):
element_name = models.CharField(max_length=255, unique=True)
element_tag = models.CharField(max_length=255)
element_type = models.CharField(max_length=255)
element_img = models.ImageField(upload_to='elements/')
creator_tag = models.CharField(max_length=255)
creator_link = models.CharField(max_length=255)
def __str__(self):
return self.element_name
serializers.py (Element App)
from rest_framework import serializers
from element import models
class ElementSerializer(serializers.ModelSerializer):
element_img = serializers.ImageField(max_length=None, use_url=True)
class Meta:
model = models.Element
fields = ('id', 'element_name', 'element_tag', 'element_type', 'element_img', 'creator_tag', 'creator_link')
views.py (Element App)
from django.shortcuts import render
from rest_framework import viewsets
from rest_framework import filters
from element import serializers
from element import models
# Create your views here.
class ElementViewSet(viewsets.ModelViewSet):
queryset = models.Element.objects.all()
serializer_class = serializers.ElementSerializer
filter_backends = (filters.SearchFilter,)
search_fields = ('element_name', 'element_tag', 'element_type',)
urls.py (Element App)
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from element import views
router = DefaultRouter()
router.register('elements', views.ElementViewSet, basename='Elements')
urlpatterns = [
path('', include(router.urls))
]
Note: The image along with its data is saved and can be seen in the admin panel. However, when opening the URL to the image, it returns 'Not Found'.
Both staticfiles and media folder are pushed into GitHub repository
When viewing in my local machine, if I open the URL to 127.0.0.1:8000/media/elements/picture.png, it returns the image. After being deployed, when I open the URL to project_name.herokuapp.com/media/elements/picture.png, it returns 'Not Found'
The problem is in serving your media files.
Django is not built to serve static and media files in production Deploying Static Files
Since your using Heroku as your hosting platform, whitenoise is able to handle your static files. However, for media files a simple fix to the problem is to set up a free Amazon S3 account to host all your media files.
Here is a quick reference guide Serving Django Media Files in Production

How to change the default image location in the Django ImageField?

Having trouble trying to change where Django looks for the default image in the ImageField. I am trying to store a default image within a folder in my "media" file.
Code from models.py below:
from django.db import models
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='profile_pics/default.jpg', upload_to='profile_pics')
When I load the page I get a 404 error:
Not Found: /media/default.jpg
[21/Apr/2020 18:11:48] "GET /media/default.jpg HTTP/1.1" 404 1795
Any ideas on how to add the "profile_pics" piece to the path?
add media path to your urlpatterns in DEBUG mode
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
you have to copy a image with default.jpg in media/profile_pics directory and use it for your default image for users

unable to display images from model usingo django

in settings.py
MEDIA_ROOT = os.path.join(BASE_DIR,'pictures')
MEDIA_URL = '/pictures/'
in models.py
class Campaign(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
# this is many to one relationship, on_deleting user, profile will also be deleted
campaign_title = models.CharField(max_length=200, blank=True)
campaign_image = models.ImageField(default="default_campaign.png",upload_to="campaign_pictures")
in views.py
def landing_page(request):
campaigns = Campaign.objects.all().order_by('-id')
print(campaigns)
return render(request, 'core/landing_page.html',{'campaigns':campaigns})
in landing_page.html
{% for campaign in campaigns %}
<img src="{{campaign.campaign_image.url}}">
{% endfor %}
issue
if file name is abc xyz.jpg, it gets saved into /pictures/campaign_pictures as abc_xyz.jpg
in html template, the src of image should be '/pictures/campaign_pictures/abc_xyz.jpg' but it shows only '/pictures/abc%20xyz.jpg'
I think you missed in urls.py file
from django.conf import settings
from django.conf.urls import url
from django.conf.urls.static import static
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
] + static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
Also correct it with
campaign_image = models.ImageField(default="default_campaign.png",upload_to="campaign_pictures/")
You can define the 'upload_to' as a callable function and use the os.path to join the directory name with the media url.
Your field will call a function which will provide the path.
campaign_image = models.ImageField(default="default_campaign.png",upload_to=get_campaign_path)
and define your function like this
import os
def get_campaign_path(instance, filename):
return os.path.join('campaign_pictures/',filename)
Reference:
https://docs.djangoproject.com/en/3.0/ref/models/fields/#django.db.models.FileField.upload_to

Django Rest app not using media root correctly to serve images

I have a project that has 3 apps, one named stores with store models, products with product models, and api which is the rest framework app that serves the Json results to clients. I set the media root in settings.py as MEDIA_ROOT = '/photos/' and the upload works for both product and store models. The main problem here is that for some reason the rest framework returns a url that references the api app instead of the products or stores apps for the media root url. here are my models
class Product(models.Model):
def get_image_path(instance, filename):
return '/Products/' + filename
picture = models.ImageField(width_field=None, max_length=100, blank =True, null =True)
store:
class Store(models.Model):
def __str__(self):
return self.name
def get_image_path(instance, filename):
return os.path.join('productphotos', 'stores', filename)
picture = models.ImageField(width_field=None, max_length=100, blank =True, null =True)
How do i set the mediaroot to the project directory instead so that all apps in the project reference it as mediaroot instead of themselves?
The upload works and upoads the pictures to the instructed directories in the root of the project (where manage.py is found), but the rest framework thinks it should get the media from the api app.. what's the proper way of doing this? here are screenshots:
the path uploaded to
the path returned in json
The MEDIA_URL setting is the URL path in the browser. The MEDIA_ROOT setting is the root directory on your server, and should be an absolute path.
MEDIA_URL = '/pictures/'
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
MEDIA_ROOT = os.path.join(BASE_DIR, 'uploaded_pictures')
Also, if you want Product and Store pictures to go into different sub directories, for example pictures/products/ and pictures/store/, you'd need to set the upload_to argument on the model field. For example
picture = models.ImageField(upload_to='products/', ... )
Edit: To serve static and media files during development, add this at the end of the urls.py
if settings.DEBUG:
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.conf.urls.static import static
urlpatterns += staticfiles_urlpatterns()
urlpatterns += static(
settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Categories