How to define multiple optional variables in the URL? - python

In django doc proposed instead GET method use urlpatterns, and made ​​convenient way to handle these variables. But if at least one of the variables is not necessary I'll have to write more lines in url.py. I like that I can avoid this?
Example:
If I want to take a sample of posts in a given year, in urlpatterns I should add something like this:
url(r'^articles/(?P<year>\d{4})/$', 'news.views.show_archive'),
url: .../articles/1994/
If I want to make the sample positions for a particular month a specific year, in urlpatterns I should add something like this:
url(r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/$', 'news.views.show_archive'),
url: .../articles/2003/03/
But if I want to see the records of all the years created particular month of year I have to add also this line:
url(r'^articles/(?P<month>\d{2})/$', 'news.views.show_archive'),
url: .../articles/03/
But I would like to do only one line that specifies the maximum set of variables, but that would process any of these URL.
To be honest I'm not sure that this is possible.

regexps can have optional parts, and view functions can have optional arguments. Also, you can still use querystrings (through request.GET) for what has no business being part of the URL (like query terms for a "search" view, ordering and filtering for a listing view, etc).
The point of using urlpatterns instead of querystrings is to build clean "semantic" urls, ie /blog/posts/<post_id>/ instead of /blog/posts/?post_id=<post_id>.

you could try like this
url(r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/$', 'news.views.show_archive'),
def show_archive(request,year=None,month=None):
if year and month:
.....................
elif year:
.....................
elif month:
....................

Related

django how to pass parameter from url to view

I'm trying to append a parameter no_rep at the end of my question url as a signal to show different views. I'm using Django 1.8 and following the url pattern from askbot.
This is the url.py:
url(
(r'^%s(?P<id>\d+)/' % QUESTION_PAGE_BASE_URL.strip('/') +
r'(%s)?' % r'/no-rep:(?P<no_rep>\w+)'),
views.readers.question,
name='question'
),
I'm trying to show different displays depending on the value of no_rep in my url.
This is the view:
def question(request, id, no_rep):
if no_rep == '1':
request.session['no_rep'] = True
else:
request.session['no_rep'] = False
I couldn't find information on what the +,%,? do, which is probably where the problem is. Could someone explain how the regex work with the base url? When I enter the url http://localhost:8000/question6/test-question/no_rep:1, request.session['no_rep'] should be set to true, but it's not. What am I missing?
Your url looks like this after all substitutions (%): r'^question(?P<id>\d+)/(/no-rep:(?P<no_rep>\w+))?', so:
1. Missing part for test-question
2. You have odd grouping around named group no_rep (which is legal, but not recommended)
So for url like http://localhost:8000/question6/test-question/no_rep:1 your url pattern should look like this:
r'^%s(?P<id>\d+)/test-question/(?:no_rep:(?P<no_rep>\d+))?' % QUESTION_PAGE_BASE_URL.strip('/') (you can change \d+ in the last group for \w+ if you want letters to match too).
About non-capturing groups (?:...) and meaning of + and ? you can read in the documentation of Python re module.

Django - regex optional function parameters in URL

I am starting off with Django now (already have quite a bit of Python knowledge, as well as with other languages). I am wondering whether it is possible to pass optional parameters through the url to a view (function that is called when a certain url is entered). What I have:
url(regex=r'^bydate/year=(?P<year>[0-9]+)_month=(?P<month>[0-9]+)_day=(?P<day>[0-9]+)/$', view=views.question_by_date, name='question_by_date')
So, in other words, if the end of the url looks like this, for example:
...bydate/year=2001_month=11_day=2/
then it calls the question_by_date function, whose signature looks as follows:
question_by_date(request, **kwargs)
So with the above url, question_by_date will be called as
question_by_date(request, year=2001, month=11, day=2)
But I also want the user to be able to type in the url specifying just the year, e.g.
...bydate/year=2005/
which will call
question_by_date(request, year=2005)
Or for that matter, any combination of year, month, day (like just the year and the month, or just the year and day even, etc.)
So, is this possible? I am not so experienced in regex, and I understand that you can have optional string matches (zero or more) in regex, which will match the above just fine in normal circumstances, but here we are also passing (optional) parameters to a function.
NOTE:
A very similar question to this has already been asked here. I realize that I could make a different URL for each combination, but that would entail making 8 different URLs. Also, that question was asked 6 years ago. Hopefully some enhancement has been made in the meantime?
I think what you need is GET parameters for this:
Define you url without any parameters:
url(r'^bydate/$', views.question_by_date, name='question-by-date')
In your views, extract GET parameters:
from datetime import date
def question_by_date(request):
year = request.GET.get('year', 2005)
month = request.GET.get('month', 1)
day = request.GET.get('day', 1)
# use the parameters however you want afterwards
Call your url like:
http://localhost:8000/bydate/?year=2016&month=1&day=1
Check django doc for more details about http GET.

Django urlpattern with infinite number of parameters

Is it possible to define Django urlpattern, which would get any number of same type parameters and pass them to a view?
Lets say I want to create a page which gets a list of numbers from url and sums them. So these would be valid urls:
/sum/10/99/12/
/sum/1/2/3/4/5/6/7/8/9/
/sum/3/
I guess that view could look like this:
def sum_view(request, *args):
return render(request, 'sum.html', {'result': sum(args)})
Question is how should urlpattern look like? Maybe something like this:
url(r'^sum/((\d+)/)+$', views.sum_view)
But this way view gets only last number repeated twice: args == ('1/', '1'). What is the correct regular expression to get all the numbers passed ot the view?
You could capture a single argument, e.g. '1/2/3/4/5/6/7/8/9/'
url(r'^sum/(?P<numbers>[\d/]+)$', views.sum_view)
The split the list in the view.
def sum_view(request, numbers):
processed_numbers = [int(x) for x in number.split('/') if x]
...
Django's urlpatterns are based on python's regexps so there is no way of catching all data from repeating group. Check this question for explanation.
You will have to split and process them by yourself (like #Alasdair suggests).

Django: variable parameters in URLconf

I've been looking for this question and couldn't find any, sorry if it's duplicated.
I'm building some kind of ecommerce site, similar to ebay. The problem i have arise when i'm trying to browse through "categories" and "filters". For example. You can browse the "Monitor" category. That will show you lots of monitors, and some filters (exactly the same as ebay) to apply them. So, you go to "monitors", then you have filters like:
Type: LCD - LED - CRT
Brand: ViewSonic - LG - Samsung
Max Resolution: 800x600 - 1024x768
And those filters will be appended to the URL, following with the example, when you browse monitors the URL could be something like:
store.com/monitors
If you apply the "Type" filter:
store.com/monitors/LCD
"Brand":
store.com/monitors/LCD/LG
"Max Resolution":
store.com/monitors/LCD/LG/1024x768
So, summarizing, the URL structure would be something like:
/category/filter1/filter2/filter3
I can't figure out how to do it really. The problem is that filters can be variable. I think in the view will need to use **kwargs but i'm not really sure.
Do you have any idea how to capture that kind of parameters?
Thanks a lot!
Ben, I hope this will help you
urls.py
from catalog.views import catalog_products_view
urlpatterns = patterns(
'',
url(r'^(?P<category>[\w-]+)/$', catalog_products_view, name="catalog_products_view"),
url(r'^(?P<category>[\w-]+)/(?P<filter1>[\w-]+)/$', catalog_products_view, name="catalog_products_view"),
url(r'^(?P<category>[\w-]+)/(?P<filter1>[\w-]+)/(?P<filter2>[\w-]+)/$', catalog_products_view, name="catalog_products_view"),
url(r'^(?P<category>[\w-]+)/(?P<filter1>[\w-]+)/(?P<filter2>[\w-]+)/(?P<filter3>[\w-]+)/$', catalog_products_view, name="catalog_products_view"),
)
view.py
def catalog_products_view(request, category, filter1=None, filter2=None, filter3=None):
# some code here
or
def catalog_products_view(request, category, **kwargs):
filter1 = kwargs['filter1']
filter2 = kwargs['filter2']
....
filterN = kwargs['filterN']
# some code here
You could add this to your urls:
url(r'^(?P<category>\w)/(?P<filters>.*)/$', 'myview'),
And then myview would get the parameters of category and filters. You could split filters on "/" and search for each part within the Filters table.
Does that make sense?
how do you intend to decide what aspect is being filtered by? Do you have a list of accepted keywords for each category? ie how does the server know that
/LCD/LG/
means type=LCD, brand=LG
but
/LG/LCD
doesn't mean type=LG, brand=LCD etc
Is there any reason you don't want to use GET params, e.g.
.../search/?make=LD&size=42

How do I display most recent week items by default with WeekArchiveView?

I'm astonished by how little documentation on class-based generic views there is.
Anything slightly more complex than a trivial sample has to get done through guesswork, trial and error.
I want to use WeekArchiveView to display a week's item list.
There's my urls.py entry:
url(r'^items/(?P<year>\d{4})/week/(?P<week>\d{1,2})/$', ItemWeekArchiveView.as_view())
When no year or week is specified, I get an error page.
I want them to equal today's year and week by default.
What is the right place for tweak here? Should I introduce another mixing and override a method?
Urls like /items/ or /items/2011/ wouldn't match your regexp because \d{4} means exactly 4 digits.
You probably should specify two another url entries for both cases:
url(r'^items/$', AchievementListView.as_view(
year=str(date.today().year), week=str(date.today().isocalendar()[1])
)),
url(r'^items/(?P<year>\d{4})/week/(?P<week>\d{1,2})/$', ItemWeekArchiveView.as_view()),
(Using isocalendar to get the week number).

Categories