Python: Having trouble understanding regex - python

I was going through the django tutorial and though now almost everything there seems pretty clear, I am having trouble understanding the regex while matching the urls :
r'^(?P<poll_id>\d+)/$
what does (?P<poll_id>\d+) do ?
I am understanding that after stripping off the "34/" from "polls/34/", The polls.url is being called and there the keyword urlpatterns is being looked for , but how does poll_id get this value 34 ?
I know only a bit of regex, so thats why it might be hard for me to read.
Also, here is the reference that I am using for this question :Tutorial Part3

It's a regex that takes the poll_id (a number) as a variable.
The corresponding view is:
def detail(request, poll_id):
return HttpResponse("You're looking at poll %s." % poll_id)
Now when you go to example.com/polls/34/, it knows you are looking for poll number 34, and it brings that in to the view as the poll_id.
So in your view, poll_id = 34. This allows you to display or manipulate this specific poll.
Essentially the point of the regex in this case is to allow you to view a large number of specific polls without having to create an explicit url for each one.
To clarify, this regex is saying take any number \d+, save it as poll_id, and proceed to this view with that poll_id.

To support for Dan Hoerst 's answer: yup, django uses regular expression to extract the poll_id for the view. The underneath of this is:
import re
r = re.compile(r'^poll/(?P<poll_id>\d+)/$')
r.match('poll/132/').groups() # ('132',)

Related

Django domain + regex parameter not working on production machine

I currently have a django view with a fairly simple search function (takes user input, returns a list of objects). For usability, I'd like the option of passing search paramters via url like so:
www.example.com/search/mysearchstring
Where mysearchstring is the input to the search function. I'm using regex to validate any alphanumeric or underscore characters.
The problem I'm having is that while this works perfectly in my development environment, it breaks on the live machine.
Currently, I am using this exact same method (with different regex patterns) in other django views without any issues. This leads me to believe that either.
1) My regex is truly bad (more likely)
2) There is a difference in regex validators between environments (less likely)
The machine running this is using django 1.6 and python 2.7, which are slightly behind my development machine, but not significantly.
urls.py
SEARCH_REGEX = '(?P<pdom>\w*)?'
urlpatterns = patterns('',
....
url(r'^polls/search/' + SEARCH_REGEX, 'polls.views.search'),
...)
Which are passed to the view like this
views. py
def search(request, pdom):
...
When loading up the page, I get the following error:
ImproperlyConfigured: "^polls/search/(?P<pdom>\w*)?" is not a valid regular expression: nothing to repeat
I've been scratching my head over this one for a while. I've attempted to use a few different methods of encapsulation around the expression with no change in results. Would appreciate any insight!
I would change it to this:
SEARCH_REGEX = r'(?P<pdom>.+)$'
It's usually a good idea to use raw strings r'' for regular expressions in python.
The group will match the entire content of the search part of your url. I would handle query string validation in the view, instead of in the url regex. If someone tries to search polls/search/two+words, you should not return a 404, but instead a 400 status and a error message explaining that the search string was malformed.
Finally, you might want to follow the common convention for search urls. Which is to use a query parameter called q. So your url-pattern would be ^polls/search/$, and then you just handle the q in the view using something like this:
def search_page_view(request):
query_string = request.GET.get('q', '')

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 URL regex "is not a valid regular expression" error

I'm having a bit of trouble configuring the following url. I want it to be able to match a pages which start off with a category and then finish with a slug, examples:
/category1/post1/
/category2/post2/
/category3/post3/
/category1/post4/
/category2/post5/
I've tried many different methods with no success... I always get an "is not a valid regular expression" error.
This is how I thought it should work:
url(r'^(?P<category1|category2|category3>[\w\-]+)/(?P<slug>[\w\-]+)/$', blog_post, name = 'blog_post'),
I am fairly new to regex and trying to learn so any help on this one with an explanation would be much appreciated :)
Your pattern is incorrect; you are putting the alternative values in the wrong place. You put them in the name of the group:
(?P<category1|category2|category3>...)
Put them in the part the name is supposed to match instead:
(?P<category>category1|category2|category3)
Making the full registration:
url(r'^(?P<category>category1|category2|category3)/(?P<slug>[\w\-]+)/$', blog_post, name='blog_post'),
I'm assuming your blog_post callable looks something like:
def blog_post(category, slug):

In a Django URL, what is the regular expression so that "foo.com/Bar" is the same as "foo.com/bar"

My problem is people keep linking to example.com/FooBar but the actual link is example.com/foobar.
My current regex is...
SLUG = '(?P<slug>[\w\d-]+)'
I hope that makes sense. I was surprised I couldn't find this question already asked. Maybe my google fu is weak today.
The regex matches both. The difficulty is that you've likely got a query like:
obj = MyModel.objects.get(slug=slug)
Which isn't matching.
To fix this, change the query to:
obj = MyModel.objects.get(slug=slug.lower())
Also your query could be like
obj = MyModel.objects.get(slug__icontains=slug)
The icontains field lookup will do a case insensitive match

Python: Need to replace a series of different substrings in HTML template with additional HTML or database results

Situation:
I am writing a basic templating system in Python/mod_python that reads in a main HTML template and replaces instances of ":value:" throughout the document with additional HTML or db results and then returns it as a view to the user.
I am not trying to replace all instances of 1 substring. Values can vary. There is a finite list of what's acceptable. It is not unlimited. The syntax for the values is [colon]value[colon]. Examples might be ":gallery: , :related: , :comments:". The replacement may be additional static HTML or a call to a function. The functions may vary as well.
Question:
What's the most efficient way to read in the main HTML file and replace the unknown combination of values with their appropriate replacement?
Thanks in advance for any thoughts/solutions,
c
There are dozens of templating options that already exist. Consider genshi, mako, jinja2, django templates, or more.
You'll find that you're reinventing the wheel with little/no benefit.
If you can't use an existing templating system for whatever reason, your problem seems best tackled with regular expressions:
import re
valre = re.compile(r':\w+:')
def dosub(correspvals, correspfuns, lastditch):
def f(value):
v = value.group()[1:-1]
if v in correspvals:
return correspvals[v]
if v in correspfuns:
return correspfuns[v]() # or whatever args you need
# what if a value has neither a corresponding value to
# substitute, NOR a function to call? Whatever...:
return lastditch(v)
return f
replacer = dosub(adict, another, somefun)
thehtml = valre.sub(replacer, thehtml)
Basically you'll need two dictionaries (one mapping values to corresponding values, another mapping values to corresponding functions to be called) and a function to be called as a last-ditch attempt for values that can't be found in either dictionary; the code above shows you how to put these things together (I'm using a closure, a class would of course do just as well) and how to apply them for the required replacement task.
This is probably a job for a templating engine and for Python there are a number of choices. In this stackoveflow question people have listed their favourites and some helpfully explain why: What is your single favorite Python templating engine?

Categories