Django, name parameter in urlpatterns - python

I'm following a tutorial where my urlpatterns are:
urlpatterns = patterns('',
url(r'^passwords/$', PasswordListView.as_view(), name='passwords_api_root'),
url(r'^passwords/(?P<id>[0-9]+)$', PasswordInstanceView.as_view(), name='passwords_api_instance'),
...other urls here...,
)
The PasswordListView and PasswordInstanceView are supposed to be class based views.
I could not figure out the meaning of the name parameter. Is it a default parameter passed to the view?

No. It is just that django gives you the option to name your views in case you need to refer to them from your code, or your templates. This is useful and good practice because you avoid hardcoding urls on your code or inside your templates. Even if you change the actual url, you don't have to change anything else, since you will refer to them by name.
e.x with views:
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse #this is deprecated in django 2.0+
from django.urls import reverse #use this for django 2.0+
def myview(request):
passwords_url = reverse('passwords_api_root') # this returns the string `/passwords/`
return HttpResponseRedirect(passwords_url)
More here.
e.x. in templates
<p>Please go here</p>
More here.

Related

How to redirect url pattern with variables from urls.py in Django?

I'd like to redirect url pattern with variables from urls.py.
I refer other stackoverflow solution, but I don't know when url having a variable like following code.
from django.conf.urls import patterns, url
from django.views.generic import RedirectView
urlpatterns = patterns(
url(
r'^permalink/(?P<id>\d+)/foo/$',
RedirectView.as_view(url='/permalink/(?P<id>\d+)/')
),
)
With this code, django will redirect /permalink/1/foo/ to /permalink/(?P<id>\d+)/, not the /permalink/1/.
Is there any solution without using views.py?
Of course I know solution using controller, but I wonder is there any simpler solution with using url pattern.
Passing url='/permalink/(?P<id>\d+)/' to RedirectView will not work, because the view does not substitute the named arguments in the url.
However, RedirectView lets you provide the pattern_name instead of the url to redirect to. The url is reversed using the same args and kwargs that were passed for the original view.
This will work in your case, because both url patterns have one named argument, id.
urlpatterns = [
url(r'^permalink/(?P<id>\d+)/foo/$',
RedirectView.as_view(pattern_name="target_view"),
name="original_view"),
url(r'^permalink/(?P<id>\d+)/$', views.permalink, name="target_view"),
]
If the target url pattern uses other arguments, then you can't use url or pattern_name. Instead, you can subclass RedirectView and override get_redirect_url.
from django.core.urlresolvers import reverse
from django.views.generic import RedirectView
class QuerystringRedirect(RedirectView):
"""
Used to redirect to remove GET parameters from url
e.g. /permalink/?id=10 to /permalink/10/
"""
def get_redirect_url(self):
if 'id' in self.request.GET:
return reverse('target_view', args=(self.request.GET['id'],))
else:
raise Http404()
It would be good practice to put QuerystringRedirect in your views module. You would then add the view to your url patterns with something like:
urlpatterns = [
url(r'^permalink/$', views.QuerystringRedirect.as_view(), name="original_view"),
url(r'^permalink/(?P<id>\d+)/$', views.permalink, name="target_view"),
]

Django Tutorial "Write Views That Actually Do Something"

I've been working on the Django tutorial. I'm on the part where it is "Write Views That Actually Do something." (Part 3)
I'm trying to use the index.html template that it gives you, but I keep getting a 404 error that says
Request Method: GET
Request URL: http://127.0.0.1:8000/polls/index.html
Using the URLconf defined in mysite.urls, Django tried these URL patterns, in this order:
^polls/ ^$ [name='index']
^polls/ ^(?P<question_id>\d+)/$ [name='detail']
^polls/ ^(?P<question_id>\d+)/results/$ [name='results']
^polls/ ^(?P<question_id>\d+)/vote/$ [name='vote']
^admin/
The current URL, polls/index.html, didn't match any of these.
I don't know if one of the regex are wrong? I've been messing around with it for a while now and I have had no luck getting it to work.
I can go to /polls just fine. But /polls/index.html does not work.
Any help would be appreciated.
The version of Django that I'm using is 1.7.4
Django view functions or classes use the template you define, so that you do not have to specify it in the URL. The urls.py file matches your defined regex to send requests to views.
If you truly wanted to use that URL, you would have to define ^polls/index.html$ in your urls.py and direct it to your view.
From what you're asking it sounds like you essentially want to output a static html file on a URL defined in your urlpatterns in urls.py.
I strongly suggest you take a look at Class Based Views.
https://docs.djangoproject.com/en/1.7/topics/class-based-views/#simple-usage-in-your-urlconf
The quickest way to go from what you've got, to rendering polls/index.html would be something like;
# some_app/urls.py
from django.conf.urls import patterns
from django.views.generic import TemplateView
urlpatterns = patterns('',
(r'^polls/index.html', TemplateView.as_view(template_name="index.html")),
)
But I'm sure you'll want to pass things to the template so class based views will be what you need. So the alternative to the above with added context would be;
# some_app/views.py
from django.views.generic import TemplateView
class Index(TemplateView):
template_name = "index.html"
def get_context_data(self, **kwargs):
context = super(Index, self).get_context_data(**kwargs)
context['foo'] = 'bar'
return context
Then obviously adding {{ foo }} to your index.html would output bar to the user. And you'd update your urls.py to;
# some_app/urls.py
from django.conf.urls import patterns
from .views import Index
urlpatterns = patterns(
'',
(r'^polls/index.html', Index.as_view()),
)

