First of all, this is not an error, but the function is well documented in the documents :
[]
Used to indicate a character set. In the set:
Character ranges can be specified by specifying two characters and dividing them by "-", for example, [az] will match any lowercase ASCII letter, [0-5] [0-9] will correspond to all two-digit characters, numbers from 00 to 59, and [0-9A-Fa-f] will match any hexadecimal digit. If - is escaped (for example, [az]), or if it is placed as the first or last character (for example, [a-]), it will match the literal '-' .
So using - between two literals will evaluate this regular expression as a range of characters:
re.compile("[a-0]+") >> error: bad character range re.findall("[.-_]+", "asdasd-asdasdad._?asdasd-") >> ['._?']
As you can see, python will always be interperet - as a range indicator when used between characters in character sets.
As it is (also) indicated in documents, avoiding the declaration of a range, it is done by escaping - using \- or by placing it as the first or last literal in the character set []
If you want to capture this range of characters, including - , try:
re.findall("[.-_\-]+", "asdasd-asdasdad._?asdasd-") >> ['-', '._?', '-']
Note: \w is [a-zA-Z0-9_] when the LOCALE and UNICODE flags are not set. Therefore you do not need to declare _ again
And in your situation:
url(r'^user/(?P<username>[-.\w]+)/foo', 'myapp.views.foo') url(r'^user/(?P<username>[.\w-]+)/foo', 'myapp.views.foo') url(r'^user/(?P<username>[.\-\w]+)/foo', 'myapp.views.foo')
Besides using - if you are using the default Django Username style, then @ navneet35371 is right about a valid character set. You can change your regex character set to include @ and + and use
url(r'^user/(?P<username>[\ w.@ +-]+)/foo', 'myapp.views.foo')