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
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.
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 yet to wrap my head around django and URLs, and my confusion is now preventing me from doing what I feel like should be a very simple task.
I have successfully implemented file upload.
In my settings.py file, I have added the specifications for where to store the uploaded files and the URL Django should use to serve them.
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL= '/media/'
I also added the necessary line to urls.py to allow Django to serve files from MEDIA_URL.
from django.conf.urls import url, include
from django.contrib import admin
from login_app import views as login_app_views
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login/', login_app_views.login_user),
# creating registered namespaces for each app
url(r'^login/', include('login_app.urls', namespace = "login_app")),
url(r'^CMIRS/', include('dashboard_app.urls', namespace = "dashboard_app")),
url(r'^CMIRS/', include('submit_app.urls', namespace = "submit_app")),
url(r'^CMIRS/', include('filter_app.urls', namespace = "filter_app")),
url(r'^CMIRS/case/',include('report_app.urls', namespace = "report_app")),
url(r'^CMIRS/', include('search_app.urls', namespace = "search_app")),
url(r'^search/', include('haystack.urls')), ##used in navbar-search
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
In an app report_app, I want the webpage to display a hyperlink that can be used to view an uploaded file. When I click on the hyperlink, I want it to request the URL to the uploaded file.
The upload looks like such in my models:
upload1 = models.FileField(upload_to = 'documents/%Y/%m/%d/')
I am having trouble figuring out what to use in the render(request) in my view and how to correctly code this in HTML. When I attempt to use "media", I get an error saying it cannot be matched.
Here is a snippet of the HTML I am trying:
<dt>Upload</dt><dd><tr><td>{{ case.upload1 }}</td></tr></dd>
I am also confused as how to set up my render(request) so that it knows to access media/, and then go to the correct documents/Y/M/D depending on the primary key.
You don't want to use the url tag here at all. Your media's URL is stored in your model, and has nothing to do with Django's path resolution logic. Just reference the url method of the field:
<a href="{{ case.upload1.url }}">
See the docs.
(Note also that serving files via your urls.py like this works in dev only; for prod you'll need to configure your webserver to do it.)
I have a simple Django admin page that uploads images to a product description. Everything works until I try to view the image by clicking on its path in the products information. I get this error:
Page not found (404)
Request URL: http://0.0.0.0:6666/the_image.jpg
I'm guessing I need to declare something in urls.py, but I have no idea where to start. I also tried changing my media paths in settings.py but I always get errors if I change to anything other than '/'
model.py
class Image(models.Model):
product_image = models.ForeignKey(Product)
image = models.ImageField(upload_to='/')
settings.py
MEDIA_ROOT = '/'
MEDIA_URL = '/'
admin.py
class InlineImage(admin.TabularInline):
model = Image
class ProductAdmin(admin.ModelAdmin):
inlines = [InlineImage]
Docs are here https://docs.djangoproject.com/en/dev/ref/settings/#media-root
You need to set MEDIA_ROOT and MEDIA_URL in your settings file like this
MEDIA_ROOT = /var/www/example.com/media/
MEDIA_URL = /media
and your upload_to should probably be the model name or something to identify it.
image = models.ImageField(upload_to='image')
Then the link should point the /media/image/NAME_OF_IMAGE.png
You will also need to have urls.py setup to server media files. For production you would want to do this in nginx with an alias. See https://docs.djangoproject.com/en/dev/howto/static-files/#serving-files-uploaded-by-a-user-during-development
Which says:
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = patterns('',
# ... the rest of your URLconf goes here ...
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)