Django: Making alias in urls.py for amazon s3? - django

I am encountering a problem in setting up the URLs in Django.
To serve my media files I have this Amazon S3 bucket:
https://somebucket.s3.amazonaws.com/
I set the media URL inside settings.py as follows:
MEDIA_URL = https://somebucket.s3.amazonaws.com/media/
Inside the urls.py I set the code as follows:
urlpatterns += patterns('',
(r'^media/(?P<path>.*)$', 'django.views.static.serve', {
'document_root': settings.MEDIA_URL}));
My intention is that, when I point an image file from, lets say <img src="/media/image.jpg"/> it will be automatically pointed to http://somebucket.s3.amazonaws.com/media/image.jpg
How can I do that? I have tried many methods but it always returns a 404.
However if i try to access the file directly http://somebucket.s3.amazonaws.com/media/image.jpg it works.

Why would you want to do that? That defeats most of the purpose of having the external storage in the first place. It means that for every media request, it has to go through Django itself, to resolve the URL and generate the redirect to S3, with all the overhead that implies.
Instead, as sneawo suggests in the comments, you should simply set the img src attribute to point to the image via the S3 URL.

turned out that django automatically appends the media_url in front of the imagefield url.
i was under impression that i have to append the media_url, which caused me to look for a simpler solution.
Django Admin only shows relative paths
![django admin shows relative paths][1]
http://i.stack.imgur.com/aZGPy.png
But, tastypie gives me absolute path
http://i.stack.imgur.com/SEdaX.png
so i now don't have to worry about urls anymore...thanks again guys :)

Related

Create a 'dummy' URL path for frontend pictures rendering

I have application with DjangoRestFramework for backend and Vue.js for frontend.
My user can upload pictures and they are stored in an uploaded_media file.
Therefore I added + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) to my urlpatterns.
But since it is a Single Page Application, I added re_path(r"^.*$", IndexTemplateView.as_view(), name="entry-point"), in my urlpatterns for everything to be redirected to my index.html.
My issue is since my pictures URL is fetched in this format: "http://127.0.0.1:8000/media/my_pic.jpg", it can't be rendered frontend because it's redirected to my entry-point.
So I made a 'dummy' URL path (path('media/', DummyView.as_view())) pointing to a dummy View:
class DummyView(TemplateView):
pass
And it works... just for the first picture. I am doing it right and missing something or I am going to the wrong direction?
If it helps, I find a better way than creating a 'dummy' view, I just change my entry-point URL this way:
re_path(r"^(?!media).*$", IndexTemplateView.as_view(), name="entry-point")
So everything except the URL starting with 'media' is redirected to the entry-point

Getting Page not found (404) in Django 1.3.1 from bad url pattern

I am following along with this Django blog tutorial and can not get the url pattern given in the tutorial to work properly. The url.py code the author gives is
(r'^static/(?P
.*)$', 'django.views.static.serve',
{'document_root': 'c:/static/adornment'}),)
and I adapted it to my Linux set up like this
from django.conf.urls.defaults import patterns, include, url
urlpatterns = patterns('',
(r'^static/(.*)$', 'django.views.static.serve',
{'document_root': '/home/sez/blog/static/image.png'}
),
)
and after going to http://127.0.0.1:8000/static/image.png I received the following error
Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8000/static/image.png
'image.png' could not be found
How can I make this work?
Change up your 'document_root' to be a directory, and make sure your STATIC_URL setting is set to /static/
The likely reason for the behavior you were experiencing is as follows. You probably have 'django.contrib.staticfiles' included in your INSTALLED_APS in the "settings.py" file. In that case, when you run "manage.py runserver" (and you have DEBUG = True in your "settings.py"), static files will be automatically served from your STATIC_URL by the staticfiles app and not by your 'django.views.static.serve' URL pattern. However, in your case staticfiles app is not set up correctly and won't find your 'image.png' file. You might want to read more about conventional serving of static files here: Managing static files.
For that matter, STATIC_URL is not supposed to be a filesystem path like you have now: STATIC_URL.
When you made it that way, you effectively disabled staticfiles app and your code started working as a result :)
So, to solve your problem "correctly", you need to either make sure that STATIC_URL and the URL path in your "urls.py" are different, for example, make one of them "/static/" and another one "/media/" (or something else), or just remove "django.contrib.staticfiles" from your INSTALLED_APPS altogether if you don't use it. (And, of course, the advice about making 'document_root' a directory was entirely correct. You can read more about using 'django.views.static.serve' here: Serving static files in development.)

Django admin shows full path to uploaded file, and link contains full path. How can I fix this?

