覆盖管理员save_model方法

时间:2020-09-17 19:52:22

标签: python django

我使用slugify为我的博客文章网址创建标签。为了也可以接受非英语字符(希腊语),我用带有参数allow_unicode=True的Post模型的save()方法进行了覆盖。但是,这无法在管理区域中工作。每当我尝试通过设置带有希腊标题的新帖子或通过编辑现有帖子的英文提示在管理区域中设置希腊字符提示时,管理表单都不允许我保存。为此,正如我在其他线程中发现的那样,我应该覆盖admin.py文件中的save_model()方法。我照做了,但是我得到了一个错误。现在,我得到的错误指出,管理员区域要求该帖子的子条目将更改为旧的url(基于id的帖子),而不是我在urls.py中设置的slug-url。

我得到的错误是AttribureError at /admin/blog/post/1(当我编辑现有帖子的条目时)或AttribureError at /admin/blog/post/add(当我添加新帖子时)。两种情况下的异常值为'WSGIRequest' object has no attribute 'save'

我应该如何设置管理端保存方法以使用Slug url请求url? 预先谢谢你!

models.py:

from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse
from ckeditor.fields import RichTextField
from django.utils.text import slugify
from taggit.managers import TaggableManager

class Post(models.Model):
    title = models.CharField(max_length=100)
    content = RichTextField(blank=True, null=True)
    date_posted = models.DateTimeField(default=timezone.now)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    is_published = models.BooleanField(default=True)
    slug = models.SlugField(unique=True, max_length=100)
    tags = TaggableManager(blank=True)

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse('post-detail', kwargs={'slug': self.slug})

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.title, allow_unicode=True)
        super(Post, self).save(*args, **kwargs)

admin.py:

from django.contrib import admin
from .models import Post
from django.utils.text import slugify

class PostAdmin(admin.ModelAdmin):
    prepopulated_fields = {'slug': ('title',)}
    list_display = ('title', 'slug', 'is_published', 'author', 'date_posted')
    list_editable = ('is_published',)

    def save_model(self, request, obj, form, change):
        if not obj.slug:
            obj.slug = slugify(obj.title, allow_unicode=True)
        super(PostAdmin, self).save_model(self, request, obj, form)

admin.site.register(Post, PostAdmin)

urls.py:

from django.urls import path, register_converter, re_path
from .views import (
    PostListView,
    UserPostListView,
    PostDetailView,
    PostCreateView,
    PostUpdateView,
    PostDeleteView,
    TagIndexView
)
from django.urls.converters import SlugConverter

class CustomSlugConverter(SlugConverter): 
    regex = '[-\w]+'

register_converter(CustomSlugConverter, 'custom_slug')

urlpatterns = [
    path('front_page', PostListView.as_view(), name='blog-home'),
    path('user/<str:username>', UserPostListView.as_view(), name='user-posts'),
    re_path(r'post/(?P<slug>[\w-]+)/$', PostDetailView.as_view(), name='post-detail'),
    path('post/new/', PostCreateView.as_view(), name='post-create'),
    re_path(r'post/(?P<slug>[\w-]+)/update$', PostUpdateView.as_view(), name='post-update'),
    re_path(r'post/(?P<slug>[\w-]+)/delete$', PostDeleteView.as_view(), name='post-delete'),
    path('tag/<slug>', TagIndexView.as_view(), name='tag-posts'),
]

编辑:这是错误回溯:

Traceback (most recent call last):
  File "/home/george/PythProj/myWebsite/myws_venv/lib/python3.7/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/home/george/PythProj/myWebsite/myws_venv/lib/python3.7/site-packages/django/core/handlers/base.py", line 179, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/george/PythProj/myWebsite/myws_venv/lib/python3.7/site-packages/django/contrib/admin/options.py", line 614, in wrapper
    return self.admin_site.admin_view(view)(*args, **kwargs)
  File "/home/george/PythProj/myWebsite/myws_venv/lib/python3.7/site-packages/django/utils/decorators.py", line 130, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "/home/george/PythProj/myWebsite/myws_venv/lib/python3.7/site-packages/django/views/decorators/cache.py", line 44, in _wrapped_view_func
    response = view_func(request, *args, **kwargs)
  File "/home/george/PythProj/myWebsite/myws_venv/lib/python3.7/site-packages/django/contrib/admin/sites.py", line 233, in inner
    return view(request, *args, **kwargs)
  File "/home/george/PythProj/myWebsite/myws_venv/lib/python3.7/site-packages/django/contrib/admin/options.py", line 1656, in change_view
    return self.changeform_view(request, object_id, form_url, extra_context)
  File "/home/george/PythProj/myWebsite/myws_venv/lib/python3.7/site-packages/django/utils/decorators.py", line 43, in _wrapper
    return bound_method(*args, **kwargs)
  File "/home/george/PythProj/myWebsite/myws_venv/lib/python3.7/site-packages/django/utils/decorators.py", line 130, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "/home/george/PythProj/myWebsite/myws_venv/lib/python3.7/site-packages/django/contrib/admin/options.py", line 1534, in changeform_view
    return self._changeform_view(request, object_id, form_url, extra_context)
  File "/home/george/PythProj/myWebsite/myws_venv/lib/python3.7/site-packages/django/contrib/admin/options.py", line 1580, in _changeform_view
    self.save_model(request, new_object, form, not add)
  File "/home/george/PythProj/myWebsite/blog/admin.py", line 15, in save_model
    super(PostAdmin, self).save_model(self, request, obj, form)
  File "/home/george/PythProj/myWebsite/myws_venv/lib/python3.7/site-packages/django/contrib/admin/options.py", line 1093, in save_model
    obj.save()

Exception Type: AttributeError at /admin/blog/post/1/change/
Exception Value: 'WSGIRequest' object has no attribute 'save'

EDIT2:避免错误的解决方案当然是以正确的方式编写我的super()方法。但是,这并没有给我的代码提供我想要的功能。因此,似乎可以解决我的问题的方法是,将模型中的子段声明为CharField而不是SlugField。在那种情况下,我什至可以删除我的save_model()方法,这就是发布的原因。现在,我正在检查删除SlugField是否会有任何副作用。如果没有,我应该找到我看到的解决方案来赞扬该线程,如果有副作用,我应该恢复SlugField并找到一种方法来覆盖其validate_slug类。就这样,谢谢大家的回应!

EDIT3:没有注意到allow_unicode=True不仅可以作为slugify()的参数,而且可以作为models.SlugField()的参数...所以这对我来说是最终的解决方案... < / p>

1 个答案:

答案 0 :(得分:1)

在调用super()方法时,不应在此处传递self作为参数。因此,而不是您当前的代码:

def save_model(self, request, obj, form, change):
    super(PostAdmin, self).save_model(self, request, obj, form)

您应在不使用super()作为参数的情况下调用self,并在末尾添加缺少的change

def save_model(self, request, obj, form, change):
    super(PostAdmin, self).save_model(request, obj, form, change)