Django basic url slugifying issues - django

I want to slugify my urls in my Django application. I have read many documents but I am still not sure how to do it better. I have two questions:
How to call the same view for two different urls?
I would like to call home view for both www.mysite.com and www.mysite.com/index.html
(r'^$', 'myapp.main.views.home')
(r'([-\w]+)$', 'myapp.main.views.home')
The code above sounds good but of course it raises an error as home view expects 1 parameter but 2 is given. How can I resolve this?
I have so many apps and they all have their own urls.py file. I was handle them as including their urls file to the root urls.py as
(r'^warehouse/', include('myapp.warehouse.urls')),
In that way, urls seems like www.mysite.com/warehouse/blabla/
However, I want to slugify them as www.mysite.com/warehouse_blabla.html
Slugifying is not hard but how can I resolve such url and redirect it to the blabla view in warehouse app?
Thanks

Regarding the first problem, you would be better off using a redirect for the index.html URL (better for SEO etc.)
from django.views.generic.simple import redirect_to
urlpatterns = patterns('',
url(r'^$', 'myapp.main.views.home')
url(r'^index.html$', redirect_to, {'url': '/'}),
)
Regarding the second issue, your urls.py file is just a set of regular expressions, so you have control over the URL scheme you want to use:
urlpatterns = patterns('',
url(r'^warehouse_(?P<slug>[_w]+).html$', 'warehouse.views.warehouse_detail'),
)
That said, I think you would be better sticking to the usual convention of slashes

Related

Using a name for dummy url patterns in django

I have a project with an app named exams. Right now my index page is the index page of one of these apps. So the url patterns is something like this:
from django.conf.urls import patterns, include, url
urlpatterns = patterns('',
url(r'^', include('exams.urls', namespace="exams")),
)
However it is possible that in future I want to create a new view for my index page and change the url patterns to something like this:
from django.conf.urls import patterns, include, url
urlpatterns = patterns('',
url(r'^exams/', include('exams.urls', namespace="exams")),
url(r'^/$', 'mysite.views.index', name="index"),
)
I want to create some links in my template to index whether it loads the exams app or another view. So I tried to use the name argument for the url method(like above) but it seems it's not working. When I use {% url 'index' %} in my template it returns the following error:
Reverse for 'index' with arguments '()' and keyword arguments '{}' not found. 0 pattern(s) tried: []
UPD: I forgot to mention that I tried using the following code:
from django.conf.urls import patterns, include, url
urlpatterns = patterns('',
url(r'^', include('exams.urls', namespace="exams"), name="index"),
)
And I got the error I wrote above.
UPD2: To clarify the problem more:
Right now when I go to http://mydomain/ I'll see my app index. But maybe in the future I like to change my index page and use another view for creating it. So when I go to http://mydomain/ I'll see the page rendered by that view and by going to http://mydomain/exams I'll see my apps index pages. In that case my urls.py will be sth like the second code I wrote above in which I can easily link to index page using {% url 'index' %} tag. However for now I'm using the code I wrote in my first update. I want my templates to render {% url 'index' %} as a link to my index page(instead of using {% url 'exams:index' %} so when I later change the urls.py code I won't have to change all of my templates.
If I understand well, you want an index view that could be easily changed, while not changing the links pointing to it in your templates. You can use your index view as a wrapper for other views ie:
def a_view_that_will_show_all_the_exams(request):
# this is the page displayed for now as default, but this could change
# some logic here
def another_view_that_could_become_the_home_page(request):
# some logic here
def index(request):
return a_view_that_will_show_all_the_exams(request)
# or another_view_that_could_become_the_home_page
# or return exams.views.whatever_view
This way you can easily change the result of the index view while keeping your links static.
If I understood you correctly, right now you don't have a url with the name index, in his case it is normal that when the template renders, it tries to find a url named index, and when it doesn't find it, it fails. What you might need is create the url and redirect to another view for now, like explained here:
Redirect to named url pattern directly from urls.py in django?
UPDATE:
I'm still not completely sure of what you want (sorry about that), but I suspect what you want to do is something similar to this:
from django.conf.urls import patterns, include, url
from django.core.urlresolvers import reverse_lazy
from django.views.generic import RedirectView
urlpatterns = patterns('',
url(r'^exams/', include('exams.urls', namespace="exams")),
url(r'^/$', RedirectView.as_view(url=reverse_lazy('exams:index'), name="index"),
)
The solution that Raphael is giving you is similar, but the user will not be redirected (with both urls the user will see the same content). Maybe that is what you are looking for?

urls.py structure for Django music app

I'm having some issues with the structuring of my Django app's urls.py file.
My project is a basic music player app. You begin by clicking a link for Music, followed by (for example) Artists, then you choose an artist, such as Weezer. The app then displays a list of albums and songs by that artist, rendered on the artist_name.html template by the views.artist_name function.
So far in the navigation of the app, the URL will look like http://localhost/music/artists/Weezer/.
My problem lies with the encoding of the next URL. If I choose the album The Blue Album by Weezer, I return the URL: http://localhost/music/artists/Weezer/The%20Blue%20Album.
This should render a template called artist_album_title.html using the views.artist_album_title function. Instead, it renders the new page using the same views.artist_name function as on the current page.
What seems to be happening is that the regex pattern for the ...Weezer/The%20Blue%20Album/ isn't matching with its related URL pattern in my urls.py file. Being new to Django (and with minimal experience with regex), I'm having a hard time determining what my urls.py file should look like for this kind of app.
Below is my urls.py file as it currently stands. Any help at all with my problem would be welcomed. Thanks guys.
from django.conf.urls import patterns, include
from music.views import home, music, artists, artist_name, artist_album_title
# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
(r'^admin/', include(admin.site.urls)),
(r'^$', home),
(r'^music/$', music),
(r'^music/artists/$', artists),
(r'^music/artists/([\w\W]+)/$', artist_name),
(r'^music/artists/([\w\W]+)/([\w\W]+)/$', artist_album_title),
)
artist_album_title function from views.py
def artist_album_title(request, album_title):
album_tracks = Track.objects.filter(album__title=album_title)
return render_to_response('artist_album_title.html', locals(), context_instance=RequestContext(request))
The problem with your urlpatterns is that the url /music/artists/Weezer/The%20Blue%20Album satisfies the first pattern so it doesn't go to the next one. This is because Django executes the patterns in the order they are specified.
In order for this to work you must switch the places of the two patterns like so:
urlpatterns = patterns('',
(r'^admin/', include(admin.site.urls)),
(r'^$', home),
(r'^music/$', music),
(r'^music/artists/$', artists),
(r'^music/artists/([\w\W]+)/([\w\W]+)/$', artist_album_title),
(r'^music/artists/([\w\W]+)/$', artist_name),
)
The best would be to use the following structure for your urls:
urlpatterns = patterns('',
(r'^admin/', include(admin.site.urls)),
(r'^$', home),
(r'^music/$', music),
(r'^music/artists/$', artists),
(r'^music/artists/(?P<artist_name>[\w\W]+)/(?P<album_title>[\w\W]+)/$', artist_album_title),
(r'^music/artists/(?P<artist_name>[\w\W]+)/$', artist_name),
)
and then your views definition will look like this:
def artist_album_title(request, artist_name,album_title):
and
def artist_name(request, artist_name):
you can read more about the named groups in the url in Django docs here
https://docs.djangoproject.com/en/dev/topics/http/urls/#named-groups

