Django restapi passing parameter to read() - python

In the test example http://django-rest-interface.googlecode.com/svn/trunk/django_restapi_tests/examples/custom_urls.py on line 19 to they parse the request.path to get the poll_id. This looks very fragile to me. If the url changes then this line breaks. I have attempted to pass in the poll_id but this did not work.
So my question is how do I use the poll_id (or any other value) gathered from the url?

Views are only called when the associated url is matched. By crafting the url regex properly, you can guarantee that any request passed to your view will have the poll_id at the correct position in the request path. This is what the example does:
url(r'^json/polls/(?P<poll_id>\d+)/choices/$', json_choice_resource, {'is_entry':False}),
The json_choice_resource view is an instance of django_restapi.model_resource.Collection and thus the read() method of Collection will only ever act on requests with paths of the expected format.

Related

URL pattern for query string parameters Django REST Framework

This is my current url path is as http://localhost:8000/api/projects/abcml/2021
and in the urls.py page I am passing as path("api/projects/<str:project_handle>/<int:year>", functionname...) and in the view, I accept this parameters with self.kwargs.get method.
I want to pass url as this format http://localhost:8000/api/projects/abcml/?year=2021
What changes do I need to make in url pattern?
I tried this path("api/projects/<str:project_handle>/?year=<int:year> but did not seem correct also in the view page, instead of self.kwargs.get I changed it to self.request.query_params.get for year parameter. That did not work either. Error it throwing is Page not found (404).
The query string [wiki] is not part of the path, and therefore can not be matched.
You thus specify as path:
path('api/projects/<str:project_handle>/', functionname)
In the view, you can access the data with self.request.GET['year'] and this will return a string or a KeyError in cas the year was not provided in the query string.

Why do I need to specify HTML file in render()

Why do I need to give html file name in render() - I have already set url in my project file in urls.py in django
urls.py
url('view-books',views.viewBooks)
views.py
def viewBooks(request):
books=models.Book.objects.all()
res=render(request,'BRMapp/view_book.html',{'books':books})
Why can I not give in render view-books?
i think you have typo
def viewBooks(request):
books=models.Book.objects.all()
context = {"books":book}
return render(request,'BRMapp/view_book.html',context)
your question why you need html file name in render because render is a function it takes 3 arguments 1st is request second is "path of the html file" 3rd is the context
further explaination
Do you have basic idea how django work first of first you are not giving url in render you are giving path to render which template should be render . django follow mvc pattern you read on it but to simplify it urls just have the routing task they are just there to filter routes not to do any thing in url you can give 3 arguments two are compulsary first the path by which it recognize that the time has come to act the second the function name which direct him where to go then its function responsibilty to process the data
Unfortunately, you didn't return anything in your view. So you need to add return to your function:
def viewBooks(request):
books=models.Book.objects.all()
return render(request,'BRMapp/view_book.html', {'books':books})
You might want to take a look at this tutorial.
https://yourwebsite/view-book is not the same as BRMapp/view_book.html, Django needs to know that one corresponds to the other.
The routing in Django works like this:
The user sends a request to Django with a url.
Django looks through your urls in urls.py for a path that matches what was requested.
When it finds a path, like view-books, that path has a view. The view is just a function (viewBooks()), and Django executes it.
The view function is expected to return the content that the user will see. You could, if you wanted, write the whole page by hand as a string in the return line of viewBooks(), but that's inconvenient, so instead you tell Django to make the page for you, starting from a template. To do so, you call render().
What render() does is take the template and replace all parts that need to be replaced for the user that will see it. But to know what the initial content will look like, it needs to read it from somewhere, and that's the HTML file BRMapp/view_book.html.
The HTML file doesn't need to have the same name as the view, you could have called it foobar.html and it would have worked the same. But regardless of its name, you need to tell Django that you want to use a file (render() tells Django that), and you need to tell Django where that file is. You'll have many different files in different places with different names, and it can happen that you have the same name for templates in different directories, so Django will not attempt to guess which one you want: you'll have to put its path inside render() so that Django knows where to start building the page.
If you gave the URL to render() instead of the path to the file, Django would get to point 5 and then back again to 1 to figure out what that URL means, and so on and so forth forever.

Can a empty string be passed in the url in django?

I am working on a django project which have a posts page. I have its url as follows:
path('posts/<str:sort>', views.posts, name='posts'),
and this is what its view looks like:
def posts(request,sort)
b=""
if b=="time":
posts=Post.objects.all().order_by(b)
else:
posts=Post.objects.all()
return render(request,posts.html,{'posts':posts})
Now what I want is that if there is nothing passed as sort in the url or the url is like : /posts/ I want to display all posts but if the parameter is 'time' then I want to order_by as in my view. But currently if nothing is passed in url for sort then I get the error that no path found the url.
str converter is defined as follows:
class StringConverter:
regex = '[^/]+'
# other methods
Which means it requires at least one character (note +, not *). You can create a new url mapping and manually pass empty string as sort parameter:
path('posts/', views.posts, kwargs={'sort': ''})
You can also register your own converter to allow empty string or just switch to plain old re_path. These options are preferred in case if you want to reduce code repetition and reuse this behavior somewhere else. They also allow you to keep the same url name (useful if you're planning to reverse urls)

Capture URL with query string as parameter in Flask route

Is there a way for Flask to accept a full URL as a URL parameter?
I am aware that <path:something> accepts paths with slashes. However I need to accept everything including a query string after ?, and path doesn't capture that.
http://example.com/someurl.com?andother?yetanother
I want to capture someurl.com?andother?yetanother. I don't know ahead of time what query args, if any, will be supplied. I'd like to avoid having to rebuild the query string from request.args.
the path pattern will let you capture more complicated route patterns like URLs:
#app.route('/catch/<path:foo>')
def catch(foo):
print(foo)
return foo
The data past the ? indicate it's a query parameter, so they won't be included in that patter. You can either access that part form request.query_string or build it back up from the request.args as mentioned in the comments.
Due to the way routing works, you will not be able to capture the query string as part of the path. Use <path:path> in the rule to capture arbitrary paths. Then access request.url to get the full URL that was accessed, including the query string. request.url always includes a ? even if there was no query string. It's valid, but you can strip that off if you don't want it.
#app.route("/<path:path>")
def index(path=None):
return request.url.rstrip("?")
For example, accessing http://127.0.0.1:5000/hello?world would return http://127.0.0.1:5000/hello?world.

Python Django: urls.py questions

Need a little help with my urls.py and other stuff.
How can I replicate this in Django?
1) When user requests a non-existent page it will redirect to one up the directory level. Ex: example.com/somegoodpage/somebadpage should be redirected to example.com/somegoodpage.
2) When user requests page example.com/foo/bar/?name=John it will make url to example.com/foo/bar/name=John
3) When user requests page example.com/foo/bar/John it will change url to example.com/foo/bar/name=John.
Any help is greatly appreciated. Thank You.
For 1), if you don't want to do a separate route for every single route on your website, you'll need middleware that implements process_exception and outputs an HttpResponseRedirect.
For 2 and 3, those are rules that are presumably limited to specific routes, so you can do them without middleware.
2 might be doable in urls.py with a RedirectView, but since the relevant bit is a query string argument, I would probably make that an actual view function that looks at the query string. Putting a ? character in a url regex seems strange because it will interfere with any other use of query strings on that endpoint, among other reasons.
For 3, that's a straightforward RedirectView and you can do it entirely in urls.py.
according to django doc for number 1:
django URL dispatcher runs through each URL pattern, in order, and stops at the first one that matches the requested URL, so add a pattern that matches "somebadpage"s and assign it to a view which redirects the user to "somegoodpage".
for number 2:
the doc says "The URLconf searches against the requested URL, as a normal Python string. This does not include GET or POST parameters, or the domain name."
so i don't think that you can get the "?name=John" in url dispather, so if you describe what you want to do maybe I can help better
and for 3:
to capture bits of the URL and pass them as positional arguments to a view you should use named regular-expression groups, for example :
url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', 'news.views.month_archive'),
and the request to /articles/2005/03/ would call the function news.views.month_archive(request, year='2005', month='03'), instead of news.views.month_archive(request, '2005', '03').
hope this helped :)

Categories