簡體   English   中英

基於Django類的視圖,get_absolute_url無法正常工作

[英]Django Class Based Views, get_absolute_url not working

我買了並且正在閱讀Django的Book Two Scoops: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 - 基於類的通用視圖 - “沒有重定向到的URL”

我希望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.

生成此異常是因為在有效編輯后嘗試重定向時self.object = None 由於self.object的值是form.save()調用的結果,因此出現此錯誤的最可能原因是您已在NonProfitCreateForm重寫了save()方法,但忘記返回已保存的對象。

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參數實例化表單。

查看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從子類派生。

使用reverse ,請使用要reverse的url模式的名稱。

您希望重定向到此網址:

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})  

嘗試從get_absolute_url方法中刪除@permalink裝飾器。 它不能與reverse一起工作。

此外, Django文檔聲明如下:

不再推薦permalink裝飾器。 您應該在get_absolute_url方法的主體中使用reverse()

您可以覆蓋基於類的視圖的get_success_url函數。 像這樣:

def get_success_url(self):
    return reverse("NonProfit", kwargs={"slug": self.object.slug})  

閱讀奧斯汀菲利普斯的第一句話后解決了這個問題:

    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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM