Synthax to declare urls in django - django

I'm not sure to understand the difference between the two urls below
from django.conf.urls import patterns, url
from main_app import views
urlpatterns = patterns('',
url(r'^$', views.main, name='home'),
(r'^accounts/$', views.accounts, name="account"),
...
)
Both are working for me. Should I use one instead of the other? Why? All the examples I quickly found were reffering to the first synthax but I'd like to understand why.

This is the latest example from the Django Documentation for the urls.py file
from django.conf.urls import patterns, url
urlpatterns = patterns('',
url(r'^articles/2003/$', 'news.views.special_case_2003'),
url(r'^articles/(\d{4})/$', 'news.views.year_archive'),
url(r'^articles/(\d{4})/(\d{2})/$', 'news.views.month_archive'),
url(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'),
)
So you could say this is the standard as most people will learn it that way and it seems it is also promoted this way.

The first syntax, using the url function, allows you to pass a dictionary of keyword arguments to your view.
https://docs.djangoproject.com/en/dev/topics/http/urls/#passing-extra-options-to-view-functions
From the documentation:
urlpatterns = patterns('blog.views',
url(r'^blog/(?P<year>\d{4})/$', 'year_archive', {'foo': 'bar'}),
)
In this example, for a request to /blog/2005/, Django will call
blog.views.year_archive(request, year='2005', foo='bar')

Related

Display static page in Django

I am trying to display contents of a static page in Django project.
urls.py :-
from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
# Examples:
# url(r'^$', 'spollow.views.home', name='home'),
# url(r'^blog/', include('blog.urls')),
(r'^$', 'django.views.generic.simple.direct_to_template', {'template': 'index.html'}),
url(r'^admin/', include(admin.site.urls)),
)
index.html is in the same directory as urls.py
I am getting 500 internal server error. Any ideas where I am going wrong?
First of all, what is the stacktrace from the 500 error saying that the error may be? You may be using Django 1.6 and the call to direct_to_template is deprecated.
On Django 1.5 or newer you can use TemplateView
Here's the example from the documentation
https://docs.djangoproject.com/en/dev/topics/class-based-views/
from django.conf.urls import patterns
from django.views.generic import TemplateView
urlpatterns = patterns('',
(r'^about/', TemplateView.as_view(template_name="about.html")),
)
You can use the direct_to_template view on Django 1.4 or older
Here's the relevant documentation
https://docs.djangoproject.com/en/1.4/ref/generic-views/#django-views-generic-simple-direct-to-template
from django.views.generic.simple import direct_to_template
urlpatterns = patterns('',
(r'^foo/$', direct_to_template, {'template': 'foo_index.html'}),
(r'^foo/(?P<id>\d+)/$', direct_to_template, {'template': 'foo_detail.html'}),
)
If it is the latter, I would use a module instead of string, (look at the import on the example).
Other than that, without the 500 details it will be shooting in the dark, you may not have the right template, or an incorrect path, or a million different things.
Bonus note
If you just want to serve static pages, it might be better to serve them through the actual webserver in front of django (nginx, apache, etc), specially if you are expecting a high volume of traffic.
If Your error is due to unable to find index.html
if yours is an app(ie: created by python manage.py startapp <app>) then:
Then django will search for template files in <app>/templates directory, if you added the app to INSTALLED_APPS in settings.py.
so you need to create a folder templates inside your <app> and put index.html inside it.
if you don't have any apps, you want to add the template path manually :
open settings.py, then edit TEMPLATE_DIRS
TEMPLATE_DIRS = (
# Put the full path of the template dir here, like "/home/html/django_templates" or
# "C:/www/django/templates".
)
In Django 1.5 or newer you can use the render function instead of direct_to_template:
from django.conf.urls import patterns, include, url
urlpatterns = patterns('',
url(r'^$', 'django.shortcuts.render', {'template_name': 'index.html'}),
)
Or if you prefer the more complex way :), you can use class-based TemplateView:
from django.conf.urls import patterns, include, url
from django.views.generic import TemplateView
urlpatterns = patterns('',
url(r'^$', TemplateView.as_view(template_name="index.html")),
)

How to add more than one link in Django 1.6.1 urls.py

I am trying to add more than one link to my urls.py. First code below is in the app url, and other one in the main urls. However; when I am trying to add REGISTER and run the server, it still displays me the same of BLOG page.
from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^blog/', include('blog.urls')),
url(r'^register/', include('blog.urls')),
url(r'^admin/', include(admin.site.urls)),)
This one in the main urls.py
from django.conf.urls import patterns, url
from blog import views
urlpatterns = patterns('',
url(r'^$', views.index, name='index'),
url(r'^$', views.register, name='register'),)
What should I do to fix this situation? Any idea will be appreciated. Thanks in advance
Your main urls.py should have:
url(r'^register/$', views.register, name='register'),)
and you should remove the register from app urls.
This will make yourapp.com/register/ point to views.register (or possibly yourapp.com/blog/register/ view it - I'm slightly confused on which urls.py is taking precedence)
The first block of code should be in your project's folder/project folder/urls.py, so paste it there. The second block is perfect, it should be placed in the new urls.py that you have created recently in the apps folder.

Why is the url function used more often in Django 1.5 documentation?

I'm working with some older Django code and the url function is not used anywhere, similar to the examples in the Django 1.4 documentation:
from django.conf.urls import patterns, url, include
urlpatterns = patterns('',
(r'^articles/2003/$', 'news.views.special_case_2003'),
(r'^articles/(\d{4})/$', 'news.views.year_archive'),
(r'^articles/(\d{4})/(\d{2})/$', 'news.views.month_archive'),
(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'),
)
but I notice in the Django 1.5 documentation the url function is used frequently:
from django.conf.urls import patterns, url
urlpatterns = patterns('',
url(r'^articles/2003/$', 'news.views.special_case_2003'),
url(r'^articles/(\d{4})/$', 'news.views.year_archive'),
url(r'^articles/(\d{4})/(\d{2})/$', 'news.views.month_archive'),
url(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'),
)
Why is this? Is it a matter of convention, or is there a technical reason to use the url function? Which practice should I follow in the future, and how should I maintain my legacy code without url calls?
From the docs
url(regex, view, kwargs=None, name=None, prefix='')
You can use the url() function, instead of a tuple, as an argument to patterns(). This is convenient if you want to specify a name without the optional extra arguments dictionary. For example:
urlpatterns = patterns('',
url(r'^index/$', index_view, name="main-view"),
...
)
And you use them for reverse URL matching (again, the docs)
You could convert the first example as:
url(r'^articles/2003/$', special_case_2003, name="special_case_2003"),
and call it in your template
{% url special_case_2003 %}
Yeah, maybe the two examples you posted are a bit too fuzzy about this

Redirect to named url pattern directly from urls.py in django?

In Django, how can I do a simple redirect directly from urls.py? Naturally I am a well organized guy, favoring the DRY principle, so I would like to get the target based on it's named url pattern, rather than hard coding the url.
If you are on Django 1.4 or 1.5, you can do this:
from django.core.urlresolvers import reverse_lazy
from django.views.generic import RedirectView
urlpatterns = patterns('',
url(r'^some-page/$', RedirectView.as_view(url=reverse_lazy('my_named_pattern'), permanent=False)),
...
If you are on Django 1.6 or above, you can do this:
from django.views.generic import RedirectView
urlpatterns = patterns('',
url(r'^some-page/$', RedirectView.as_view(pattern_name='my_named_pattern', permanent=False)),
...
In Django 1.9, the default value of permanent has changed from True to False. Because of this, if you don't specify the permanent keyword argument, you may see this warning:
RemovedInDjango19Warning: Default value of 'RedirectView.permanent' will change from True to False in Django 1.9. Set an explicit value to silence this warning.
This works for me.
from django.views.generic import RedirectView
urlpatterns = patterns('',
url(r'^some-page/$', RedirectView.as_view(url='/')),
...
In above example '/' means it will redirect to index page,
where you can add any url patterns also.
for django v2+
from django.contrib import admin
from django.shortcuts import redirect
from django.urls import path, include
urlpatterns = [
# this example uses named URL 'hola-home' from app named hola
# for more redirect's usage options: https://docs.djangoproject.com/en/2.1/topics/http/shortcuts/
path('', lambda request: redirect('hola/', permanent=False)),
path('hola/', include("hola.urls")),
path('admin/', admin.site.urls),
]
I was trying to redirect all 404s to the home page and the following worked great:
from django.views.generic import RedirectView
# under urlpatterns, added:
url(r'^.*/$', RedirectView.as_view(url='/home/')),
url(r'^$', RedirectView.as_view(url='/home/')),
This way is supported in older versions of django if you cannot support RedirectView
In view.py
def url_redirect(request):
return HttpResponseRedirect("/new_url/")
In the url.py
url(r'^old_url/$', "website.views.url_redirect", name="url-redirect"),
You can make it permanent by using HttpResponsePermanentRedirect
You could do straight on the urls.py just doing something like:
url(r'^story/(?P<pk>\d+)/',
lambda request, pk: HttpResponsePermanentRedirect('/new_story/{pk}'.format(pk=pk)))
Just ensure that you have the new URL ready to receive the redirect!!
Also, pay attention to the kind of redirect, in the example I'm using Permanent Redirect

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