Creating a big url - django

There are references:
sort1, sort2
filter1, filter2
We click on a sort1 and have a new url like: www.example.com?sort=1
Then we click on filter1 and we must have: www.example.com?sort=1&filter=1
Then we click on filter2 and we must have: www.example.com?sort=1&filter=2
and etc...
how can i do this, add more parametrs? my parameters change each other and always only one.

Query parameters like your sort and filter will be passed to your / route through GET variable. So your URLconf looks like:
urls.py
...
url(r'^/$',
sorter
),
Note that you don't put your GET parameters in your URLconf. Instead, they are parsed in key-value fashion and put in an HTTPRequst object, which gets passed to your view. Your view looks like:
views.py
def sorter(request):
...
and in this view, you can access your GET parameters through request.GET. For example, you might use request.GET['sort'] to get the value of the sort parameter. Because parameters are key/value pairs, you can have essentially as many as you want in any order, and it's up to the logic of the view to put them into use. You might want to start at Part 4 of the tutorial for an example of request processing, noting that URL query parameters are passed in request.GET instead of request.POST.

try some of the examples in the docs, replacing POST with GET in templates and views and see what happens

Related

How to get current url or input parameters in web.py template

I have a web page designed with web.py. I use web.template.render() and an HTML template file to draw a table in this web page.
I pass a list of items to this template, and would like to show the data in different pages using GET method and offset and count parameters (i.e. http://mywebsite/records?offset=10&count=15).
I am looking for a way to get the input values of offset and count and also the current url in the HTML template file, so I would be able to put links to next page and previous page.
Templates get data either passed into them (e.g., render.home(a, b, c)) or as a global (explicitly passed in as a dict via globals parameter when you define your renderer).
Your example is easier to do by getting the information in python, and passing it into the template. This allows you to error check the values, provide defaults, etc.
So, have your GET() extract the proper information and pass it to the template:
class index(object):
def GET(self):
my_render.index(url=web.ctx.fullpath,
offset=web.input().offset,
count=web.input().count())
==== index.html ====
$def with(url, offset, count)
<table>
<tr><td>URL is: $url</td>
<td>OFFSET is: $offset</td>
<td>COUNT is: $count</td></tr>
</table>

Django pass known exact string as a url parameter

I have two urls in dispatcher pointing the same view
path('posts/top/', posts, name='top'),
path('posts/new/', posts, name='new'),
I want view start as follows:
def posts(request, ordering):
...
I guess, to pass top and new as a parameter it should be something like:
path('posts/<ordering:top>/', posts, name='top'),
path('posts/<ordering:new>/', posts, name='new'),
But it gives me:
django.core.exceptions.ImproperlyConfigured: URL route 'posts/<ordering:top>/' uses invalid converter 'ordering'.
So, as a work around I use this, but it looks a little bit dirty:
path('posts/top/', posts, name='top', kwargs={'order': 'top'}),
path('posts/new/', posts, name='new', kwargs={'order': 'top'}),
What is the right way to do it?
You've misunderstood the way path converters work. The first element is the type, which here is str, and the second is the parameter name to use when calling the view. At this point you don't constrain the permissible values themselves. So your path would be:
path('posts/<str:ordering>/', posts, name='posts')
and when you come to reverse you would pass in the relevant parameter:
{% url 'posts' ordering='top' %}
If you really want to ensure that people can only pass those two values, you can either check it programmatically in the view, or you can use re_path to use regex in your path:
re_path(r'^posts/(?P<ordering>top|new)/$', posts, name='posts')

How to organize URLs in django for views handling GET data and parsing URL?

I have a view that displays some movie data. I thought that it might be a good idea to have a view handle a an URL like movie-id/1234 to search for movie id 1234. Furthermore I would like to be able to enter the ID into a form and send that to a server and search for it. To do that I created a second entry in the urls.py file shown below.
urlpatterns = patterns('',
url(r'movie-id/(?P<movie_id>.+?)/$', 'movieMan.views.detailMovie'),
url(r'movie-id/$', 'movieMan.views.detailMovie', name='movieMan.detailMovie.post'),
)
So if I want to pass data to my view either via a URL or a GET or POST request I have to enter two urls or is there a more elegant way? In the view's code I am then checking if there is any GET data in the incoming request.
To make the second url usable with the template engine, where I wanted to specify the view's url using the {% url movieMan.detailMovie.post %} syntax I had to introduce a name attribute on this url to distinguish between these two.
I am not sure if I am thinking too complicated here. I am now asking myself what is the first url entry good for? Is there a way to get the URL of a movie directly? When do these kinds of URLs come into play and how would they be generated in the template ?
Furthermore I would like to be able to enter the ID into a form and
send that to a server and search for it.
Is this actually a search? Because if you know the ID, and the ID is a part of the URL, you could just have a textbox where the user can write in the ID, and you do a redirect with javascript to the 'correct' URL. If the ID doesn't exist, the view should return a Http404.
If you mean an actual search, i.e. the user submitting a query string, you'll need some kind of list/result view, in which case you'll be generating all the links to the specific results, which you will be sure are correct.
I don't think there is a more elegant way.
I did almost the same thing:
url( r'^movies/search/((?P<query_string>[^/]+)/)?$', 'mediadb.views.search_movies' ),
The url pattern matches urls with or without a search parameter.
In the view-function, you will have to check whether the parameter was defined in the url or in the query string.

Using both sort & filter on a QuerySet

I have a list of userprofiles that I want to be able to sort and filter.
I have been able to do this manually, by manually typing in the URLs, but I haven't been able to code the template page to allow the persistence of a previously-applied filter or sort. Here is the url and template code that I currently have --
# in urls
url(r'^talent/filter\:(?P<position>[A-Za-z]+)/sort\:(?P<sort>[A-Za-z]+)$', 'talent_filter', name='talent_filter_sort'),
url(r'^talent/filter\:(?P<position>[A-Za-z]+)/$', 'talent_filter', name='talent_filter'),
url(r'^talent/sort\:(?P<sort>[A-Za-z]+)/$', 'talent_sort', name='talent_sort'),
url(r'^talent/$', 'talent', name='talent'),
# in template
<ul>
<li>SORT BY:</li>
<li>Alphabetical</li>
...
</ul>
<ul>
<li><a href = '{% url talent_filter position=position%}'>{{ position }}</a></li>
...
</ul>
Currently, if I am on the (unsorted, unfiltered) talent page, and I select a filter on the results, it will return
talent/filter:filter. Then, if I choose to sort the results, it (obviously) goes to talent/sort:sort, removing the previous filter.
What I want to accomplish is that if I am currently on talent/filter:filter and click a sort method, it will go to talent/filter:filter/sort:sort, and if I have already sorted the results (talent/sort:sort) and click on filter, it will also take me to talent/filter:filter/sort:sort. How would I accomplish this. Thank you.
I think one way you might be able to accomplish this is store a flag in your session that indicates what the sorting or filtering should be. For example, something like below could be used to save the state of the your sort choice.
request.session['TALANT_SORT'] = "alphabetical"
request.session['TALENT_FILTER'] = "top_ten"
And then your views can check for the existence the session keys and apply a filter accordingly.
qs = models.MyModel.objects.all()
sort = request.session.get('TALENT_SORT', None)
if sort in ["alphabetical", "created_date"]:
qs = qs.order_by(sort)
myfilter = request.session.get("TALENT_FILTER", None)
if myfilter in ["top_ten","bottom_ten"]:
qs = qs.filter( .... )
....
The sorting and filtering could then persist across requests.
If you want to remove the sort or filter, then perhaps you can delete the session keys in the view depending on some user action:
try:
del request.session['TALENT_SORT']
del request.session['TALENT_FILTER']
except KeyError:
pass
Also, depending on your requirements, you might consider combining the 2 urls into 1 and just use GET parameters to activate the sort.
request.GET.get('sort',None)
....
request.GET.get('filter', None)
....
These examples could probably use some more rigor, but that's the idea. Hope this helps.
Joe
Despite being slightly against what django is all about, the best approach to user specified sorts/filters if to use GET variables. So your URLs would appear like:
/talent/?filter=foo&sort=bar
Within your view set context variables for your current filter and sort then use those to build your urls in your templates.
Something like:
Alphabetical
If you really feel it's necessary to use url captured parameters you'll need to set up your urls to handle all the conditions (sort set, filter set, neither set, and both set). And then in your templates you'll need a bunch of if statements to select the correct url and parameters.
As I said this type of situation is much better handled with GET parameters.

Django: Should I use Query Strings or clean url's to map display parameters? And how?

I have the following urlconf:
urlpatterns = patterns('page.manager.views',
url(r'^$', 'pages', name='page_manager-pages'),
url(r'^add/$', 'add_page', name='page_manager-add_page'),
url(r'^(?P<page_id>\d+)/', include(object_patterns)),
)
The 'pages' view must return an object list of all pages. The user will be offered several display/search options through a side menu:
- created: any/ past 6hours/12hours/24hours/week
- Status: any/ status_1/status_2/status_3
- Duration: any / duration_1/duration_2/duration_3
etc.
These options are used to select which values should be presented to the user and can be used in combination, eg: created=any, status=status_1, duration=duration_1
My question is, how best to achieve this in Django?
What I have so far:
I can subclass a generic view for list objects, creating a view which takes the arguments(created, status, duration, etc) and provides the proper queryset(with the chosen[or default] ordering options passed along with the other arguments).
To pass these arguments, query strings seem to be right for this, since we are selecting from a resource(the list of all pages). Yes/no?
I'm also aware we get this information from request.GET.get('argument_name').
But how to create the links for the search options? eg: any, any/ status_1/status_2/status_3. We need to know which are already active, so...template tag? An easier way perhaps?
Is this the proper solution to handle this type of thing in Django, or is there a better way?
Since you have discrete, optional and unordered pieces of knowledge contributing to your query, I think that GET is the best way. Also, note that request.GET is a dict (ergo, you can do request.GET['status']).
As for the search options, I'd say a template tag and a context variable might either be appropriate depending on the details of your view. My most likely approach is to populate a context dict with True / False flags for which need to be displayed and then have {% if %} blocks to sort it out in the template.