I am serving static files in Django locally through their simple server. I have the following line included in my urls.py:
static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
(Bonus points to anyone who can tell me why this isn't automatically checked by the url resolver. I have django.contrib.staticfiles install and have DEBUG set to True).
If we take a peek at the implementation of static, we find a really simple function:
if not settings.DEBUG or (prefix and '://' in prefix):
return []
elif not prefix:
raise ImproperlyConfigured("Empty static prefix not permitted")
return patterns('',
url(r'^%s(?P<path>.*)$' % re.escape(prefix.lstrip('/')), view, kwargs=kwargs),
)
the last line ends up getting added to my url patterns.
When I run the web server, it doesn't properly serve files from that STATIC_ROOT. Here is an example:
I type the following into url into my browser: localhost:8000/Users/nick/Documents/coding/sparestub/static_root/contact/js/contact.js
Here is the server response:
Request Method: GET
Request URL: http://localhost:8000/Users/nick/Documents/coding/sparestub/static_root/contact/js/contact.js
Using the URLconf defined in sparestub.urls, Django tried these URL patterns, in this order:
^$ [name='homepage']
^registration/
^Users\/nick\/Documents\/coding\/sparestub\/sparestub\/\.\.\/static_root\/(?P<path>.*)$
Notice that we are searching the STATIC_ROOT correctly. If I copy and paste the url into bash, it finds the directory:
Nick-MacBook-Pro:Documents nick$ cd /Users\/nick\/Documents\/coding\/sparestub\/sparestub\/\.\.\/static_root\/
Nick-MacBook-Pro:static_root nick$ pwd
/Users/nick/Documents/coding/sparestub/static_root
Nick-MacBook-Pro:static_root nick$ cd /Users\/nick\/Documents\/coding\/sparestub\/sparestub\/\.\.\/static_root\/
Nick-MacBook-Pro:static_root nick$ pwd
/Users/nick/Documents/coding/sparestub/static_root
Nick-MacBook-Pro:static_root nick$ cd contact/js
Nick-MacBook-Pro:js nick$ ls
contact.js
And notice that it contains /contact/js/contact.js!!
And seeing at contact/js/contact.js matches the RE pattern (?P.*), I expect this entire thing to work. Can anyone offer some guidance?
Related
In a django 1.8 project, I am attempting to redirect http://myProject/ads.txt to an external url http://a.location.that.has.the.ads.txt.file and thus serve the ads.txt file without using ftp to simply place the ads.txt in the root.
Given this minimal directory structure:
django projects
myProject
myapp
urls.py
views.py
someotherapp
yetanotherapp
myProject
settings.py
urls.py (this is the top urls.py)
views.py
in myProject/myProject/urls.py, (the “top” urls.py) I have as the first entry in the urlpatterns list, the lines:
urlpatterns = patterns('',
(r'^ads\.txt', RedirectView.as_view(url='http://a.location.that.has.the.ads.txt.file', permanent=False)),
followed by many more pattern matching regex’s. This does not work and fails with a 404. What does work is
urlpatterns = patterns('',
(r'^foo/ads\.txt', RedirectView.as_view(url='http://a.location.that.has.the.ads.txt.file', permanent=False)),
and then calling http://myProject/foo/ads.txt
Unfortunately, ads.txt files must be placed at the site root. I have tried many different regex’s that test fine in a regex validator, but just don’t work (returns 404). How do I do this without the extra dir “foo”? Any thoughts appreciated. Thank you.
Turns out you cannot redirect with the top level urls.py "routing table" to above the Django project root. A nginx server level redirect did the trick.
My goal is to have an Angular project being served from the root of my development server. The files will be completely static as far as Django is concerned, no Django template processing is needed. The angular project will then make resource calls to a Django project located at /api/ on the same development server, which will then return json results generated from a view for the Angular project to process.
I assumed it would be as easy as adding the following to my urls.py file.
url(r'^/', 'django.views.static.serve', {
'document_root':'/Users/kyle/Development/project/site/app',
}),
Or
+ static("^/$", document_root="/Users/kyle/Development/project/site/app")
To the end of the urlpatterns.
With /project/site/app being the directory with the Angularjs files.
However, both of these leave me with 404 errors.
I'm open to changing the structure of the project if a more obvious solution exists.
You need to serve both index.html and your static files on / which is done like this in Django 1.10:
from django.contrib.staticfiles.views import serve
from django.views.generic import RedirectView
urlpatterns = [
# / routes to index.html
url(r'^$', serve,
kwargs={'path': 'index.html'}),
# static files (*.css, *.js, *.jpg etc.) served on /
url(r'^(?!/static/.*)(?P<path>.*\..*)$',
RedirectView.as_view(url='/static/%(path)s')),
]
See this answer where I wrote a more complete explanation of such a configuration – especially if you want to use it for production.
It turned out that it was a combination of 2 things, as shavenwarthog said, it shouldn't have the slash. Also, it needed a regular expression to direct it to the file. The final line ended up being:
url(r'^(?P<path>.*)$', 'django.views.static.serve', {
'document_root':'/Users/kyle/Development/project/site/app',
}),
I can then access files like
http://localhost/beer.jpg
note that by default Django won't serve a directory listing. Do you still get a 404 if file /Users/kyle/Development/project/site/app/beer.jpg doesn't appear as http://localhost/beer.jpg ?
in urls.py URLs don't start with a slash; compare url(r'beer') with url(r'^/beer')
I suggest just going for the standard STATIC support. It's awkward, but lets you serve file simply during development, and switch to a 3rd party server (ie Nginx) for production:
https://docs.djangoproject.com/en/dev/howto/static-files/
Very new to django. I'm using version 1.5.2 and I just did a fresh install. I'm using the django development server; I'll be moving to Apache down the road, but I want to understand the django's particular flavor of MVC methodology before doing taking that step.
So I start up the django server with `python manage.py runserver 0.0.0.0:8000' through the terminal in my project directory (django_books). I get this error:
ViewDoesNotExist at /
Could not import django_books.views.home. Parent module django_books.views does not exist.
So my view doesn't exist. My view.py file is empty because the tutorial I was following did not include one. I'm not sure if this is the problem. If it is, how do I create this file (what goes in it)?
Directory Structure:
django_books
beer (from the tutorial lol)
migrations
__init__.py
models.py
views.py
random_book
(same as beer above)
django_books (this is my actual django project, beer and random_book are apps)
__init__.py
settings.py
urls.py
wsgi.py
media
.gitignore
manage.py
requirements.txt (output from pip freeze command)
urls.py
from django.conf.urls import patterns, include, url
# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
# Examples:
url(r'^$', 'django_books.views.home', name='home'),
# url(r'^django_books/', include('django_books.foo.urls')),
# Uncomment the admin/doc line below to enable admin documentation:
# url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
# Uncomment the next line to enable the admin:
url(r'^admin/', include(admin.site.urls)),
)
If you keep your urls.py the way it is, that means you need to create views.py within /django_books/django_books/
Within that file, create a new function called home.
Alternately, if you have any functions inside of /django_books/beer/, you could reference them from urls.py.
All urls.py does is expose a python path to a function and route a URL there. So you can see that you don't have a module or file called views within django_books/django_books, which is why you get the failure.
View is basically a python function that receives HTTP Request and returns HTTP Response.
Quote from docs:
A view function, or view for short, is simply a Python function that
takes a Web request and returns a Web response. This response can be
the HTML contents of a Web page, or a redirect, or a 404 error, or an
XML document, or an image . . . or anything, really. The view itself
contains whatever arbitrary logic is necessary to return that
response. This code can live anywhere you want, as long as it’s on
your Python path. There’s no other requirement–no “magic,” so to
speak. For the sake of putting the code somewhere, the convention is
to put views in a file called views.py, placed in your project or
application directory.
This line url(r'^$', 'django_books.views.home', name='home'), in urls.py points the index / of your site to the home view - you should create it.
Create a python function called home in views.py:
from django.http import HttpResponse
import datetime
def home(request):
now = datetime.datetime.now()
html = "<html><body>It is now %s.</body></html>" % now
return HttpResponse(html)
Restart your development server and visit http://127.0.0.1:8000.
FYI, read the tutorial more carefully, part 3 is about dealing with urls and views.
I have an application that is running on Django. Our urls.py had following entries -
url(r'^$', 'web.views.index', name='index'),
url(r'^g$', 'web.views.getpost', name='getpost'),
url(r'^p$', 'web.views.postarticle', name='postarticle'),
It was working fine for thes url patterns. However, I've added two more url patterns -
url(r'^d$', 'web.views.delete', name='delete'),
url(r'^u$', 'web.views.update', name='update'),
And it when I hit
http://127.0.0.1:8000/d
It gives - The current URL, d, didn't match any of these.
I don't know why its not recognizing newly added url patterns. Any idea why its not working?
EDIT: As Wesley mentioned, it shows:
Request URL: http://127.0.0.1:8000/d Django tried these URL patterns, in this order:
^$ [name='index']
^g$ [name='getpost']
^p$ [name='postarticle']
It doesn't show ^d or ^u url patterns.
Here is my urls.py
from django.conf.urls.defaults import patterns, url
from django.conf import settings
urlpatterns = patterns('',
url(r'^$', 'web.views.index', name='index'),
url(r'^g$', 'web.views.getpost', name='getpost'),
url(r'^p$', 'web.views.postarticle', name='postarticle'),
url(r'^d$', 'web.views.delete', name='delete'),
url(r'^u$', 'web.views.update', name='update'),
)
The problem is not in the information you gave us. Both the url pattern and the url you try to visit look ok.
-> What does the debug view exactly return? Does is show:
Request URL: http://127.0.0.1:8000/d
Django tried these URL patterns, in this order:
^ ^$ [name='index']
^ ^g$ [name='getpost']
^ ^p$ [name='postarticle']
^ ^d$ [name='delete']
^ ^u$ [name='update']
Probably the debug view either doesn't list the delete url, it show it with a typo, or the request url is a little different. Try to give us a little more information if you still can't figure out the problem!
As shown in the comments to the question, the problem was a stale .pyc file. This was fixed by deleting the .pyc files and restarting the server.
In order to prevent this issue in future, you should remove .pyc files before starting a dev server. You can use the following command to quickly delete all pyc files in the current directory and all subdirectories (make sure to check that find returns the right files before killing them).
find . -name "*.pyc" #Find all pyc files and list them to console
find . -name "*.pyc" -exec rm '{}' ';' #Run command rm on each file found
In browser I get:
Request URL: http://xxxxxx:8000/person/test/
Using the URLconf defined in person.urls, Django tried these URL patterns, in this order:
^person/ ^$
^person/ ^person/(?P<slug>[-\w]+)/$
^admin/
The current URL, person/test/, didn't match any of these.
In python shell I get:
import re
url = 'person/test/'
pattern = re.compile(r'^person/(?P<slug>[-\w]+)/$'
re.match(pattern,url)
<_sre.SRE_Match object at 0xb7716860>
So it obviously should match the regexp.
Using only url person/ (the ^$ regexp) does work.
I've tried restarting the development server of course. What could be wrong here?
It isn't matching against r'^person/(?P<slug>[-\w]+)/$', the 404 page shows that it's matching against r'^person/person/(?P<slug>[-\w]+)/$'
You've probably matched ^person/ in a urls.py, then imported another urls.py and put "person" in there also. Remove it from the second urls.py. After importing, a secondary urls.py only has to match the rest of the URL, not the whole URL.