Django URL-Patterns not working as expected when using INCLUDE

I am currently working my way through the Django Tutorial (Step 3) and am stuck at the part with "Decoupling the URLconfs".
What I try to do is to set up one URL-Pattern that catches lnadmin/, to redirect to the django admin, and eventually another catch-all that redirects to other patterns included from another file.
Here's my mysite/urls.py:
from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^lnadmin/', include(admin.site.urls)), #match admin
url(r'^test/', include('lnapp.urls')), #match test, should be a catch-all later
)
and here's the lnapp/urls.py, which is supposed to match hash/(anything)/:
from django.conf.urls import patterns, include, url
urlpatterns = patterns('lnapp.views',
url(r'^hash/(?P<hash>.+)/$', 'hash'), #match part to load from hash
)
I had this pattern in the main url.py before, and it worked as intended.
What's happening now is that when I open (mydomain)/lnadmin/, it tries to access lnapp.views.hash (Could not import lnapp.views.hash, as no view is defined yet).
This doesn't make any sense to me, as lnadmin/ should be matched by the first pattern, and /lnadmin/ doesn't match test/hash/(anything)/. As soon as I comment out the one url in lnapp/urls.py, it redirects to the admin, as intended.
Swapping both urls in the main url.py has no effect.
The answer to my own question is: you have to define a view even for the unmatched urls, or else it will fail.

Should every django app within a project have it's own urls.py?

I am working on a django project which will contain several apps. Each app will have their own set of models and views.
Should each app also define their own url's with a urls.py or maybe a function. What is the best practice for defining urls of apps within a django project, and integrating these urls with the main urls.py (root url conf) ?
It depends. If you're dealing with a tiny website with one app, you can keep all the expressions in the same urls.py.
However, when you're dealing with a more complicated site with truly separate apps, I prefer the following structure:
myapp
admin.py
forms.py
models.py
urls.py
views.py
manage.py
settings.py
urls.py
Don't forget each folder needs it's own __ init__.py
# urls.py
from django.conf.urls.defaults import *
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
# Notice the expression does not end in $,
# that happens at the myapp/url.py level
(r'^myapp/', include('myproject.myapp.urls')),
)
# myapp/urls.py
from django.conf.urls.defaults import *
urlpatterns = patterns('myproject.myapp.views',
(r'^$', 'default_view',
(r'^something/$', 'something_view',
)
You also may want to look at Class-based Generic Views
If your app is going to display anything to the user with its own url pattern, it should probably have its own urls.py file. So in your base urls file, you'd have something in your urlpatterns like url(r'', include('path.to.app.urls')). Then your app's urls.py file would have a pattern like url(r'^$', 'path.to.app.views.view').
If the app is mostly self-contained and having its own place in the URL hierarchy makes sense, then it should have its own urls.py. But even if it does exist, it's still only a guideline to the project developer unless include() is used to graft it into the project URLconf.

What's the best way to map the main urls in a django project?

I've got a django project that contain some apps. The main urls.py includes the urls.py from the apps I've enabled, and all is good.
Now I want to configure the project so that when you go to http://testsite/, you'll get the same page that you get when you go to http://testsite/app/.
I can do this by duplicating the corresponding line in the apps urls.py in the projects urls.py, but this feels dirty.
Anyone know a better way?
Set up a redirect_to from the first url to the second, ie:
from django.conf.urls.defaults import patterns, url, include
from django.views.generic.simple import redirect_to
urlpatterns = patterns('',
# Example:
url(r'^$', redirect_to, {'url':'/app/'}),
url(r'^app/', include('app.urls')),
# ...
)
HTH
A redirect is the way to go, because you don't want multiple canonical URLs for the same resource (wastes Google juice). Ideally, you should do the redirect as close to the edge of your stack as possible to conserve server resources. So you can do a Django redirect_to urlconf entry, but you'd be better off with an Apache or nginx or insert-your-webserver-here redirect, so the initial request never has to hit Django at all.