Passing kwargs to Django URL and views - python

I would like to pass kwargs to my view function through URL.
urls.py
urlpatterns = [
# ------------- set relations --------------------
url(r'^approve-form/$', views.approve_form,
{'content_type':None, 'form_id':None,}, name='approve-form'),]
views.py
def approve_form(request, content_type=None, form_id=None):
return HttpResponse('Working')
Now I am using reverse_lazy function to call the url from on of the model instance
models.py
class FormStatus(models.Model):
content_type = models.ForeignKey(ContentType)
form_id = models.IntegerField(verbose_name='Form Ref ID')
def __str__(self):
return "{}".format(self.content_type)
def get_approve_link(self):
return reverse_lazy("flow-control:approve-form", kwargs={'form_id':self.form_id,
'content_type':self.content_type})'
ERROR
Reverse for 'approve-form' with arguments '()' and keyword arguments '{'content_type': <ContentType: admin sanc model>, 'form_id': 12}' not found. 1 pattern(s) tried: ['flow-control/approve-form/$']
Is something wrong with the approach or is there any better approach for this ?
Thanks in advance.
PS: I tried the url documentation but couldn't figure it out.

Change your url to and check if its worked or not-
urlpatterns = [
# ------------- set relations --------------------
url(r'^approve-form/(?P<content_type>\w+)/(?P<form_id>\d+)/$', views.approve_form, name='approve-form'),]
views
def approve_form(request, content_type=None, form_id=None):
return HttpResponse('Working')

Related

Django Admin Model on add fails to render related change link

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.

Django: reverse() does not find view with args/kwargs given

There are a few posts related to my problem. However, none seems to solve the following issue:
I have defined urls in myapp/urls.py:
app_name = "myapp"
urlpatterns=[
url(r'^$', views.index, name="index"),
url(r'^adduser/$', views.addUser, name="adduser"),
]
and corresponding views in myapp/views.py:
def index(request, status_msg=None, error_msg=None):
return HttpResponse(render(request, "myapp/index.html",
context={"error_message":error_msg, "status_message":status_msg}))
def addUser(request):
try:
uname=request.POST["user_name"]
except KeyError:
url = reverse("myapp:index", args=(None, "No user name specified."))
return HttpResponseRedirect(url)
# ... adding user to db ...
url = reverse("myapp:index", args=("Added user '%s'"%uname,))
return HttpResponseRedirect(url)
Either variant of passing arguments to index() from the redirect in addUser() yields an error of the kind
Reverse for 'index' with arguments '(None, u'No user name specified.')' not found. 1 pattern(s) tried: [u'myapp/$']
I don't get what I'm doing wrong here. Seems the index view is found but not recognized to allow any arguments aside the request?
Using kwargs instead of args does not help, either.
Any suggestions are highly appreciated. Thanks already!
Your URL doesn't seem to support arguments (i.e captured groups in the regex). Therefore you should be using just:
reverse("myapp:index")
Check the docs for the reverse() function here.

Django 1.6 reverse() fails, kwarg value missing from Exception value

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

NoReverseMatch error using get_absolute_url()

I am trying to use get_absolute_url to follow DRY rules. If I code the class to build the href directly from the slug it all works fine. Ugly, messy but working...
So I am trying to get this done right using get_absolute_url() and I am getting stuck with a NoReverseMatch exception using the code below. I know this must be some kind of newbie error, but I have been up and down all the docs and forums for days, and still can't figure this one out!
I get this error:
NoReverseMatch at /calendar
Reverse for 'pEventsCalendarDetail' with arguments '()' and keyword arguments '{u'slug': u'Test-12014-05-05'}' not found. 0 pattern(s) tried: []
Request Method: GET
Request URL: http://127.0.0.1:8000/calendar
Django Version: 1.6
Exception Type: NoReverseMatch
Exception Value:
Reverse for 'pEventsCalendarDetail' with arguments '()' and keyword arguments '{u'slug': u'Test-12014-05-05'}' not found. 0 pattern(s) tried: []
Exception Location: /usr/local/lib/python2.7/site-packages/django/core/urlresolvers.py in _reverse_with_prefix, line 429
Python Executable: /usr/local/opt/python/bin/python2.7
Python Version: 2.7.6
using the following models.py excerpt:
#python_2_unicode_compatible
class Event(models.Model):
eventName = models.CharField(max_length=40)
eventDescription = models.TextField()
eventDate = models.DateField()
eventTime = models.TimeField()
eventLocation = models.CharField(max_length=60, null=True, blank=True)
creationDate = models.DateField(auto_now_add=True)
eventURL = models.URLField(null=True, blank=True)
slug = AutoSlugField(populate_from=lambda instance: instance.eventName + str(instance.eventDate),
unique_with=['eventDate'],
slugify=lambda value: value.replace(' ','-'))
#models.permalink
def get_absolute_url(self):
from django.core.urlresolvers import reverse
path = reverse('pEventsCalendarDetail', (), kwargs={'slug':self.slug})
return "http://%s" % (path)
The complete urls.py file:
from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
# Examples:
url(r'^$', 'electricphoenixfll.views.home', name='home'),
url(r'^home$', 'electricphoenixfll.views.home', name='home'),
url(r'^calendar$', 'electricphoenixfll.views.calendar', name='calendar'),
url(r'^forum$', 'electricphoenixfll.views.forum', name='forum'),
url(r'^donate$', 'electricphoenixfll.views.donate', name='donate'),
url(r'^donate_thanks$', 'electricphoenixfll.views.donate_thanks', name='donate_thanks'),
url(r'^what_is_fll$', 'electricphoenixfll.views.what_is_fll', name='what_is_fll'),
url(r'^core_values$', 'electricphoenixfll.views.core_values', name='core_values'),
url(r'^follow_the_phoenix$', 'electricphoenixfll.views.follow_the_phoenix', name='follow_the_phoenix'),
url(r'^followEnter/$', 'electricphoenixfll.views.followEnter', name='followEnter'),
url(r'^followList/$', 'electricphoenixfll.views.followList', name='followList'),
url(r'^about_us$', 'electricphoenixfll.views.about_us', name='about_us'),
url(r'^calendarDetail/(?P<slug>[\w-]+)/$', 'phoenixEvents.views.calendarDetail', name='pEventsCalendarDetail'),
url(r'^admin/', include(admin.site.urls)),
)
The second positional argument to reverse() is urlconf argument:
reverse(viewname[, urlconf=None, args=None, kwargs=None, current_app=None])
To make it work use keyword argument for setting args:
path = reverse('pEventsCalendarDetail', args=(), kwargs={'slug':self.slug})
Or, don't set args at all:
path = reverse('pEventsCalendarDetail', kwargs={'slug':self.slug})
Don't use both the permalink decorator and the reverse() call. They both do the same thing. Drop the decorator: it is deprecated.

