The urlconf and view is as follows:
url(r'^register/$',
register,
{ 'backend': 'registration.backends.default.DefaultBackend' },
name='registration_register'),
def register(request, backend, success_url=None, form_class=None,
disallowed_url='registration_disallowed',
template_name='registration/registration_form.html',
extra_context=None):
What i want to do is redirect users to the register page and specify a success_url. I tried reverse('registration.views.register', kwargs={'success_url':'/test/' }) but that doesn't seem to work. I've been trying for hours and can't get my mind around getting it right. Thanks
If you want to be able to specify reverse() with parameters, those parameters have to be defined in the URL configuration itself (regexp). Something like:
url(r'^register/(?P<success_url>[\w\/]+)/$',
register,
{ 'backend': 'registration.backends.default.DefaultBackend' },
name='registration_register'),
You can wrap that URL section in ()? to make it optional (So that it matches just simple register/ too)
The difference between args and kwargs is that with args you can specify unnamed/named URL params while with kwargs only named.
So:
r'^register/(?P<success_url>\w+)/$'
reverse('url_name', args=[my_success_url])
reverse('url_name', kwargs={'success_url': my_success_url}) // both work and do the same
r'^register/(\w+)/$'
reverse('url_name', args=[my_success_url]) // only this works
Edit:
For success_url params, if you want to be able to match any full relative URL, including possible GET params in the relative URL, the actual regexp could get pretty complex.
Something like (untested):
r'^register/(?P<success_url>[\w\/]+(((\?)([a-zA-Z]*=\w*)){1}((&)([a-zA-Z]*=\w*))*)?)/$'
Edit: Sorry, completely misread the question - I didn't look at the function definition. Actually, the issue here is that your URLconf is designed in such a way as to make it impossible to set the success_url dynamically. It has to be passed explicitly to the function via the extra_context dictionary - ie the one where you have currently defined backend. Since there is nothing in the URL itself to accept this parameter, it has to be hard-coded there.
Related
Is it possible to pass context through the reverse function in Django in some way like reverse('foo', context={'bar':'baz'})? Or is there a better workaround?
As already described by Sir WillemVanOnsem in the above comment.
You can't provide context in reverse as it only produces a string: a path, eventually it goes to view.
reverse() can only take args and kwargs, see Reversing namespaced URLs for more detail.
Reverse generates an URL. The URL can parse or supply extra context. In urls.py,
path( 'action/<str:context>/', MyView.as_view(), name='foo' )
then
reverse('app:foo', kwargs={'context':'bar:baz+quux:help'} )
will generate the URL ending
.../appname/action/bar:baz+quux:help
and your view will parse context:
context = self.kwargs.get( context, '')
context_dir = {}
for kv in context.split('+'):
keyval = kv.split(':')
context_dir[ keyval[0].strip() ] = keyval[1].strip()
or something like this, ending with context_dir as {'bar':'baz', 'quux':'help'}
Alternatively you can append a querystring to the URL returned by reverse and retrieve that in the view you redirect to via request.GET
url = reverse('foo') + '?bar=baz&quux=help'
redirect, and then in that view request.GET.get('bar') will return "baz" etc.
Finally you can stuff an almost arbitrarily complex context into the user's session (which gets stored either as a cookie in his browser, or an object in your database). This is the most general but also the most complex. See the doc for using Django sessions
I want url to have optional url parameter. Primary url is:
url(r'^(?P<letnik_id>[1-4])/(?P<classes_id>[A-G])/(?P<subject_id>[\w\-]+)$', views.subject, name="subject_id"),
but after subject id i want to be able to add optional parameter that is always a number:
url(r'^(?P<letnik_id>[1-4])/(?P<classes_id>[A-G])/(?P<subject_id>[\w\-]+)/(?P<digit>\d+)/$'', views.subject, name="subject_id_optional"),
Im not even sure if did that correctly, as i dont know how to set number for parameter. So after the parameter is passed i want the (template?) or maybe view to read the number (which is model's ID number) and add css class ) .highlited-model {background-color: red;} to that model.
How would i achieve this and how should i handle it in views or template, wherever it makes more sense?
I think you can just have two urls pointing to the same view, one with your optional parameter, and one without:
urls = [
url(r'^(?P<letnik_id>[1-4])/(?P<classes_id>[A-G])/(?P<subject_id>[\w\-]+)/(?P<digit>\d+)/$', views.subject, name="subject_id_optional"),
url(r'^(?P<letnik_id>[1-4])/(?P<classes_id>[A-G])/(?P<subject_id>[\w\-]+)$', views.subject, name="subject_id"),
]
def subject(request, optional_parameter=''):
return render(
request,
"template.html",
{
"optional_parameter": optional_parameter
}
)
Then you can get the parameter in your template as you would any other variable passed into the context.
I'm having trouble getting the JSON for function based views in django. I have the below code. I basically would like the function to return either json or an html page based on the user request.
#api_view(['GET'])
#renderer_classes((JSONRenderer,TemplateHTMLRenderer,BrowsableAPIRenderer))
def meld_live_orders(request):
if request.method =='GET':
current_orders = Meld_Sales.objects.values_list('TicketNo',flat=True).distinct()
prev_orders = Meld_Order.objects.values_list('TicketNo',flat =True).distinct()
live_orders = live_order_generator(current_orders,prev_orders)
return render(request,'live_orders.html',{'live_orders':live_orders})
When i go to the url - http://localhost:8000/live-orders.json
I'm getting an error which states the below -meld_live_orders() got an unexpected keyword argument 'format'
Is this because i need to include the serializer class somewhere the same way in CBVs? Doesnt the #API_VIEW serialize the response?
i tried including format = '' in the function argument. but the problem is that it still renders html when i want it to render json.
You need to make some changes to your code.
Firstly, you need to use format_suffix_patterns in your urls if you have not defined it. This will allow us to use filename extensions on URLs thereby providing an endpoint for a given media type.
from rest_framework.urlpatterns import format_suffix_patterns
urlpatterns = [
...
]
urlpatterns = format_suffix_patterns(urlpatterns, allowed=['json', 'html']) # allow us to use '.json' and '.html' at the end of the url
Secondly. your view does not have a format parameter in the definition.
When using format_suffix_patterns, you must make sure to add the
'format' keyword argument to the corresponding views.
#api_view(['GET'])
#renderer_classes((JSONRenderer,TemplateHTMLRenderer,BrowsableAPIRenderer))
def meld_live_orders(request, format=None): # add a 'format' parameter
...
Thirdly, you need to return a DRF response and not a Django response which you are returning at the end of the view.
You must have match a format parameter in the url pattern, but in the view function there is not an argument named format. Change the view definition into:
def meld_live_orders(request, format = ""):
What I am trying to do is as follows
I have urls like this /blog/1/sdc/?c=119 or /forum/83/ksnd/?c=100 What I want to do is to redirect these to a view, so that I can change the url to /blog/1/sdc/#c119
One way would be to do this is to make provision in views of each of the app, where such a url maybe generated, but that is not scalable. What I want to do is to catch any url that has ?c=<some_digit> at the end and redirect to my custom view.
Can anybody help, I am not good with regex.
You can't do this in your urlconf, it doesn't match anything in the query string. What you'll need to do is write a middleware along the lines of this:
class RedirectMiddleware:
def process_request(self, request):
if 'c' in request.GET:
# return a HttpResponseRedirect here
See https://docs.djangoproject.com/en/dev/topics/http/middleware/ for more details.
Consider that I include namespaced reusable application:
urlpatterns = patterns('',
# ella urls
url('^ella/', include('ella.core.urls', namespace="ella")),
)
Now, the Ella applications has urls like that:
urlpatterns = patterns( '',
url( r'^(?P<category>[a-z0-9-/]+)/$', category_detail, name="category_detail" ),
# object detail
url( r'^(?P<category>[a-z0-9-/]+)/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/(?P<content_type>[a-z0-9-]+)/(?P<slug>[a-z0-9-]+)/$',
object_detail, name="object_detail" )
)
Now, calling {% url ella:category_detail category="cat" %} works fine. However, when object tries to generate link to it's details, it calls
from django.core.urlresolvers import reverse
url = reverse('object_detail', kwargs={'required' : 'params'})
This is not working, unless rewritten as
from django.core.urlresolvers import reverse
url = reverse('ella:object_detail', kwargs={'required' : 'params'})
So, if I understand it correctly, including reusable application into namespace breaks all inner reverse()s inside given application.
Is it true? What have I missed? Is there any way around?
Since you have name-spaced url configuration, you need to mention namespace:view-name pattern in order to reverse it properly (especially from view).
But, if you want to avoid this, you may also pass namespace/appname as current_app parameter.
There are multiple ways to specify current_app when you are in template. But if you are in view, you need to hard-code as you did, or pass to current_app parameter
url = reverse('object_detail',
kwargs={'foo':'bar'},
current_app=app_name_or_name_space)
refer: http://docs.djangoproject.com/en/dev/topics/http/urls/#reverse
URL Namespaces can be specified in two ways.
Firstly, you can provide the application and instance namespace as arguments to include() when you construct your URL patterns. For example,:
(r'^help/', include('apps.help.urls', namespace='foo', app_name='bar')),
This is right from http://docs.djangoproject.com/en/dev/topics/http/urls/#defining-url-namespaces.
Try changing include('ella.core.urls', namespace="ella") to include('ella.core.urls', namespace="ella", app_name="ella"). I'm not 100% this will work, but its worth a shot.
At least in Django 1.8 you can write something like this:
url = reverse('%s:object_detail' % request.resolver_match.namespace, kwargs={'required' : 'params'})
request.resolver_match.namespace is a string containing the namespace of the currently running view.