In a search form, users can choose some of the criteria (country, province and city) and post it the result to this view:
def profile_search(request):
if request.method == 'POST':
form = AdvancedSearchForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
country=cd['country']
province=cd['province']
city = cd['city']
params=( country, province, city ,)
url = reverse('userprofile.views.profile_search_result', args= params)
return HttpResponseRedirect(url)
args = {}
args.update(csrf(request))
return HttpResponseRedirect("/result/ایران")
Which is supposed to be found by one of these url patterns:
url(r'^result/(?P<country>\w+)/(?P<province>\w+)/(?P<city>\w+)', 'userprofile.views.profile_search_result'),
url(r'^result/(?P<country>\w+)/$','userprofile.views.profile_search_result'),
However, no matter what criteria are chosen in the search form, I get errors like:
Reverse for 'userprofile.views.profile_search_result' with arguments '(u'\u0627\u06cc\u0631\u0627\u0646', u'\u0627\u0644\u0628\u0631\u0632', u'')' and keyword arguments '{}' not found. 2 pattern(s) tried: ['result/(?P<country>\\w+)/$', 'result/(?P<country>\\w+)/(?P<province>\\w+)/(?P<city>\\w+)']
How to fix this?
You have two problems.
Firstly, \w does not match the Arabic characters you are using in your params - it's equivalent to [A-Za-z0-9] only. You will need to explicitly use the Unicode codepoints for the characters you want to match, or alternatively a much more general .:
r'^result/(?P<country>.+)/(?P<province>.+)/(?P<city>.+)'
Secondly, in your pattern the city parameter is required, but you are passing an empty string. You should probably define a third pattern that omits that parameter:
r'^result/(?P<country>.+)/(?P<province>.+)'
But note that I don't recommend doing any of that. Rather than submitting your form as a POST and redirecting to a second view with URL parameters to actually do the search, you should simply use a GET action in your form and submit it straight to the search_result view, where you get the search query from request.GET.
try this line in urls.py
url(r'^result/(?P<country>.*)/$','userprofile.views.profile_search_result'),
this is sample of using unicode chars in my application:
urls.py
urlpatterns += patterns('pin.views',
url(r'^(?P<user_namefl>.*)/followers/$', 'absuser_followers', name='pin-absuser-followers'),
url(r'^(?P<user_namefg>.*)/following/$', 'absuser_friends', name='pin-absuser-following'),
url(r'^(?P<user_namel>.*)/likes/$', 'absuser_like', name='pin-absuser-like'),
url(r'^(?P<user_name>.*)/$', 'absuser', name='pin-absuser'),
)
links from html pages
<a href="{% url "pin-absuser" username %}">
with reverse in views or models
reverse("pin-absuser", args=["وحید"])
To use reverse(), you need to give the url a name, and use it in the reverse function - see documentation.
Example in urls.py:
url(r'^result/(?P<country>\w+)/(?P<province>\w+)/(?P<city>\w+)', 'userprofile.views.profile_search_result', name='search_results'),
Example call:
url = reverse('search_results', args= params)
Related
Get and post work pretty well for me .
but put and delete i use "U_repo_name" to look in table
i got the error message :
Page not found (404)
Request Method: PUT
Request URL: http://localhost:8000/gitapi/repo/authoo/
Using the URLconf defined in gitit.urls, Django tried these URL patterns, in this order:
admin/
gitapi/ [name='gitapi']
gitapi/ repo/
gitapi/ repo/str:U_repo_name
this is my model :
class UserRepos(models.Model):
U_repo_name =models.CharField( max_length=50)
this is my url :
urlpatterns = [
path('repo/',view=userreposapi),
path('repo/<str:U_repo_name>',view=userreposapi),
]
project urls :
urlpatterns = [
path('admin/', admin.site.urls),
path('gitapi/',include('gitapi.urls')),
]
this is my serializer :
class UserReposSerializer(serializers.ModelSerializer):
class Meta:
model = UserRepos
fields ='__all__'
and this is my views :
#csrf_exempt
def userreposapi(request,id=0):
if request.method=='GET':
userrepos = UserRepos.objects.all()
userreposserializer = UserReposSerializer(userrepos , many=True)
return JsonResponse(userreposserializer.data , safe=False)
elif request.method=='POST':
userrepos_data=JSONParser().parse(request)
userreposerializer = UserReposSerializer(data=userrepos_data)
if userreposerializer.is_valid():
userreposerializer.save()
return JsonResponse("added successfully!!",safe=False)
return JsonResponse("failed to add",safe=False)
elif request.method=='Put':
userrepos_data=JSONParser().parse(request)
userrepos = UserRepos.objects.get(U_repo_name=userrepos_data['U_repo_name'])
userreposserializer=UserReposSerializer(userrepos,data=userrepos_data)
if userreposserializer.is_valid():
userreposserializer.save()
return JsonResponse("updated successfully", safe=False)
return JsonResponse("failed to update",safe=False)
elif request.method=='DELETE':
userrepos = UserRepos.objects.all()
userrepos.delete()
return JsonResponse("deleted",safe=False)
Hi! I see a few issues with your code that might be causing this problem.
request.method is always full capitalized, so you should use the string 'PUT' instead of 'Put' on this line:
elif request.method=='Put':
You are adding a trailing slash to your route when trying to access it (/gitapi/repo/authoo/), but the pattern set in urlpatterns doesn't have this trailing slash:
path('repo/<str:U_repo_name>',view=userreposapi),
You can use re_path() instead of path() to set a regex URL pattern that works whether you add a trailing slash or not:
re_path(r'repo/(?P<U_repo_name>\w+)/?', view=userreposapi),
(?P<U_repo_name>\w+) creates a named group called U_repo_name that matches any word character ([a-zA-Z0-9_]) from one to more times. /? matches a single optional /.
Your route 'repo/<str:U_repo_name>' captures a string in the variable U_repo_name. This variable is provided to the view userreposapi() as a keyword argument, but the view currently only accepts the id kwarg. You should either add the U_repo_name kwarg as an optional argument or make the view accept other keyword arguments with **kwargs:
# Both are valid:
def userreposapi(request, id=0, U_repo_name=None):
...
def userreposapi(request, id=0, **kwargs):
...
Fixing these 3 issues should make the route work.
I think the trailing slash in the url is the problem. I should be not there.
http://localhost:8000/gitapi/repo/authoo # here I removed the trailing slash.
It seems like the original URL querying function has been removed from Django 3.1. Does anyone know how to do it with a new package?
The url.py:
urlpatterns = [
re_path(r'^portfolio/(?P<title>[\w-]+)/$' , BlogApp_View.displayPortfolio, name='displayPortfolio'),
path('portfolio/', BlogApp_View.selectPortfolio, name='selectPortfolio'),]
The view.py
def displayPortfolio(request):
title = request.GET.get('title')
portfolio = Article.objects.filter(articleType__name__contains = "Portfolio", title=title)
print(title)
DICT = {}
return render(request, 'Article/', DICT)
The problem is now if I visit http://127.0.0.1:8000/Blog/portfolio/?title=A_UAV_Positioning_Approach_Using_LoRa/, it will skip the re_path shows in url.py.
Instead, it goes to the path one.
I have tried str:title method but that is actually not what I want. I prefer using the question mark pattern to finish the query.
The part after the questionmark is the querystring [wiki] and is not part of the path. This thus means that regardless what patterns you write, you can not distinguish on this, since the path patterns, regardless whether it is a path or re_path, are never matched against a URL with a query string.
You thus should write a single view, and inspect the request.GET query dict (which is a dictionary-like representation of the query string and see if it contains a value for title.
Your urlpatterns thus look like:
urlpatterns = [
path('portfolio/', BlogApp_View.selectPortfolio, name='selectPortfolio'),
]
and in the view, you can see if it contains a title:
def selectPortfolio(request):
if 'title' in request.GET:
# contains a ?title=…
title = request.GET.get('title')
portfolio = Article.objects.filter(
articleType__name__contains='Portfolio',
title=title
)
data = {'portfolio': portfolio}
return render(request, 'some_template.html', data)
else:
# contains no ?title=…
# …
return …
The URL pattern having issues is:
url(r'^$', business_list, name='business_list_home'),
url(r'^(?P<param>\w+)$', business_list, name='business_list_results'),
My view is:
#render_to('app/business_list.html')
def business_list(request, param=None):
queryset = Business.objects.all()
search_form = SearchForm
print request.GET
if param in request.GET:
param = request.GET.get('param')
if queryset.filter(city__iexact=param).exists():
queryset = queryset.filter(city__iexact=param)
elif queryset.filter(category__iexact=param).exists():
queryset = queryset.filter(category__iexact=param)
print queryset
else:
queryset = None
print queryset
return {'business_list': queryset, 'search_form': search_form}
Essentially, I don't understand why when I go to /Miami I don't have access to it via request.GET['param'] in the view? print request.GET prints <QueryDict: {}>
The reason I want to do this is to have a nice URL scheme for displaying results of businesses for the city or category (and that's why I check if it's a city or category in the view too) in the url. Let me know if there's a better way to accomplish this like
url(r'^$', business_list),
url(r'^(?P<city>\w+)$', business_list),
url(r'^(?P<category>\w+)$', business_list),
url(r'^(?P<category>\w+)/(?P<city>\w+)$', business_list),
Thanks for any help!
business_list is a function that takes a request and a parameter called "param" (should probably give it a better name as to make it a little less generic). In Django, the URL routes can define what values get passed to the parameters of the view functions.
In the situation above, when a user goes to /Miami, Django will try to match the string "Miami" with any of the regular expressions defined in the URL routes. In this case, the matching expression is ^(?P<param>\w+)$. When this match is made, the string Miami is captured into param.
Django will then call business_list(request, param="Miami"). Note that there were no query parameters passed in the URL (e.g., /Miami?color=blue).
The issue in the code you've written above is that you're checking to see not if param exists, but rather that param was passed in the query parameters. Try going to the URL /Miami?param=test and it'll probably work the way that you expected.
The real fix here is to not reference request.GET, because using GET parameters is exactly what you're trying to avoid. So, instead of
if param in request.GET:
param = request.GET.get('param')
if queryset.filter(city__iexact=param).exists():
queryset = queryset.filter(city__iexact=param)
elif queryset.filter(category__iexact=param).exists():
queryset = queryset.filter(category__iexact=param)
print queryset
Just do:
if param:
if queryset.filter(city__iexact=param).exists():
queryset = queryset.filter(city__iexact=param)
elif queryset.filter(category__iexact=param).exists():
queryset = queryset.filter(category__iexact=param)
I use a form in template,and I want to redirect a friendly url when user fill the form
I search many issue in stackoverflow,I think my problem like this issue: Django form redirect,
but I can't understand the template tag,so I can't solve my problem.
I write the form:
<form method="GET" action="/stock/search">
search:<input class="search" name="search" type="text" value="" id="serach" >
<input type="submit" value="Go"/>
</form>
and write the urls:
url(r'^(?P<number>\w+)/$', 'stock.views.stocknumber'),
url(r'^search/$', 'stock.views.search'),
and the views:
def stocknumber(request, number):
"""
stock info
"""
stock = Stock.objects.filter(number="%s"%number)
stock_number = Stock.objects.filter(number="%s"%number)
stock_reportinfo = Reportinfo.objects.filter(number="%s"%number)
stock_blockinfo = Blockinfo.objects.filter(number="%s"%number)
stock_stockinfo = Stockinfo.objects.filter(number="%s"%number)
data = Stockhq.objects.filter(number="%s"%number).values('timeStamps','openData','highData','lowData', 'closeData', 'volData').reverse()
datalist=[ ]
for item in data:
d =[item['timeStamps'].toordinal(),item['openData'],item['highData'],item['lowData'],item['closeData'],item['volData']]
datalist.append(d)
hisdata = datalist
return render_to_response(
'stock/stock.html',
{"stock_number": stock_number,
"stock_reportinfo": stock_reportinfo,
"stock_blockinfo": stock_blockinfo,
"stock_stockinfo": stock_stockinfo,
"hisdata":simplejson.dumps(hisdata) ,
},
context_instance=RequestContext(request))
def search(request):
return HttpResponseRedirect('/stock/%s/'%request.GET['search'])
and now I hope the user input the stock number and redriect to the friendly url like:http://..../stock/YHOO
and this url is get the stock info to render template,is this idea is right?
if it is ,what is the correct code ?
I don't think that question is really similar to your question, if I'm understanding correctly. Because that one already predetermines the action of the form, the redirected URL doesn't seem to depend on the user input. So I'm not entirely sure what your question is.
Are you implementing a simple search that, when a user inputs the stock's number (I'm assuming you consider "YHOO" a number? Is the "number" input something like "YHOO" or is it actually a number?), the stock with the number (so "YHOO" stock) is displayed with all of its information on a new page with the URL "http://.../stock/YHOO"?
In any case, here are some observations.
stock = Stock.objects.filter(number="%s"%number)
stock_number = Stock.objects.filter(number="%s"%number)
Is there a reason why you have both when you don't use the first one? In addition, are numbers unique? If so, you can just do Stock.objects.get(number=number), because:
You would use "get" instead of "filter" because you'd expect a
single record to match that.
Number is already a string when
passed in, so you don't need to do "%s" % number.
You can also try the following instead of using the actual URL, to make it more Django-like.
from django.core.urlresolvers import reverse
...
def search(request):
number = request.GET['search']
return HttpResponseRedirect(reverse('stock.views.stocknumber', args=(number,)))
I have a search page that takes a variety of parameters. I want to create a new URL by just altering one parameter in the query. Is there an easy way to do this - something like:
# example request url
http://example.com/search?q=foo&option=bar&option2=baz&change=before
# ideal template code
{% url_with change 'after' %}
# resulting url
http://example.com/search?q=foo&option=bar&option2=baz&change=after
So this would take the request url, alter one query parameter and then return the new url. Similar to what can be achieved in Perl's Catalyst using $c->uri_with({change => 'after'}).
Or is there a better way?
[UPDATED: removed references to pagination]
I did this simple tag which doesn't require any extra libraries:
#register.simple_tag
def url_replace(request, field, value):
dict_ = request.GET.copy()
dict_[field] = value
return dict_.urlencode()
Use as:
<a href="?{% url_replace request 'param' value %}">
It wil add 'param' to your url GET string if it's not there, or replace it with the new value if it's already there.
You also need the RequestContext request instance to be provided to your template from your view. More info here:
http://lincolnloop.com/blog/2008/may/10/getting-requestcontext-your-templates/
So, write a template tag around this:
from urlparse import urlparse, urlunparse
from django.http import QueryDict
def replace_query_param(url, attr, val):
(scheme, netloc, path, params, query, fragment) = urlparse(url)
query_dict = QueryDict(query).copy()
query_dict[attr] = val
query = query_dict.urlencode()
return urlunparse((scheme, netloc, path, params, query, fragment))
For a more comprehensive solution, use Zachary Voase's URLObject 2, which is very nicely done.
Note:
The urlparse module is renamed to urllib.parse in Python 3.
I improved mpaf's solution, to get request directly from tag.
#register.simple_tag(takes_context = True)
def url_replace(context, field, value):
dict_ = context['request'].GET.copy()
dict_[field] = value
return dict_.urlencode()
This worked pretty well for me. Allows you to set any number of parameters in the URL. Works nice for a pager, while keeping the rest of the query string.
from django import template
from urlobject import URLObject
register = template.Library()
#register.simple_tag(takes_context=True)
def url_set_param(context, **kwargs):
url = URLObject(context.request.get_full_path())
path = url.path
query = url.query
for k, v in kwargs.items():
query = query.set_param(k, v)
return '{}?{}'.format(path, query)
Then in the template:
<a href="{% url_set_param page=last %}">
There are a number of template tags for modifying the query string djangosnippets.org:
http://djangosnippets.org/snippets/553/
http://djangosnippets.org/snippets/826/
http://djangosnippets.org/snippets/1243/
I would say those are the most promising looking. One point in all of them is that you must be using django.core.context_processors.request in your TEMPLATE_CONTEXT_PROCESSORS.
You can try https://github.com/dcramer/django-paging
In addition to the snippets mentioned by Mark Lavin, Here's a list of other implementations I could find for a Django template tag which modifies the current HTTP GET query string.
On djangosnippets.org:
#2237 Manipulate URL query strings using context variables using a template tag by JHsaunders
#2332 Querystring Builder - create urls with GET params by jibberia
my favorite: #2413 Yet another query string template tag by atms
#2428 Add GET parameters from current request by naktinis
On PyPI:
django-spurl by Jamie Matthews
django-urltags by Calloway Project/Corey Oordt
the add_query_param filter in django-rest-framework by Tom Christie
On GitHub:
update_querystring by David Gouldin