I have a model which is defined like this:
class Attachment(models.Model):
file = models.FileField(upload_to=MEDIA_ROOT)
MEDIA_ROOT is defined using it's absolute path, and it's something like d:\django\my_proj\media . In the admin, the link to it appears like this: http://localhost:8000/media/d:/django/my_proj/media/file.txt . How can I fix this?
Use / instead of MEDIA_ROOT. From the docs, upload_to should be:
A local filesystem path that will be
appended to your MEDIA_ROOT setting to
determine the value of the url
attribute.
In other words, the path that you specify in upload_to will be appended to MEDIA_ROOT to form the upload directory, and appended to MEDIA_URL to form the URL to the file.
p.s. it might be worth specifying a subdirectory instead of / just so the uploaded files cannot overwrite your media files. For example, upload_to='uploads/'. To organise you uploads by year/month, you can even do upload_to='uploads/%Y/%m/'. See docs for more details.

Referencing image in CSS with relative path doesn't work in Django

I am using Django 1.3 with built-in static app.
My static folder structure is like this:
static/
css/
main.css
img/
js/
So I tried to reference images under static/css/img/ folder from CSS like this:
background:url('img/btn_white.gif') repeat-x;
But the images don'e show up. When I inspect elements in Chrome, I found the image path to be http://localhost/mysite/static/css/main.css/img/btn_white.gif/
Which is very wierd since this relative path should have referenced static/css/ folder instead of main.css. So I tried to change path to be url('../img/btn_white.gif'), and it works in Chrome and Firefox but not in IE.
I am pretty sure this problem is related to Django, because in my pure HTML/CSS, this relative path works just fine. I also tried to put css in media folder and the problem is the same.
My settings related to static app:
in settings.py:
STATIC_ROOT = os.path.join(os.path.dirname(__file__),'static').replace('\\','/')
STATIC_URL = 'http://localhost/mysite/static/'
in urls.py:
(r'^static/(?P<path>.*)/$', 'django.views.static.serve', {'document_root': settings.STATIC_ROOT}),
Related question: Is a relative path in a CSS file relative to the CSS file?
The problem is caused by your URLconf, specifically the pattern:
r'^static/(?P<path>.*)/$'
This means that a the URL must end in a forward slash for it to match this pattern. i.e. the following URL will not match: (because it doesn't have a trailing slash)
/mysite/static/css/main.css
The weird thing, is that it does work. The reason for this is Django's APPEND_SLASH setting:
When set to True, if the request URL does not match any of the patterns in the URLconf and it doesn't end in a slash, an HTTP redirect is issued to the same URL with a slash appended. Note that the redirect may cause any data submitted in a POST request to be lost.
So when your browser makes a request to:
/mysite/static/css/main.css
…Django will fail to match it against any of the URLs, and will issue a redirect to: (because APPEND_SLASH defaults to True)
mysite/static/css/main.css/
This new request will succeed and your browser will now be able to download the CSS file, however the CSS file's resource URL now ends with a slash. When your browser processes the CSS rules and comes across:
background:url('img/btn_white.gif') repeat-x;
It will attempt to join that relative URI to the URI of the CSS resource. e.g.:
/mysite/static/css/main.css/ + img/btn_white.gif = /mysite/static/css/main.css/img/btn_white.gif
This will fail, so your browser will get a redirect to: (again because of APPEND_SLASH)
/mysite/static/css/main.css/img/btn_white.gif/
But obviously that too will fail.
Solutions
Change your URL pattern to the following: (note the removed trailing / in the pattern)
(r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.STATIC_ROOT}),
Or use one of the recommended methods:
from django.conf import settings
if settings.DEBUG:
urlpatterns += patterns('django.contrib.staticfiles.views',
url(r'^static/(?P<path>.*)$', 'serve'),
)
…or:
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
# ... the rest of your URLconf here ...
urlpatterns += staticfiles_urlpatterns()

Django : How do I call "reverse" on a link to a static image file?

In Django, I have images stored in site_media like this :
/site_media/somepath/image.jpg
The urls.py file has been set up to server these using :
urlpatterns += patterns('',
(r'^site_media/(?P<path>.*)$', 'staticfiles.views.serve')
)
urlpatterns += patterns('',
(r'^site_media/(?P<path>.*)$', 'staticfiles.views.serve')
)
So how can I make a reverse() or {% url %} call to one of these images?
It's probably easier to just use:
{{ MEDIA_URL }}somepath/image.jpg
assuming you've set up the MEDIA_URL setting in your settings.py.
Also, you really don't want to serve static files through Django in a production environment. From the docs:
Using this method is inefficient and insecure. Do not use this
in a production setting. Use this only for development.
One more thing - what is staticfiles.views.serve? Django has a built in system for serving static files, though the disclaimer above still applies.
You probably want to serve static files straight from Apache/nginx/whatever. It'll be heaps quicker.