Is there a way to add context to Django reverse function? - python

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

Related

Django: Make query using url ( Assigning variable using url )

I am trying to make a query system for my website, i think the best way and the most compact would be to assign search variable using url pattern.
So for example, i want to search objects of model User:
User sends HttpRequest to following url:
https://127.0.0.1/search/q="admin"
Now HttpRequest is also sent to search view, we somehow get q variable data.
def search(request):
for query in User.objects.all():
if q in query: # < We somehow need to get data of 'q'.
return HttpResponse(q)
Since i have admin in User.objects.all(), this should return HttpResponse of 'admin'.
How can this url pattern be made? So i can assign q variable from the url and then send it to system to find it?
I have problems with this URL:
https://127.0.0.1/search/q="admin"
There is no ? in the URL, so there is no query string, it's all part of the "path". Using characters like = and " in there will confuse a lot of things, if it works at all.
Either just do
https://127.0.0.1/search/admin
With an URL pattern like r'^search/(?P<querystring>.+)$', or
https://127.0.0.1/search/?q=admin
In this case the query string will be in request.GET['q']; it's also possible to use Django forms to process query parameters (e.g. for validating them).
You can capture named strings from URLs like this:
urls.py:
urlpatterns = [
url(r'^blog/page(?P<num>[0-9]+)/$', views.page),
]
views.py:
def page(request, num="1"):

Django Rest Framework for function based views

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 = ""):

How to use current logged in user as PK for Django DetailView?

When defining URL patterns, I am supposed to use a regular expression to acquire a PK from the URL.
What if I want a URL that has no PK, and if it's not provided, it will use the currently logged in user? Examples:
visiting /user will get a DetailView of the currently logged in user
/user/edit will show an UpdateView for the currently logged in user
I tried hard-coding the pk= in the Detail.as_view() call but it reports invalid keyword.
How do I specify that in the URL conf?
My sample code that shows PK required error when visiting /user URL:
urlpatterns = patterns('',
url(r'user/$',
DetailView.as_view(
model=Account,
template_name='user/detail.html')),
)`
An alternative approach would be overriding the get_object method of the DetailView subclass, something along the line of:
class CurrentUserDetailView(UserDetailView):
def get_object(self):
return self.request.user
Much cleaner, simpler and more in the spirit of the class-based views than the mixin approach.
EDIT: To clarify, I believe that two different URL patterns (i.e. one with a pk and the other without) should be defined separately in the urlconf. Therefore they could be served by two different views as well, especially as this makes the code cleaner. In this case the urlconf might look something like:
urlpatterns = patterns('',
url(r"^users/(?P<pk>\d+)/$", UserDetailView.as_view(), name="user_detail"),
url(r"^users/current/$", CurrentUserDetailView.as_view(), name="current_user_detail"),
url(r"^users/$", UserListView.as_view(), name="user_list"),
)
And I've updated my example above to note that it inherits the UserDetailView, which makes it even cleaner, and makes it clear what it really is: a special case of the parent view.
As far as I know, you can't define that on the URL definition, since you don't have access to that information.
However, what you can do is create your own mixin and use it to build views that behave like you want.
Your mixin would look something like this:
class CurrentUserMixin(object):
model = Account
def get_object(self, *args, **kwargs):
try:
obj = super(CurrentUserMixin, self).get_object(*args, **kwargs)
except AttributeError:
# SingleObjectMixin throws an AttributeError when no pk or slug
# is present on the url. In those cases, we use the current user
obj = self.request.user.account
return obj
and then, make your custom views:
class UserDetailView(CurrentUserMixin, DetailView):
pass
class UserUpdateView(CurrentUserMixin, UpdateView):
pass
Generic views uses always RequestContext. And this paragraph in the Django Documentation says that when using RequestContext with auth app, the template gets passed an user variable that represents current user logged in. So, go ahead, and feel free to reference user in your templates.
You can get the details of the current user from the request object. If you'd like to see a different user's details, you can pass the url as parameter. The url would be encoded like:
url(r'user/(?P<user_id>.*)$', 'views.user_details', name='user-details'),
views.user_details 2nd parameter would be user_id which is a string (you can change the regex in the url to restrict integer values, but the parameter would still of type string). Here's a list of other examples for url patterns from the Django documentation.

regular expression in django for urls

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.

Django: How to write the reverse function for the following

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.

Categories

Resources