I have a django app (installed on a Debian server) where there is file upload.
Traditionaly, it ulpload in a folder in site_media.
For some reason,(please don't ask why,take it for granted) I have to save the files in a different disk.
The path to the other disk is /disk/site_media
The saving do the other disk is donw succesfully!
When I try to open the file by clicking on it , I get File not Found.
I am open to ideas!!!
Here's my code when uploading the file:
obj = form.save(commit=False)
obj.user_id = self.request.user.pk
obj.save()
initial_path = obj.file.path
print(initial_path)
new = settings.MEDIA_ROOT_NEW + obj.file.name
print(new)
#os.rename(initial_path,new)
shutil.move(initial_path, new)
I upload the files in my EmployeeDoc class:
class EmployeeDoc(models.Model):
file = models.FileField('DocFile', upload_to='edocs/')
employee = models.ForeignKey(Employee , related_name='documents')
user = models.ForeignKey(User , related_name='employeedocs')
created_at = models.DateTimeField(auto_now_add=True,default=timezone.now)
update_at = models.DateTimeField(auto_now=True,default=timezone.now)
I get the files in my template with a function written under my Employee class:
class Employee(models.Model):
name ...
last ...
def getDocuments(self):
return EmployeeDoc.objects.filter(employee_id=self.pk,del_f=0)
Here are my paths in settings.py:
MEDIA_ROOT = os.path.join(PROJECT_PATH, 'site_media/')
MEDIA_ROOT_NEW = '/disk/site_media/'
MEDIA_URL = '/site_media/'
In my urls.py despite all the othe urls I have:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
You're serving MEDIA_ROOT directory on MEDIA_URL url. That means files from MEDIA_ROOT_NEW won't be accessible on MEDIA_URL url.
If you want to serve all your media files from MEDIA_ROOT_NEW, change line:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
to
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT_NEW)
If you want to serve both directories on one URL, consider using nginx or other web server for that.
Related
My code generates Pandas dataframes. They are big. I save them as files. For this, I have created this Model:
models.py:
class TargetFiles(models.Model):
owner = models.CharField(max_length=25)
csv_file = models.FileField(blank=True, upload_to='target')
file_name = models.CharField(max_length=255)
settings.py:
...
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
mycode.py:
file_content = df.to_csv(index=False, encoding='utf-8')
csvname = 'target1.csv'
csf = ContentFile(file_content, csvname)
TargetFiles.objects.create(owner=self.user, csv_file=csf, file_name=csvname)
urls.py (project):
from django.urls import include, path
from django.contrib import admin
urlpatterns = [
path('dataapp/', include('dataapp.urls')),
]
urls.py (dataapp):
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='dataapp'),
path('welcome/', views.welcome_dataapp, name='welcome_dataapp'),
path('download/<str:file_name>', views.download, name='download'),
]
I don't know if this is the best approach for the problem. This documentation made me skeptical. The thing is that my code is generating the file properly, and saving it in the MEDIA_ROOT directory. But when I go to admin view and click on TargetFiles object, the link to the file returns this error:
The current path, media/target/target1.csv, didn't match any of these.
Since I am not an Django expert, I think I am setting something wrong. Maybe in settings.py or in urls.py (in this file I didn't write any reference to media, maybe this is where the error lives).
I have already read these posts:
Django - how to create a file and save it to a model's FileField?
,
Django: generate a CSV file and store it into FileField and this assign resulting csv file to django model. But I was not able to make the admin link point to the MEDIA_ROOT file.
Does anyone have ideas?
Thanks in advance.
Django does not serve the files stored in the MEDIA_ROOT. You can enable this during development by adding the following to your root url config:
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# ... the rest of your URLconf goes here ...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
https://docs.djangoproject.com/en/3.0/howto/static-files/#serving-files-uploaded-by-a-user-during-development
It's recommended to let file serving be handled by some other server (apache or nginx) whe deploying to a production server.
I am running python 3.7/Django==2.2.6 . My issue is all old files uploaded through django admin console were accessible from media folder when i go with domain.com/media/. But when i upload a new file, it says successfully saved and i can see the file in media folder but when access it it says 404 not found. All old files in media folder still accessbile.
My settings.py
DEBUG = 'True'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
urls.py
urlpatterns = [
path(......),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Try this:
class HomeSliderModel(models.Model):
image = models.FileField(null=False, blank=False, upload_to = '/user_directory_path/')
is_active =models.BooleanField(null=False, blank=False, default=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['-updated']
def __str__(self):
return self.image.name
have the following problem, I have in my settings.py configured in the following way:
RUTA_PROYECTO = os.path.dirname(os.path.realpath(__file__))
MEDIA_ROOT = os.path.join(RUTA_PROYECTO,'fotos')
MEDIA_URL = '/media/'
In my urls file I have:
from django.conf.urls.static import static
Urlpatterns = patterns ('',
....
) + static (settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
I have in my models
def upload_name(instance, filename):
return '{}/{}'.format(instance.persona.nro_doc, filename)
class FotosPersona(models.Model):
persona = models.ForeignKey(Personas,related_name='fotos_persona')
tipo_foto = models.CharField(max_length=25)
foto = models.ImageField(upload_to=upload_name)
fecha = models.DateField(auto_now=True)
class Meta:
db_table = 'fotos_persona'
When I save the data, the image is stored in a folder within the following structure:
Project
|
|
|----Project
|---- settings.py
|---- media
|---- urls.py
.....
But when I want to display the image in a template, it is not displayed.
When in the browser I entered the
http://localhost:8000/media/other_folder/image_file.jpg url
it returns me an HTTP 500 error.
I know my answer is a little late, but this might be useful considering your set up. Essentially, you have given the MEDIA_URL as "/media/". This is all right.
However, you would be facing a problem with reference to the URL patterns. You will probably have a generic URL along the lines of:
path('<index>', views.index, name='index'),
In such a scenario this URL would be processing everything that comes from the media URL. Although this is not ideal, only for the purpose of development I would recommend changing your URL patterns to the following:
urlpatterns = static (settings.MEDIA_URL, document_root = settings.MEDIA_ROOT) + [
...
]
Now in the hierarchy of processing URL patterns "/media/" would come before any URL that has a general pattern. Now media URLs would be processed before everything else.
Hopefully, this can address your query.
I can upload an image through the admin page, but the image can not be found when I navigate to the url that is generated by django. (404 error)
The files are being uploaded to the folder:
project_root/media/eventbanner/1/
I have tried multiple solutions but none seem to work for my situation.
Django 1.10 is being run local on Ubuntu 16.04.
The url I get is:
http://localhost:8000/media/eventbanner/1/banner_image.jpg
Media root folder is located at:
/home/username/xxx/xxx/project_name/media
Code in HTML file:
<div class="banner-image">
<img src="{{ event.eventbanner.banner_image.url }}"/>
</div>
url.py code:
from django.conf.urls import url, include
from django.contrib import admin
from . import views
from django.conf import settings
from django.conf.urls.static import static
app_name = 'events'
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^details/(?P<event_id>[0-9]+)/$', views.details, name='details'),
url(r'^details/(?P<event_id>[0-9]+)/addcomment/$', views.add_comment, name='add_comment'),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS =[os.path.join(BASE_DIR, 'static'),]
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
MEDIA_URL = '/media/'
models.py
def validate_only_one_instance(obj):
model = obj.__class__
if (model.objects.count() > 0 and obj.id != model.objects.get().id):
raise ValidationError("Can only create 1 %s instance" % model.__name__)
class EventBanner(models.Model):
event = models.OneToOneField(Event, unique=True)
banner_image = models.ImageField(upload_to=get_image_path, blank=True, null=True)
def clean(self):
validate_only_one_instance(self)
The real problem here is that there is no relationship between this url http://localhost:8000/media/eventbanner/1/banner_image.jpg and this location on disk /home/username/xxx/xxx/project_name/media.
In a production application you'd have a web server where you'd store your Media content, the serving URL would be MEDIA_ROOT and you'd append ImageField.url to this value to get a valid image path.
What you need here is to set up a web server for your media images. At first that sounds like a lot of work, but Django provides a shortcut...
Serving Files in Development
You have some work you need to do to have the media files served locally. It requires some changes to your urls.py ...
from django.conf import settings
from django.views.static import serve
# ... the rest of your URLconf goes here ...
if settings.DEBUG:
urlpatterns += [
url(r'^media/(?P<path>.*)$', serve, {
'document_root': settings.MEDIA_ROOT,
}),
]
This uses the views.serve bit and should only be used in DEBUG mode. It overrides the path to media files(django's term for user uploaded content like ImageField). This will redirect those requests through the serve view. Best I can tell this is a mini web server that will map those request routes to locations on disk and allow those locations to be reachable via HTTP urls.
As of at least Django 1.8, there is a helper function static() that will set this up for you and ensure that it only functions in debug mode.
Your urls.py should look something like this:
urlpatterns = [
# ... the rest of your URLconf goes here ...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
...to simply quote the documentation.
Make sure that your MEDIA_URL is set to a relative path like /media/ and that your MEDIA_ROOT is an absolute filesystem path like /home/foo/project/media.
I have created a django rest model which includes a FileField.
media = models.FileField(upload_to='media/%Y/%m/%d/', null=True, blank=True)
I also implemented serializer and ListCreateApiView. There I can able to upload a file. On POST request rest server uploads the file in folder and returns me the url. However, on get request, server return json content with the url. If I use the url for get request, server respond Page Not Found. How to download the uploaded file using django rest? Do I have to create separate view for the same? If so, how to do that?
Edit:
The resulting url is
http://localhost:8000/message/media/2015/12/06/aa_35EXQ7H.svg
You have to define MEDIA_ROOT, MEDIA_URL and register MEDIA_URL in urlpatterns to allow Django server to serve these files.
Follow these steps:
settings.py file:
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, "media_root")
Append this in your main urls.py file to serve media files :
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# ... the rest of your URLconf goes here ...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Also, you don't have to add media again in upload_to attribute because it's prepended by MEDIA_URL, then the url will be /media/media/.
Here is a correct example:
media = models.FileField(upload_to='message/%Y/%m/%d/', null=True, blank=True)
and the url of the media will be:
http://localhost:8000/media/message/2015/12/06/aa_35EXQ7H.svg