我买了并正在阅读Django的两本书:Django 1.5的最佳实践,其中有一个基于类的视图示例。在此实现之后,我在提交表单后收到错误。
ImproperlyConfigured at /NonProfitCreate/
No URL to redirect to. Either provide a url or define a get_absolute_url method on the Model
做研究我遇到了这个问题Django - Class Based Generic View - "No URL to redirect to"
我希望get_absolute_url在我的程序中运行
这是我的forms.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# npp/forms.py
from django import forms
from .models import NonProfit
class NonProfitCreateForm(forms.ModelForm):
class Meta:
model = NonProfit
fields = ("name","contact_name","email","phone","address","image","tags",)
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
return super(NonProfitCreateForm, self).__init__(*args, **kwargs)
def save(self, *args, **kwargs):
kwargs['commit']=False
obj = super(NonProfitCreateForm, self).save(*args, **kwargs)
if self.request:
obj.user = self.request.user
obj.save()
class NonProfitUpdateForm(NonProfitCreateForm):
class Meta:
model = NonProfit
这是我的models.py和views文件
from django.db import models
from django.contrib.auth.models import User
from django.db.models import permalink
from django_extensions.db.fields import AutoSlugField
from django.contrib import admin
from django.core.urlresolvers import reverse
import tagging
from tagging.models import Tag
# Create your models here.
''' this is for the Non-Profit Proccess '''
class NonProfit (models.Model):
User = models.ForeignKey(User)
name = models.CharField(max_length=100)
contact_name = models.CharField(max_length=100)
email = models.EmailField(max_length=75)
phone = models.CharField(max_length=20)
address = models.TextField(max_length=3000)
image = models.ImageField(upload_to='photos/%Y/%m/%d',blank=True)
slug = models.SlugField(max_length=128)
slug = AutoSlugField(('slug'), max_length=128, unique=True, populate_from=('name',))
tags = tagging.fields.TagField()
def get_absolute_url(self):
return reverse("npp/nonprofit_detail", kwargs={"slug": self.slug})
def __unicode__(self):
return self.name
def get_tags(self):
return Tag.objects.get_for_object(self)
# Create your views here.
# Auction/npp/views.py
from Auction.views import ActionMixin
from django.contrib import messages
from django.views.generic import CreateView, UpdateView, DetailView
from braces.views import LoginRequiredMixin
from forms import NonProfitCreateForm,NonProfitUpdateForm
from models import NonProfit
class NonProfitCreateView(LoginRequiredMixin,ActionMixin,CreateView):
model = NonProfit
action = "created"
form_class = NonProfitCreateForm
class NonProfitUpdateView(LoginRequiredMixin,ActionMixin,UpdateView):
model = NonProfit
action = "updated"
form_class = NonProfitUpdateForm
class NonProfitDetailView(DetailView):
model = NonProfit
# Auction/views.py
class ActionMixin(object):
@property
def action(self):
msg = "{0} is missing action.".format(self.__class__)
raise NotImplementedError(msg)
def form_valid(self, form):
msg = "{0}!".format(self.action)
messages.info(self.request, msg)
return super(ActionMixin, self).form_valid(form)
urls.py
url(
regex=r'^NonProfitCreate/',
view=NonProfitCreateView.as_view(),
name='NonProfitCreate',
),
url(
regex=r'^NonProfit/(?P<slug>[-\w\d]+)/',
view=NonProfitDetailView.as_view(),
name='NonProfit'
)
这是我的堆栈跟踪,django大括号突出显示,
/home/talisman/projects/Auction/Auction/views.py in form_valid
return super(ActionMixin, self).form_valid(form)
EEnvironment:
Request Method: POST
Request URL: http://127.0.0.1:8000/NonProfitCreate/
Django Version: 1.5.1
Python Version: 2.7.4
Installed Applications:
('django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.admin',
'django.contrib.admindocs',
'django.contrib.comments',
'django.contrib.sitemaps',
'zinnia',
'tagging',
'mptt',
'south',
'misc',
'adm',
'registration',
'npp',
'blogs')
Installed Middleware:
('django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware')
Traceback:
File "/home/talisman/virt_env/Auction/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/core/handlers/base.py" in get_response
115. response = callback(request, *callback_args, **callback_kwargs)
File "/home/talisman/virt_env/Auction/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/views/generic/base.py" in view
68. return self.dispatch(request, *args, **kwargs)
File "/home/talisman/virt_env/Auction/local/lib/python2.7/site-packages/django_braces-1.0.0-py2.7.egg/braces/views.py" in dispatch
98. **kwargs)
File "/home/talisman/virt_env/Auction/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/views/generic/base.py" in dispatch
86. return handler(request, *args, **kwargs)
File "/home/talisman/virt_env/Auction/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/views/generic/edit.py" in post
199. return super(BaseCreateView, self).post(request, *args, **kwargs)
File "/home/talisman/virt_env/Auction/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/views/generic/edit.py" in post
165. return self.form_valid(form)
File "/home/talisman/projects/auction/Auction/views.py" in form_valid
54. return super(ActionMixin, self).form_valid(form)
File "/home/talisman/virt_env/Auction/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/views/generic/edit.py" in form_valid
128. return super(ModelFormMixin, self).form_valid(form)
File "/home/talisman/virt_env/Auction/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/views/generic/edit.py" in form_valid
65. return HttpResponseRedirect(self.get_success_url())
File "/home/talisman/virt_env/Auction/local/lib/python2.7/site-packages/Django-1.5.1-py2.7.egg/django/views/generic/edit.py" in get_success_url
119. "No URL to redirect to. Either provide a url or define"
Exception Type: ImproperlyConfigured at /NonProfitCreate/
Exception Value: No URL to redirect to. Either provide a url or define a get_absolute_url method on the Model.
答案 0 :(得分:10)
由于self.object = None
在有效编辑后尝试重定向时产生此异常。由于self.object
的值是form.save()
调用的结果,因此出现此错误的最可能原因是您已覆盖save()
中的NonProfitCreateForm
方法,但忘记了返回保存的对象。
Form.save()
方法应返回已保存的对象,不应为None
。
您的NonProfitCreateForm
可以修改如下:
class NonProfitCreateForm(forms.ModelForm):
...
def save(self, *args, **kwargs):
kwargs['commit']=False
obj = super(NonProfitCreateForm, self).save(*args, **kwargs)
if self.request:
obj.user = self.request.user
obj.save()
return obj #<--- Return saved object to caller.
save()
方法的前两行将根据输入的表单数据创建一个模型实例。但是因为commit=False
,对象将不保存到数据库中。如果表单实例中不存在self.request
,则返回的对象将没有数据库主键,get_absolute_url
仍将失败。
因此,您希望确保在实例化时始终将request
参数传递给表单。默认情况下不会发生这种情况,因此您需要安排视图代码以使用request
参数实例化表单。
查看code for FormMixin
,您可以看到有get_form_kwargs
函数确定传递给任何实例化表单的参数。您需要传递request=self.request
,因此在您的视图中覆盖get_form_kwargs
以添加所需的参数,如下所示:
class NonProfitCreateView(LoginRequiredMixin,ActionMixin,CreateView):
model = NonProfit
action = "created"
form_class = NonProfitCreateForm
def get_form_kwargs(self):
# Ensure the current `request` is provided to NonProfitCreateForm.
kwargs = super(NonProfitCreateView, self).get_form_kwargs()
kwargs.update({ 'request': self.request })
return kwargs
使用修改后的CreateView
函数创建get_form_kwargs
的子类可能是一个更好的主意,并让您的NonProfitCreateView
派生自子类。
答案 1 :(得分:3)
使用reverse
时,请使用您要反转的网址格式的名称。
您希望重定向到此网址:
url(
regex=r'^NonProfit/(?P<slug>[-\w\d]+)/',
view=NonProfitDetailView.as_view(),
name='NonProfit'
)
因此,您的get_absolute_url
方法应为:
def get_absolute_url(self):
return reverse("NonProfit", kwargs={"slug": self.slug})
答案 2 :(得分:1)
尝试从@permalink
方法中删除get_absolute_url
装饰器。它无法与reverse
一起使用。
此外,Django documentation声明如下:
不再推荐使用
permalink
装饰器。您应该在reverse()
方法的正文中使用get_absolute_url
。
答案 3 :(得分:1)
您可以覆盖基于类的视图的get_success_url
函数。像这样:
def get_success_url(self):
return reverse("NonProfit", kwargs={"slug": self.object.slug})
答案 4 :(得分:0)
在阅读Austin Phillips的第一句后解决了该问题:
def form_valid(self, form):
article = form.save(commit=False)
article.author = self.request.user
self.object = article.save()
return super().form_valid(form)
关键是将保存article.save()
的结果返回到self.object