Django CMS 2.1.0 App Extension NoReverseMatch TemplateSyntaxError

I'm writing a custom app for Django CMS, but get the following error when trying to view a published entry in the admin:
TemplateSyntaxError at /admin/cmsplugin_publisher/entry/
Caught NoReverseMatch while rendering: Reverse for 'cmsplugin_publisher_entry_detail' with arguments '()' and keyword arguments '{'slug': u'test-german'}' not found.
I can get the app working if I give the app a URL in my main application urls.py, but that fixes the app to a required URL, I just want extend Django CMS so the app will come from whichever page it's added to.
models.py Absolute URL Pattern
#models.permalink
def get_absolute_url(self):
return ('cmsplugin_publisher_entry_detail', (), {
'slug': self.slug})
urls/entries.py
from django.conf.urls.defaults import *
from cmsplugin_publisher.models import Entry
from cmsplugin_publisher.settings import PAGINATION, ALLOW_EMPTY, ALLOW_FUTURE
entry_conf_list = {'queryset': Entry.published.all(), 'paginate_by': PAGINATION,}
entry_conf = {'queryset': Entry.published.all(),
'date_field': 'creation_date',
'allow_empty': ALLOW_EMPTY,
'allow_future': ALLOW_FUTURE,
}
entry_conf_detail = entry_conf.copy()
del entry_conf_detail['allow_empty']
del entry_conf_detail['allow_future']
del entry_conf_detail['date_field']
entry_conf_detail['queryset'] = Entry.objects.all()
urlpatterns = patterns('cmsplugin_publisher.views.entries',
url(r'^$', 'entry_index', entry_conf_list,
name='cmsplugin_publisher_entry_archive_index'),
url(r'^(?P<page>[0-9]+)/$', 'entry_index', entry_conf_list,
name='cmsplugin_publisher_entry_archive_index_paginated'),
)
urlpatterns += patterns('django.views.generic.list_detail',
url(r'^(?P<slug>[-\w]+)/$', 'object_detail', entry_conf_detail,
name='cmsplugin_publisher_entry_detail'),
)
views/entries.py
from django.views.generic.list_detail import object_list
from cmsplugin_publisher.models import Entry
from cmsplugin_publisher.views.decorators import update_queryset
entry_index = update_queryset(object_list, Entry.published.all)
views/decorators.py
def update_queryset(view, queryset, queryset_parameter='queryset'):
'''Decorator around views based on a queryset passed in parameter which will force the update despite cache
Related to issue http://code.djangoproject.com/ticket/8378'''
def wrap(*args, **kwargs):
'''Regenerate the queryset before passing it to the view.'''
kwargs[queryset_parameter] = queryset()
return view(*args, **kwargs)
return wrap
The app integration with Django CMS is explained here: http://github.com/divio/django-cms/blob/master/cms/docs/app_integration.txt
It looks like the issue might be that I'm not correctly returning the RequestContext as I'm using a mis of generic views and custom in the application.
The CMS App extension py file:
cms_app.py
from django.utils.translation import ugettext_lazy as _
from cms.app_base import CMSApp
from cms.apphook_pool import apphook_pool
from cmsplugin_publisher.settings import APP_MENUS
class PublisherApp(CMSApp):
name = _('Publisher App Hook')
urls = ['cmsplugin_publisher.urls']
apphook_pool.register(PublisherApp)
Any pointers appreciated, it's proving to be a tough nut to crack!
Looks like it's a bug in the URLconf parser in Django-CMS 2.1.0beta3, which is fixed in dev. The bug only occurs when including other URLconfs from within an app.
UPDATE:
OK, I think your error originates from get_absolute_url:
#models.permalink
def get_absolute_url(self):
return ('cmsplugin_publisher_entry_detail', (), {'slug': self.slug})
I suspect it's because this ultimately calls object_detail which expects a positional parameter queryset (see django/views/generic/list_detail.py). You could try changing this to something like:
return ('cmsplugin_publisher_entry_detail', [Entry.objects.all(),], {'slug': self.slug})
I would double-check that urls/entries.py is actually being imported somewhere otherwise it won't be able to get the reverse match.

Categories

Resources