I am trying to make pretty meaningful urls, but I guess I'm doing it wrong.
This works:
from django.conf.urls.defaults import patterns, url
from places.views import explore_view
urlpatterns = patterns('',
url(r'', explore_view, name='explore'),
)
This does not:
from django.conf.urls.defaults import patterns, url
from places.views import explore_view
urlpatterns = patterns('',
url(r'(?P<countryorcategory>[0-9A-Za-z._%+-]+)', explore_view, name='explore'),
)
As I get this error:
Reverse for 'explore' with arguments '()' and keyword arguments '{}'
not found.
Here is the code for explore_view:
def explore_view(request, countryorcategory=None):
"""
This is the explore view - to view places sugeested by ambassadors
"""
user = request.user
page = request.GET.get("page", 1)
per_page = request.GET.get("per_page", 20)
category_id = request.GET.get("category_id", None)
attrs = request.GET
lat = safe_attr(attrs, "lat", "float", None)
lon = safe_attr(attrs, "lon", "float", None)
q = request.GET.get('q', None)
if q and not lat or lon:
cache_key = 'GoogleGeocode-{}'.format(hashlib.md5(q.encode('UTF-8', 'replace')).hexdigest())
latlon = cache.get(cache_key)
if not latlon:
latlon = geocode(q)
if latlon:
cache.set(cache_key, latlon)
if latlon:
lat = latlon['lat']
lon = latlon['lng']
if not q:
q = ''
category_names = getattr(settings, "EXPLORE_CATEGORIES", [])
categories = [Category.objects.get(name=cat_name).serialize() for cat_name in category_names]
more = True
places = Place.objects.explore_places(user, category_id=category_id, lat=lat, lon=lon, page=page, per_page=20)
if len(places) != per_page:
more = False
return render_to_response('explore/main.html', {'places': places, 'categories': categories, 'category_id': category_id, 'lat': lat, 'lon': lon, 'more': more, 'q': q}, RequestContext(request))
This line:
url(r'(?P<countryorcategory>[0-9A-Za-z._%+-]+)', explore_view, name='explore')
...is defining an url that takes an argument countryorcategory in the template. You need to put an argument on your url either of the following in your template:
{% url 'explore' argument %}
{% url 'explore' countryorcategory=argument %}
If you want to continue to use non-argument urls with the same name, you can define additional urls with the same name but with different patterns. For example:
urlpatterns = patterns('',
url(r'(?P<countryorcategory>[0-9A-Za-z._%+-]+)', explore_view, name='explore'),
url(r'', explore_view, name='explore'),
)
Then {% url 'explore' %} should work both with and without an argument.
For me, I forgot the namespace of the Route. Instead of
{% url 'login' %}
I should have written
{% url 'accounts:login' %}
with this configuration:
# root URLs
url(r'^accounts/', include('myproject.accounts.accounts.urls', namespace='accounts'))
# accounts URLs
url(r'^login$', views.login, name='login')
I'm assuming you are using a template with something like this :
{% url 'explore' argument %}
And this error probably means that the argument is not set to anything.
Related
I am doing a simple form site with Django. This is what my sites url is looks like: mysite.com/register/12345678
I want to print the part after the register (12345678) to the order id field. When someone goes this mysite.com/register/87654321 url then i want to print it.
How can i do that? These are my codes.(Currently using Django 1.11.10)
forms.py
from django import forms
from .models import Customer
from . import views
class CustomerForm(forms.ModelForm):
class Meta:
model = Customer
fields = (
'order_id','full_name','company','email',
'phone_number','note')
widgets = {
'order_id': forms.TextInput(attrs={'class':'orderidcls'}),
'full_name': forms.TextInput(attrs={'class':'fullnamecls'}),
'company': forms.TextInput(attrs={'class':'companycls'}),
'email': forms.TextInput(attrs={'class':'emailcls'}),
'phone_number': forms.TextInput(attrs={'class':'pncls'}),
'note': forms.Textarea(attrs={'class':'notecls'}),
}
views.py
from django.shortcuts import render
from olvapp.models import Customer
from olvapp.forms import CustomerForm
from django.views.generic import CreateView,TemplateView
def guaform(request,pk):
form = CustomerForm()
if request.method == "POST":
form = CustomerForm(request.POST)
if form.is_valid():
form.save(commit=True)
else:
print('ERROR FORM INVALID')
theurl = request.get_full_path()
orderid = theurl[10:]
return render(request,'forms.py',{'form':form,'orderid':orderid})
customer_form.html
{% extends 'base.html' %}
{% block content %}
<h1>REGÄ°STRATÄ°ON</h1>
<form class="registclass" method="POST">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-default">REGISTER</button>
</form>
{% endblock %}
urls.py
from django.conf.urls import url
from django.contrib import admin
from olvapp import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^thanks/$',views.ThankView.as_view(),name='thank'),
url(r'^register/(?P<pk>\d+)',views.guaform,name='custform'),
]
You have passed the value to your view as 'pk' so you can use that to set the the initial value:
views.py
form = CustomerForm(initial={'order_id': pk})
SamSparx is right, here's some additional information to help prevent such errors in advance:
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^thanks/$',views.ThankView.as_view(),name='thank'),
url(r'^register/(?P<pk>\d+)',views.guaform,name='custform'),
]
You are using regex to parse your path. Regex is generally speaking not recommended in this case according to the docs because it might introduce more errors and is harder to debug. (Unoptimized) RegEx also tends to be slower.
For simple use cases such as your path here, consider choosing the default pathing syntax as below:
urlpatterns = [
url('admin/', admin.site.urls),
url('thanks/',views.ThankView.as_view(),name='thank'),
url('register/<int:pk>',views.guaform,name='custform'),
]
You could of course also use string instead of int depending on your usage of pk.
Your paths do not all end with a slash consistently. This might impact your SEO and confuse users. See this and this.
Also your form is not imported .as_view() for some reason which could cause some problems.
Update :: Problem solved.just follow the guy below.
in my urls.py
path('', store_view, name='store'),
path('category/<str:category_name>/', category_view, name='category'),
in views.py
def store_view(request):
categories = list(Category.objects.all())
context = {
'categories': categories,
}
return render(request, 'store/store.html', context)
def category_view(request, category_name):
category = Category.objects.get(name=category_name)
context = {
'category': category,
}
return render(request, 'store/single-category-view.html', context)
in my template : store.html , that is rendered by store_view >>
{% for item in categories %}
<a href="{% url 'category' item.name %}">
{{item.name}}
</a>
{% endfor %}
Now,the problem is, in the category column in my DB, i have got one category called 'Laptop/MacBook'.when ever this name is passed to the url, it says >>
"Reverse for 'category' with arguments '('Laptop/MacBook',)' not
found. 1 pattern(s) tried: ['category/(?P<category_name>[^/]+)/$']
But when i changed the category name from Laptop/MacBook to Laptop and MacBook , it worked fine and showed no error.
But i want to keep it as it was,'Laptop/MacBook'.How can i do that??and how do you guys deal with that?
Try encoding and decoding your DB values. Assuming its Python 3:
from urllib.parse import quote, unquote
encoded = quote("Laptop/Macbook", safe="")
decoded = unquote(encoded)
print(encoded, decoded)
Output:
Laptop%2FMacbook Laptop/Macbook
With this your route should take in the right param.
from django.http import HttpResponse, request
from django.shortcuts import render
def store_view(request):
name = "Laptop/Macbook"
return render(request, './store.html', context={"name": name})
def category_view(request, category_name):
print(category_name)
return HttpResponse(b"Here we go!")
templatetags/tags.py
from urllib.parse import quote, unquote
from django import template
register = template.Library()
#register.filter(name='encode')
def encode(name):
return quote(name, safe="")
#register.filter(name='decode')
def decode(name):
return unquote(name)
Template:
{% load tags %}
<a href="{% url 'category' name|encode %}">
{{name}}
</a>
Don't forget to add in settings:
'OPTIONS': {
'libraries':{
'tags': 'templatetags.tags',
}
},
When using a "/", django thinks that you are passing more than one parameter. To fix this, replace str by path in your urls like so:
path('', store_view, name='store'),
path('category/<path:category_name>/', category_view, name='category'),
This will make django understand that the / does not mean there are two separate parameters in your url.
Is there any method to provide url argument in case of render or any other solution? Somehow I need to provide user_url.
# view
def create_gallery(request, user_url):
if request.method == 'POST':
extended_form = GalleryExtendedForm(request.POST, prefix="extended_form")
basic_form = GalleryForm(request.POST, prefix="basic_form")
print(request.POST)
if extended_form.is_valid() and basic_form.is_valid():
pass
else:
extended_form = GalleryExtendedForm(prefix="extended_form")
basic_form = GalleryForm(prefix="basic_form")
return render(request, 'galleries/gallery_create_n_update.html',
{'extended_form': extended_form,
'basic_form': basic_form})
# core.urls
urlpatterns = [
url(r'^(?P<user_url>[\w.-]+)/', include('profiles.urls', namespace='profiles_user')),
]
# profiles.urls
urlpatterns = [
url(r'^gallery/', include('galleries.urls')),
# ... lots of others urls
]
# galleries.urls
urlpatterns = [
url(r'^add/$', views.create_gallery, name='gallery-add'),
]
Error:
django.urls.exceptions.NoReverseMatch: Reverse for 'gallery-add' with arguments '('',)'
and keyword arguments '{}' not found.
1 pattern(s) tried: ['(?P<user_url>[\\w.-]+)/gallery/add/$']
You should pass user_url into the context parameter of render(), so that it can be used in the template.
Then, inside the template, you can add user_url as a parameter to the url template tag, like this:
{% url 'gallery-add' user_url=user_url %}
How does {"% url 'news_id' %"} work?
I do have a url pattern url(r'^((?:\w|-)+)/$', 'comments.views.home', name='news_id') but I still get NoReverseMatch.
It says
Reverse for 'news_id' with arguments '()' and keyword arguments '{}' not found. 1 pattern(s) tried: ['((?:\w|-)+)/$']
views.py
from django.shortcuts import render
from comments.models import User
from django.http import HttpResponseRedirect, HttpResponse
from django.template import RequestContext, loader, Context
from comments.models import News, User, Comment
from django.core.urlresolvers import resolve
def home(request, url_arg):
print "in Views.py", "and url_arg = ", url_arg
c = Comment.objects.all().filter(news__news_id=url_arg)
n = News.objects.all().get(news_id=url_arg)
cont = Context({'news': n.text, 'cts': c, 'news_id': n.news_id})
rc = RequestContext(request, cont)
t = loader.get_template('home.html')
print 'n = ', n
return HttpResponse(t.render(rc))
return render(request, 'home.html', context_dict, context_instance=RequestContext(request))
def submit(request):
print "request.path_info = ", request.path_info
print "in submit method and url = ", resolve(request.path_info).url_name, " & other try = ", request.resolver_match.url_name
news_id = request.POST.get('news_id')
user_id = request.POST.get('user_id')
comment_text = request.POST.get('comment')
print "news_id =", news_id, "user_id = ", user_id, "comment_text = ", comment_text
n = News(news_id=news_id)
n.save()
u = User(name='random',user_id=user_id)
u.save()
c = Comment(news=n, user=u, text=comment_text)
c.save()
return HttpResponse("Thanks!")
urls.py
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
# Examples:
url(r'^(?:\w|-)+/submit/$','comments.views.submit'),
url(r'^((?:\w|-)+)/$', 'comments.views.home', name='news_id'),
# url(r'^blog/', include('blog.urls')),
url(r'^admin/', include(admin.site.urls)),
]
home.html
<p>
News: {{news}}<br>
</p>
<form action="{% url news_id %}" method="post"> {% csrf_token %}
User Id: <input type="text" name="user_id"> <br>
Comment:<br>
<input type="text" name="comment" placeholder="Express your opinion ...">
<input type="submit" value="Submit"> <br>
{% for ct in cts %}
{{ ct.text }}<br>
{% endfor %}
</form>
You've misunderstood a few things here. In particular, you've mixed up the name of the URL pattern, and the parameters you need to pass to it.
For instance, if you wanted to capture the ID of a post in your blog and pass it to a detail view, you would normally do something like:
url(r'^(?P<post_id>)/$', views.post_detail, name='post_detail')
so the name of the pattern is post_detail and the parameter it takes is called post_id. So you would reverse it by doing:
{% url "post_detail" post_id=my_post.id %}
Also, your regex is very odd. You have a non-capturing group as the only contents of a capturing group. I can't tell what you are actually trying to do with that pattern, but normally a home page wouldn't take any parameters at all - and in fact you are not actually passing any parameters. Just use r'^$'.
I'm working on extending Horizon to include a custom app.
In that app, I have a DataTable:
class WorkloadsTable(tables.DataTable):
name = tables.Column("name", verbose_name=_("Name"))
description = tables.Column("description", verbose_name=_("Description"))
image = tables.Column("image", verbose_name=_("Image"))
flavor = tables.Column("flavor", verbose_name=_("Flavor"))
class Meta:
name = "workloads_table"
verbose_name = _("Workloads Table")
table_actions = (CreateNewWorkload, DeleteWorkload)
row_actions = (UpdateWorkload, DeleteWorkload)
which has a LinkAction:
class UpdateWorkload(tables.LinkAction):
name = "update"
verbose_name = _("Edit Workload")
url = "horizon:mydashboard:workloads_panel:update"
classes = ("ajax-modal",)
icon = "pencil"
def get_link_url(self, datum):
base_url = super(UpdateWorkload, self).get_link_url(datum)
workload_id = self.table.get_object_id(datum)
reversed = urlresolvers.reverse(self.url, args=[workload_id])
print reversed
return urlresolvers.reverse(self.url, args=[workload_id])
This LinkAction points to a routce in my urls.py:
WORKLOADS = r'(?P<workload_id>[^/]+)/%s$'
urlpatterns = patterns('',
url(r'^create/$', views.CreateView.as_view(), name='create'),
url(WORKLOADS % 'update', views.UpdateView.as_view(), name='update'),
url(r'^$', views.IndexView.as_view(), name='index'),
)
The issue is: When I enter the following url:
http://localhost:9000/mydashboard/workloads_panel/3/update
I get: NoReverseMatch: Reverse for 'update' with arguments '()' and keyword arguments '{}' not found. 1 pattern(s) tried: [u'mydashboard/workloads_panel/(?P<workload_id>[^/]+)/update$']
Where am I going wrong?
I guess the solution to your problem lies in the _update.html where you have to include the URL as,
{% block form_action %}
{% url 'horizon:mydashboard:workloads_panel:update' workload.id %}
{% endblock %}
while the workload.id is the object's id that you get in views.py in get_context_data function:
def get_context_data(self, **kwargs):
context = super(## the class name ##, self).get_context_data(**kwargs)
try:
context['workload'] = ##your API call ##(self.request,
self.kwargs['id'])
except Exception:
exceptions.handle(self.request)
return context
May be this will help you to resolve the error.
Well now the answer is quite simple. There is no matching URL for this reverse call:
{% url 'horizon:mydashboard:workloads_panel:update' %}
The update named URL pattern requires a valid workload_id argument matching your regex [^/]+