Django cannot retrieve url parameter - python

I'm trying to retrieve a url parameter as part of a simple query within Django but calling kwargs from within the view.py seems to return an empty value (e.g. self.kwargs[name] returns a blank/empty value), it seems Im not picking up the 'name' parameter from the url?
Im pretty new to Django so expect I'm doing something dumb?
I'm using the following url:
myIpAddress:8000/contacts/search_name/?name=gordon
my code:
URL pattern - works fine.
urlpatterns = [
url(r'^contacts/$', ContactList.as_view()),
url(r'^contacts/search_name/(?P<name>\w{0,50})$', ContactDetail.as_view()),
]
view:
class ContactDetail(generics.ListAPIView):
serializer_class = ContactSerializer
def get_queryset(self):
return Contact.objects.filter(name=self.kwargs['name'])

Not sure if it's the best way but I managed to grab the URL parameter using:
self.request.GET.get('name')
This returns the parameter supplied within the url.

Related

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

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

How to set up URL aliases for dynamically created URLs in DJANGO?

In my site, I have pages that are created on the fly using primary keys (for privacy/security reasons using uuid.uuid4()) as the URLs. I end up with .../reports/e657334b-75e2-48ce-8571-211251f1b341/ Is there a way to make aliases for all of these dynamically created sites to something like .../reports/report/.
Right now my urls.py includes the following:
path("reports/<str:pk>/", views.report_detail, name="report")
I tried changing it to:
re_path('reports/<str:pk>/', RedirectView.as_view(url='/reports/report/'), name="report"),
path("reports/report/", views.report_detail),
But I go to the site that has the links to the long URLs, I get the following error:
NoReverseMatch at /reports/Reverse for 'report' with arguments '('e657334b-75e2-48ce-8571-211251f1b341',)' not found. 1 pattern(s) tried: ['reports/str:pk/']
The template for that site includes:
<a class="card-title" href="{% url 'report' report.pk%}">
I also tried the following for urls:
path("reports/report/", views.report_detail),
path('reports/<str:pk>/', RedirectView.as_view(url='reports/report/'), name="report"),
Which allowed the previous site to load, but when I clicked on the link got the following 404 error:
Request URL: http://127.0.0.1:8000/reports/e657334b-75e2-48ce-8571-211251f1b341/reports/report/
I am trying to have one alias for multiple pages - essentially removing/replacing the long uuid with a single word.
Without trying to make an alias, the site works fine.
If you really don't want to pass the pk/uuid of the report to the shortened url, you could pass it in the session
Create a custom RedirectView that saves the pk to the session and then read that pk in the target view
class ReportRedirect(RedirectView):
def get(self, request, pk):
request.session['report_pk'] = pk
return super().get(request, pk)
def report_detail(request):
report_pk = request.session['report_pk']
...
You use the custom RedirectView just like the built-in one
path("reports/report/", views.report_detail),
path('reports/<str:pk>/', views.ReportRedirect.as_view(url='/reports/report/'), name="report"),

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

confusion in url and template in django

My url is :
1. http://localhost:8000/docs/[slug]
2. http://localhost:8000/docs/[slug]/login
1. url calls before number 2. url I want to send
the slug value to the function mapped by the url 2. In template
what should i wrote for form action event.
I agree, this is nearly incomprehensible, but I'm going to give it a go in terms of an answer.
In terms of calling sequence, there is none. A user might first visit url 2 or url 1. You have no way of guaranteeing which they will try to access first because they might directly input the url into their browser. The only thing you can do is set a variable in request.session's dict and test for it with your login url.
In terms of passing slug to another url, if you're having a url with this in it:
urls = ('',
url(r'docs/(?P<slug>\w+)', 'app.views.slug', name='slug-view'),
url(r'docs/(?P<slug>\w+)/login', 'app.views.slug_login', name='slug-login'),
#..
)
Then in your template you can do this:
<form action="{% url slug-login slugname %}" method="POST">
Your views.py would look something like this.
def slug(request, slug):
#
#
return render_to_response('templatename.html', {'slugname':slug}, context_instance=RequestContext(request))
def slug_login(request, slug):
# do something with slug.
This way, when you access the slug view, you pass into the template a variable called slugname, which the template uses with django's url library to resolve a specifically named url in urls.py with one named parameter, slug, which it will assign the value of slugname.
I suggest you try it.
I might also reccoment you read up on the django url dispatcher. Your use of regex without named parameters is acceptable but really not best practice. I'd also suggest django shortcuts (render_to_response) as a quick way to pass variables into templates and the django template language itself.

Categories

Resources