Django 1.5实现URL永久重定向及相关报错解决求助
解决Django 1.5.4中URL永久重定向的NoReverseMatch及属性错误
你遇到的两个错误根源完全一致:你的Activity模型的get_absolute_url()方法错误地返回了HttpResponseRedirect(或类似响应对象),而不是它应该返回的纯URL字符串。Django的redirect()函数和HttpResponsePermanentRedirect都需要接收字符串格式的URL,传入响应对象会直接触发内部处理逻辑出错,也就是你看到的rindex/find属性缺失错误。
第一步:修复get_absolute_url()方法
这是核心问题,必须确保这个方法返回合法的URL字符串,而非响应对象。针对你的新URL格式domain.com/team/event/01-03-2019/827,修改模型方法如下:
from django.core.urlresolvers import reverse from django.utils.dateformat import format class Activity(models.Model): # 你的模型字段(示例) date = models.DateField() id = models.AutoField(primary_key=True) def get_absolute_url(self): # 用reverse生成目标URL字符串,对应你配置的新路由name return reverse('activity_details', kwargs={ 'date_url': format(self.date, "d-m-Y"), 'activity_id': self.id })
同时确保urls.py中的新路由已正确命名:
# urls.py 中的新URL配置 urlpatterns = patterns('', # 新目标URL:domain.com/team/event/01-03-2019/827 url(r'^team/event/(?P<date_url>\d{2}-\d{2}-\d{4})/(?P<activity_id>\d+)/$', 'productions.views.activity_details', name='activity_details'), )
第二步:处理旧URL的永久重定向
现在需要让旧URL(domain.com/team/event-2019/01-03-2019/827)自动重定向到新URL,推荐两种方案:
方案1:单独配置旧URL路由和重定向视图
在urls.py中添加旧URL的路由,指向专门的重定向视图:
# urls.py urlpatterns = patterns('', # 旧URL路由:捕获年份、日期、活动ID url(r'^team/event-(?P<year>\d+)/(?P<date_url>\d{2}-\d{2}-\d{4})/(?P<activity_id>\d+)/$', 'productions.views.old_activity_redirect', name='old_activity_redirect'), # 保留新URL路由 url(r'^team/event/(?P<date_url>\d{2}-\d{2}-\d{4})/(?P<activity_id>\d+)/$', 'productions.views.activity_details', name='activity_details'), )
然后在productions/views.py中添加重定向视图:
from django.shortcuts import get_object_or_404 from django.http import HttpResponsePermanentRedirect from .models import Activity from django.utils.dateformat import format def old_activity_redirect(request, year, date_url, activity_id): # 获取对应活动实例 activity = get_object_or_404(Activity, id=activity_id) # 验证日期匹配度(可选,提升严谨性) expected_date = format(activity.date, "d-m-Y") if date_url != expected_date: # 日期不匹配时可重定向到活动列表或返回404 return HttpResponsePermanentRedirect('/team/events/') # 永久重定向到新URL return HttpResponsePermanentRedirect(activity.get_absolute_url())
方案2:在现有视图中处理旧URL判断
如果不想新增视图,可以修改现有activity_details的URL路由,允许捕获event_slug参数,然后在视图内判断是否为旧格式:
# 修改urls.py中的新URL路由: url(r'^team/(?P<event_slug>[^/]+)/(?P<date_url>\d{2}-\d{2}-\d{4})/(?P<activity_id>\d+)/$', 'productions.views.activity_details', name='activity_details'),
更新activity_details视图逻辑:
def activity_details(request, event_slug, date_url, activity_id): activity = get_object_or_404(Activity, id=activity_id) expected_date = format(activity.date, "d-m-Y") # 情况1:访问的是旧URL(slug带年份,如event-2019) if event_slug.startswith('event-'): return HttpResponsePermanentRedirect(activity.get_absolute_url()) # 情况2:访问新URL但日期不匹配 elif date_url != expected_date: return HttpResponsePermanentRedirect(activity.get_absolute_url()) # 正常执行视图逻辑(渲染模板等) # ... return render(request, 'productions/activity_details.html', {'activity': activity})
错误原因复盘
- 第一个NoReverseMatch错误:当你调用
redirect(activity.get_absolute_url())时,get_absolute_url()返回的是HttpResponseRedirect对象,而redirect()函数期望接收字符串、视图名或模型实例(内部会调用其get_absolute_url())。Django尝试把这个响应对象当作视图名去执行reverse,但响应对象没有字符串的rindex方法,因此报错。 - 第二个'find'属性错误:
HttpResponsePermanentRedirect需要接收URL字符串作为参数,你传入了HttpResponseRedirect对象,它内部处理URL时会调用字符串的find方法,响应对象没有这个方法,导致报错。
内容的提问来源于stack exchange,提问作者user9192656
相关产品推荐
相关产品推荐

