testt1
is my view for taking a queryset and turning out a list of objects and their foreign key children.
mydetail
is the detail view for the individual objects. No slug is used in the list, but it is in the list template to call the detail pages. But all these errors come from trying to call the list, not the detail. If I just type the slug into the address bar, all my detail pages come up just fine!
I have tried a lot of different things, and get a lot of different errors, but the bottom line is always the same: no list
named url fails
Error during template rendering
In template /home/malikarumi/Projects/hattie/templates/base.html, error at line 44
Reverse for 'jhp_url' not found. 'jhp_url' is not a valid view function or pattern
name.
‘jhp_url’ is the named url for the detail page.
But here is line 44:
<link href="{% static 'plugins/owl-carousel/owl.carousel.css' %}" rel="stylesheet">
the urlpattern:
path('<slug:slug>/', mydetail, name='jhp_url'),
the call to reverse():
def get_absolute_url(self):
return reverse(‘jhp_url', kwargs={'slug': self.slug})
namespaced url fails
Error during template rendering
In template /home/malikarumi/Projects/hattie/templates/base.html, error at line 44
Reverse for 'jhp_url' with keyword arguments '{'slug': ''}' not found. 1 pattern(s) tried: ['(?P[^/]+)/courts/(?P[-a-zA-Z0-9_]+)/$']
Now it has an empty string for the slug. The pattern is right. If it had a slug, it would work.
def get_absolute_url(self):
return reverse('bench:jhp_url', kwargs={'slug': self.slug})
list template:
<h3>{{ C.name }}</h3>
urlpattern is the same.
no slug passed
testt1() missing 1 required positional argument: 'slug'
Which means that as I have currently defined it:
def testt1(request, slug, *args, **kwargs):
print(request.slug)
Is not being provided the slug variable / value. Now it might also be a question of position, so I changed only this:
def testt1(request, *args, **kwargs):
But since slug is still in the return value, now I get:
Unresolved reference 'slug'
I take it out, and the autoreloader wakes up…
'WSGIRequest' object has no attribute 'slug'
Yes, well, that's what I suspected. That’s why I had the print in there. The question is: why does it not have slug?
https://docs.djangoproject.com/en/3.2/topics/http/urls/#including-other-urlconfs
Whenever Django encounters include(), it chops off whatever part of the URL matched up to that point and sends the remaining string to the included URLconf for further processing.
Apparently, I don’t understand this process, because I always assumed this meant the slug part of my url was being passed along as part of the request object. But now I see that the word 'slug' does not appear in the docs on the response request page:
https://docs.djangoproject.com/en/dev/ref/request-response/
extra arguments fail
The docs also give the option of passing ‘extra arguments’:
https://docs.djangoproject.com/en/3.2/topics/http/urls/#passing-extra-options-to-include
https://docs.djangoproject.com/en/3.2/topics/http/urls/#passing-extra-options-to-view-functions
But this says nothing about using extra arguments in conjunction with named or even namespaced urls. Does that mean they don't, or can't go together? Then shouldn’t they say so explicitly, like the Zen of Python? Anyway, my efforts in this area all failed miserably:
File "/home/malikarumi/Projects/hattie/bench/urls.py", line 13
path('<slug:slug>', mydetail, name='jhp_url', {'slug': slug}),
^
SyntaxError: positional argument follows keyword argument
Are they saying a dictionary is a positional argument, and not a keyword?
File "/home/malikarumi/Projects/hattie/bench/urls.py", line 14, in <module>
path('', testt1, slug='slug', name='testt1'),
TypeError: _path() got an unexpected keyword argument 'slug'
File "/home/malikarumi/Projects/hattie/bench/urls.py", line 13, in <module>
path('<slug:slug>', mydetail, slug='slug', name='jhp_url'),
TypeError: _path() got an unexpected keyword argument 'slug'
File "/home/malikarumi/Projects/hattie/bench/urls.py", line 13, in <module>
path('<slug:slug>', mydetail, name='jhp_url', slug=slug),
NameError: name 'slug' is not defined
It's not? then wtf is 'slug:slug'???
Clearly, the slug is not being passed. If it isn't happening automatically,
and it isn't part of the request object - despite slug:slug in the
urlpattern, and I can't use these extra arguments, how am I supposed to get
the slug passed?!
explicit slug keyword argument in view fails:
File "/home/malikarumi/Projects/hattie/bench/views.py", line 22
def testt1(request, *args, '<slug:slug>', **kwargs):
^
SyntaxError: invalid syntax
Just in case you wondering, yes, I did try explicitly passing the slug as a keyword. All such efforts failed.
def testt1(request, slug=slug, **kwargs):
unresolved reference slug
def testt1(request, slug=self.slug, **kwargs):
unresolved reference self
UPDATE
As requested, here is my latest version of views and urls, and at the bottom a link to the full stacktrace going back to yesterday.
VIEWS
from django.shortcuts import render
from bench.models import Jurisdiction
from django.shortcuts import get_object_or_404
from statedict import sdl
j = Jurisdiction.objects.all()
from urllib.parse import urlparse
def mydetail(request, slug, **kwargs):
court = j.get(slug=slug)
# twodigit = twodigit
return render(request, 'bench/jhp_.html',
{'court': court})
def testt1(request, **kwargs):
federalcourts = j.filter(sphere="Appeals").filter(purview="Federal")
circuits = federalcourts.order_by('siblingrank')
scotus = circuits.first().name
context = {'circuits': circuits, 'scotus': scotus, 'slug': slug}
return render(request, 'bench/listtest1.html', context)
URLS
from django.urls import path
from bench.views import mydetail, testt1
app_name = 'bench'
urlpatterns = [
path('/', mydetail, name='jhp_url'),
path('', testt1, name='testt1'),
]
STACKTRACE:
https://docs.google.com/document/d/1ktm-y_AEUrllw0kSctlLgUyNfxVx6eFnYlOZCs-jM2w/edit?usp=sharing
thank you
I would drop the **kwargs from your views unless you have a good reason not to. The reason is that it will hide problems with your views and urls.
The way I would write your views and urls are as follows:
# views.py
def mydetail(request, slug):
...
def testt1(request):
...
# urls.py
app_name = 'bench'
urlpatterns = [
path('<slug:slug>/', mydetail, name='jhp_url'),
path('/', testt1, name='testt1'),
]
The fully qualified url names for these would be:
bench:jhp_url
bench:testt1
If you're using something like:
<h3>{{ C.name }}</h3>
And it's still giving you an error about Reverse for 'jhp_url' with keyword arguments '{'slug': ''}' not found., then the issue is that C.slug is resolving to an empty string or None, or C is None.
Related
Sorry if the title is unclear, I'm not sure the best way to describe the issue. I have an application with a Ticket model and a Team model. All Tickets are associated with a single Team. The issue I'm having is a problem of URL reversing. I'm trying to set it up my URLs like so: /<team_pk>/tickets/ displays a list of tickets associated with the Team specified by team_pk. So /1/tickets/ would display all of the tickets for the first Team. Both of these objects are in the app tracker.
To do this, I've set up my project/urls.py files like so:
project/urls.py
urlpatterns = [ path('<team_pk>/', include('tracker.urls', namespace='tracker')), ]
tracker/urls.py
urlpatterns = [ path('tickets/', views.TicketTable.as_view(), name='ticket_list'), ]
Then, inside my html templates, I have the following URL tag:
href="{% url 'tracker:ticket_list' %}"
This results in a NoReverseMatch error:
NoReverseMatch at /1/tickets/
Reverse for 'ticket_list' with no arguments not found. 1 pattern(s) tried: ['(?P<team_pk>[^/]+)/tickets/$']
What I would like is for the reverse match to just use the current value for the team_pk URL kwarg.
What I have tried to fix it:
I have found the following solution to the problem, but it involves a lot of repetition, and I feel like there must be a DRYer way.
First, I extend the get_context_data() method for every view on the site.
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['current_team_pk'] = self.kwargs['team_pk']
return context
Then I reference this context in every URL template tag:
href="{% url 'tracker:ticket_list' team_pk=current_team_pk %}"
This results in the desired behavior, but it's a lot of repetition. So, is there a better way?
Edit:
Based on Willem Van Onsem's suggestion, I changed the URL template tag to href="{% url 'tracker:ticket_list' team_pk=team_pk %}", referencing the URL kwarg directly. But this doesn't seem to be working reliably. On the index page /<team_pk>/ loads just fine, and it includes two relevant URLs: /<team_pk>/ and /<team_pk>/tickets/. When I navigate to /<team_pk>/tickets/, however, I get another NoReverseMatch error:
NoReverseMatch at /1/tickets/
Reverse for 'home' with keyword arguments '{'team_pk': ''}' not found. 1 pattern(s) tried: ['(?P<team_pk>[^/]+)/$']
It seems the URL kwarg <team_pk> is not being passed for some reason. But the only link to 'home' is part of my base.html, which the other templates are extending. So the relevant template tags are the same.
Edit 2:
The view in question:
class TicketTable(LoginRequiredMixin, SingleTableMixin, FilterView):
table_class = my_tables.TicketTable
template_name = 'tracker/ticket_list.html'
filterset_class = TicketFilter
context_object_name = 'page'
table_pagination = {"per_page": 10}
PAGE_TITLE = 'Open Tickets'
TICKET_STATUS_TOGGLE = 'Show Closed Tickets'
TICKET_STATUS_TOGGLE_URL = 'tracker:closed_ticket_list'
DISPLAY_DEV_FILTER = True
DISPLAY_STATUS_FILTER = True
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['page_title'] = self.PAGE_TITLE
context['ticket_status_toggle'] = self.TICKET_STATUS_TOGGLE
context['ticket_status_toggle_url'] = self.TICKET_STATUS_TOGGLE_URL
context['display_dev_filter'] = self.DISPLAY_DEV_FILTER
context['display_status_filter'] = self.DISPLAY_STATUS_FILTER
return context
def get_queryset(self):
return models.Ticket.objects.filter_for_team(self.kwargs['team_pk']).filter_for_user(self.request.user).exclude(status='closed')
Edit 3:
I found a solution to access the URL kwargs without modifying context data. I'm not sure why team_pk=team_pk didn't work in the URL tag, but team_pk=view.kwargs.team_pk does work.
Based on the comments and responses from Willem Van Onsem, a friend of mine, and some of my own digging, I found what I think is the DRYest way to do what I was trying to do. I created a custom mixin:
class CommonTemplateContextMixin:
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
if self.kwargs.get('team_pk'):
context.setdefault('team_pk', self.kwargs.get('team_pk'))
else:
context.setdefault('team_pk', self.request.user.teams.all()[0].pk)
return context
Then I subclass this mixin with all my views. Then I have a team_pk template tag inside all my templates, and I just add team_pk=team_pk to all my URL template tags. The only advantage to using this instead of team_pk=view.kwargs.team_pk is that I can add some additional logic for the case when the URL kwarg isn't available.
Given following admin settings:
class BrokerLocationSetForm(forms.ModelForm):
class Meta:
model = BrokerLocationSet
fields = ('broker', 'program', 'label', 'locations')
widgets = {
'locations': autocomplete.ModelSelect2Multiple(url='admin-autocomplete-location', forward=('broker','program')),
}
class BrokerLocationSetAdmin(admin.ModelAdmin):
model = BrokerLocationSet
form = BrokerLocationSetForm
list_display=['broker', 'program', 'label']
admin.site.register(BrokerLocationSet, BrokerLocationSetAdmin)
When I try navigate to add view in admin for BrokerLocationSetForm it raises following error:
raise NoReverseMatch(msg) NoReverseMatch: Reverse for 'program_program_change' with arguments '(u'__fk__',)' not found. 1 pattern(s) tried: [u'admin/program/program/(?P<program_pk>\\d+)/change/$']
When I debug in shell:
reverse('admin:broker_broker_change', 'myapp.urls', args=(u'__fk__',))
it outputs:
u'/admin/broker/broker/fk/change/'
but for:
reverse('admin:program_program_change', 'myapp.urls', args=(u'__fk__',))
I get same error as above. After some debugging I sensed that somehow admin was passing a string instead of an int into reverse function while it expected an integer as below :
reverse('admin:program_program_change', 'myapp.urls', args=(u'1',))
u'/admin/program/program/1/change/'
Since django admin does this url reversing magic I am not sure where I should customize this to fix the bug. I have got this code base fairly new and to get sense completely.
How I can fix above bug by customizing admin model or form. I dont want to update 'admin:program_program_change' but probably provide an alternate route to same view! . Is it possible ? please advise !
I found a solution however, I am not sure if this is best one. Since ProgramAdmin expects a numeric parameter while popup link from BrokerLocationSetAdmin is expecting a route with a string parameter. e.g
reverse('admin:program_program_change', 'myapp.urls', args=(u'__fk__',))
Solution was to inject another admin route with same name to ProgramAdmin model by overriding its get_urls method as follow:
class ProgramAdmin(admin.ModelAdmin):
...
...
def get_urls(self):
from django.conf.urls import url
from functools import update_wrapper
def wrap(view):
def wrapper(*args, **kwargs):
return self.admin_site.admin_view(view)(*args, **kwargs)
wrapper.model_admin = self
return update_wrapper(wrapper, view)
urls = super(ProgramAdmin, self).get_urls()
info = self.model._meta.app_label, self.model._meta.model_name
alt_urls=[
url(r'^(?P<program_pk>\w+)/change/$', wrap(self.change_view), name='%s_%s_change' % info),
]
return urls+alt_urls
Now we have two routes with same name but different paths parameter e.g:
/admin/program/program/<program_pk>/change/ django.contrib.admin.options.change_view admin:program_program_change
admin/program/program/(?P\d+)/change/$
/admin/program/program/<program_pk>/change/ django.contrib.admin.options.change_view admin:program_program_change
admin/program/program/(?P\w+)/change/$
Depending on the context one of route will be used.
Use Django 1.10.4. I have a model Stream, for which I created CreateView. When objects are created through the admin panel everything works fine, but when I use the form CreateView, an object is created (either in admin or in the database is no different from the other), but attempts to provide a link to it through DetailView result in an error:
NoReverseMatch at /
Reverse for 'detail_stream' with arguments '()' and keyword arguments '{'pk': 17}' not found.
2 pattern(s) tried: ['(?P<pk>[0-9])/$', 'streams/(?P<pk>[0-9])/$']
This error occurs when displaying the ListView, and then only for an object created through CreateView.
The place where the error occurs:
{% for item in stream_list %}
<a href="/streams{% url "detail_stream" pk=item.id %}">
...
</a>
{% endfor %}
When you try to go directly to DetailView (http://127.0.0.1:8000/streams/17) 404 error.
urls.py:
from django.conf.urls import url
from .views import StreamDetail, StreamUpdate
urlpatterns = [
url(r'^$', StreamList.as_view(), name='streams'),
url(r'^(?P<pk>[0-9])/$', StreamDetail.as_view(), name='detail_stream'),
url(r'^(?P<pk>[0-9])/update/$', StreamUpdate.as_view()),
]
Also, the url for the streams added to the main site urlpatterns.
View:
class StreamCreate(LoginRequiredMixin, CreateView):
login_url = '/login/'
def form_valid(self, form):
regex = re.compile('[^a-zA-Z]')
newtags = []
for tag in form.cleaned_data['tags']:
tag = regex.sub('',tag)
newtags.append(tag)
form.cleaned_data['tags'] = newtags
return super(StreamCreate,self).form_valid(form)
def form_invalid(self, form):
print(form.errors)
return super(StreamCreate,self).form_invalid(form)
def get_success_url(self):
return reverse('streams')
I suspect that something I did not realize at CreateView, but I can not understand that and need your help.
Your regex in the given route is wrong.
url(r'^(?P<pk>[0-9])/$', StreamDetail.as_view(), name='detail_stream')
[0-9] means it expects a single-digit number. 17 has two digits, so the regexp needs to take that into account (add + there)
url(r'^(?P<pk>[0-9]+)/$', StreamDetail.as_view(), name='detail_stream')
Some other routes in there have the same issue.
This seems to be a "classic" problem :
NoReverseMatch at /tr/showroom/
Reverse for 'project-list' with arguments '()' and keyword arguments '{}' not found. 0 pattern(s) tried: []
But the problem is, when I check the different topic on the internet and then my files, I don't get it.
So it's working perfectly on the native language. It happens when I try to change the language on this showroom page only.
Every page that have been copy with the commad cms copy works fine except this one.
Well, here is the model :
def get_slug(self):
return self.safe_translation_getter(
'slug',
language_code=get_language(),
any_language=False)
def get_absolute_url(self, current_app=None):
"""
Warning: Due to the use of django application instance namespace
(for handle multi instance of an application)we add the possibility
to use it with the reverse.
So if get_absolute_url is call without app instance it may failed (
for example in django_admin)
"""
lang = get_language()
if self.has_translation(lang):
kwargs = {'slug': self.get_slug()}
return reverse('djangocms_showroom:project-detail',
kwargs=kwargs,
current_app=current_app)
return reverse('djangocms_showroom:project-list', current_app=current_app)
def get_full_url(self, site_id=None):
return self._make_full_url(self.get_absolute_url(), site_id)
def _make_full_url(self, url, site_id=None):
if site_id is None:
site = Site.objects.get_current()
else:
site = Site.objects.get(pk=site_id)
return get_full_url(url, site)
The url :
from django.conf.urls import patterns, url
from .views import (ProjectListView, ProjectDetailView)
urlpatterns = patterns(
'',
url(r'^$', ProjectListView.as_view(), name='project-list'),
url(r'^project/(?P<slug>\w[-\w]*)/$', ProjectDetailView.as_view(), name='project-detail'),
)
And the html error :
Error during template rendering
In template /var/www/webapps/blippar_website/app/blippar/templates/djangocms_showroom/project_list.html, error at line 14
Which is :
<form id="projects-filter" action="{% url 'djangocms_showroom:project-list' %}">
Well, I am not very good yet with django and django-cms, if someone has any clue, it would be marvellous !
I have an affiliate program app with redirects and link statistics tracking. A read-only field in the Django Admin should display the full URL of the affiliate link, (so the user can copy+paste this into their editor) but the reverse() call in the model instance's get_absolute_url() method is failing when called from a callable in the admin class. For example:
from project urls.py
urlpatterns = patterns(
'',
url(r'^a/', include('shop.affiliates.urls', namespace='affiliates')),
...
from shop.affiliates.urls.py
urlpatterns = patterns(
'',
url(r'^(?P<slug>[\w]+)/$', redirect_to_affiliate_link, name='affiliate_redirect'),
)
from shop.affiliates.models.py
class AffiliateLink(models.Model):
...
slug = models.SlugField(
max_length=4,
help_text='The slug for this link, used to generate url.',
)
...
def get_absolute_url(self):
return reverse(
'affiliates:affiliate_redirect',
kwargs={'slug': self.slug},
)
Note: for the sake of debugging simplicity, it's safe to assume that the slug field has already been populated in the database previously. So I'm not trying to create a new object where slug has not yet been set.
from shop.affiliates.admin.py
class AffiliateLinkInline(admin.StackedInline):
model = AffiliateLink
extra = 0
fields = (
..., 'hyperlink', ...
)
readonly_fields = (
'hyperlink', ...
)
def hyperlink(self, obj):
url = 'http://example.com{}'.format(obj.get_absolute_url())
return '{0}'.format(url)
hyperlink.allow_tags = True
When loading the appropriate admin page, I get a NoReverseMatch exception.
Exception value:
Reverse for 'affiliate_redirect' with arguments '()' and keyword arguments '{u'slug': u''}' not found. 1 pattern(s) tried: [u'a/(?P<slug>[\\w]+)/$']
so the proper regex is found, but the slug parameter is empty. I verified that obj.slug within the admin callable exists, and it is the correct AffiliateLink slug. To make matters more strange, if I switch the kwargs in get_absolute_url() like so:
def get_absolute_url(self):
return reverse(
'affiliates:affiliate_redirect',
kwargs={'bug': self.slug},
)
Then the exception value changes to:
Reverse for 'affiliate_redirect' with arguments '()' and keyword arguments '{u'bug': u'7aeB'}' not found. 1 pattern(s) tried: [u'a/(?P<slug>[\\w]+)/$']
So the kwarg value for key 'slug' disappears from the exception value, but the value for 'bug' stays.
What am I doing wrong here? Any help is greatly appreciated.
URL patterns are sometime evaluated before URLconf has been loaded. Try reverse_lazy instead of reverse
https://docs.djangoproject.com/en/dev/ref/urlresolvers/#reverse-lazy