Serializing with django rest framework

I have the model named Artist and I want expose this model with Django Rest Framework to create an API and this data can be consumed.
I've created a class based view in artists/views.py named ArtistViewSet
#CBV for rest frameworks
from rest_framework import viewsets
class ArtistViewSet(viewsets.ModelViewSet):
model = Artist
I also have an url named api/ in the urls.py file (view third url named api/) which the user could access to the view above mentioned.
# coding=utf-8
from django.conf.urls import patterns, include, url
from django.conf import settings
from django.contrib import admin
admin.autodiscover()
from rest_framework import routers
from artists.views import ArtistViewSet
#I create a router by default
router = routers.DefaultRouter()
#Register the model 'artists' in ArtistViewSet
router.register(r'artists', ArtistViewSet)
urlpatterns = patterns('',
(r'^grappelli/', include('grappelli.urls')), # grappelli URLS
url(r'^admin/', include(admin.site.urls)),
#Include url api/ with all urls of router
url(r'^api/', include(routers.urls)),
)
When I go to my browser and type http://localhost:8000/api/ I get this message error:
What did can be happened me?
In Django REST framework 2.4+ (including 3.0+), the model attribute for views has been deprecated and removed. This means that you should be defining your view as
from rest_framework import viewsets
class ArtistViewSet(viewsets.ModelViewSet):
queryset = Artist.objects.all()
Which should give you the result you are expecting. Now, you asked in the comments
I cannot understand the role of base_name. I mean, this base name is the url that I've created? My viewset ArtistViewSet does not have a queryset attribute, due to this, according to documentation, it's necessary put the base_name argument, but i don't know how to do it.
The base_name that can be optionally defined when registering a ViewSet is used when naming the automatically generated routes. By default, the format is [base]-list and [base]-detail, where [base] is the base_name that can be defined. When you do not specify your own base_name, it is automatically generated based on the model name. As the queryset method must be defined for ViewSet instances, this is where the model (and later model name) is retrieved. As you did not provide the queryset argument, Django REST framework triggers an error because it cannot generate a base_name.
To quote from the documentation on routers
Note: The base_name argument is used to specify the initial part of the view name pattern.
The documentation goes on to further explain exactly why you are getting the issue, even including an example, and how to fix it.

Django / From redirect_to to RedirectView

Since you know, we can't use from django.views.generic.simple import redirect_to in Django 1.5. However we were using this kind of functions in our views.py:
return redirect_to(request, '/auth/login/')
I want to migrate from 1.4 to 1.5 but I couldn't figure out how to use RedirectView in views.py with request and url argument.
You can use redirect instead
Now you can simply change the redirect_to to
return redirect('/auth/login')
You can use Class based views or RedirectView
RedirectView helps you to redirect your url which works as like redirect_to. Both are applied in urls.py. But I couldn't find any solution to redirect from views.py.
Source: "No module named simpleā€ error in Django

Customized views with django-registration

I need to make a very simple modification -- require that certain views only show up when a user is not authenticated -- to django-registration default views. For example, if I am logged in, I don't want users to be able to visit the /register page again.
So, I think the idea here is that I want to subclass the register view from django-registration. This is just where I'm not sure how to proceed. Is this the right direction? Should I test the user's authentication status here? Tips and advice welcomed!
Edit
I think this is the right track here: Django: Redirect logged in users from login page
Edit 2
Solution:
Create another app, for example, custom_registration, and write a view like this (mine uses a custom form as well):
from registration.views import register
from custom_registration.forms import EduRegistrationForm
def register_test(request, success_url=None,
form_class=EduRegistrationForm, profile_callback=None,
template_name='registration/registration_form.html',
extra_context=None):
if request.user.is_authenticated():
return HttpResponseRedirect('/')
else:
return register(request, success_url, form_class, profile_callback, template_name, extra_context)
I had to use the same function parameters, but otherwise just include the test, and if we pass it, continue to the main function.
Don't forget to put this in your URLConf either (again, this includes some stuff about my custom form as well):
top-level URLConf
(r'^accounts/', include('custom_registration.urls')),
(r'^accounts/', include('registration.urls')),
custom_registration.views
from django.conf.urls.defaults import *
from custom_registration.views import register_test
from custom_registration.forms import EduRegistrationForm
urlpatterns = patterns('',
url(r'^register/$', register_test, {'form_class': EduRegistrationForm}, name='registration.views.register'),
)
As far as I remember django-registration is using function-based views, so you can not really subclass them. The approach I usually follow is "overwriting" the original views (without modifying the django-registration app of course). This works like this:
Create another app (you could call it custom_registration or whatever you want)
This app need to contain another urls.py and in your case another views.py
Copy the original register view code to your new views.py and modify it, add a pattern to your urls.py to point to this view (use the same url pattern as in django-registration for this view)
Put an include to your projects urls.py of your new app urls.py before your are including the original django-registration app. This could look like this for example:
urlpatterns = patterns('',
...
url(r'^accounts/', include('custom_registration.urls')),
url(r'^accounts/', include('registration.backends.default.urls')),
...
)
This simply works since the first matching url pattern for /accounts/register will point to your new app, so it will never try to call the one from the original app.

Categories

Resources