#python #django
#python #django
Вопрос:
Я использую slugify для создания слагов для URL-адресов сообщений моего блога. Чтобы принимать в пуле также неанглийские символы (греческие), я заменил метод save() Post model на метод, который включает параметр allow_unicode=True
. Однако это не может работать в области администрирования. Всякий раз, когда я пытался установить греческий символ в области администрирования, либо установив новую запись с греческим названием, либо отредактировав английскую строку существующего сообщения, форма администратора не позволяла мне сохранять. Для этого, как я обнаружил в других потоках, я должен переопределить метод save_model() в admin.py досье. Я так и сделал, но я получаю сообщение об ошибке. Теперь ошибка, которую я получаю, указывает на то, что область администратора запросила сообщение, пуля которого изменится на старый URL (на основе идентификатора), вместо URL-адреса, который я установил в urls.py .
Ошибка, которую я получаю, это либо an AttribureError at /admin/blog/post/1
(когда я редактирую фрагмент существующего сообщения), либо an AttribureError at /admin/blog/post/add
(когда я добавляю новое сообщение). И значение исключения в обоих случаях равно 'WSGIRequest' object has no attribute 'save'
Как мне настроить методы сохранения на стороне администратора для запроса URL-адресов с использованием URL-адресов slug? Заранее благодарю вас!
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(). Однако это не дало моему коду той функциональности, которую я хотел. Итак, что, по-видимому, является решением моей проблемы, так это объявить slug в моей модели как CharField вместо SlugField. В этом случае я могу даже удалить свой метод save_model(), который был причиной публикации. Теперь я проверяю, будет ли какой-либо побочный эффект от удаления SlugField. Если нет, я должен найти поток, в котором я видел это решение, чтобы отдать должное, если есть побочные эффекты, я должен восстановить SlugField и найти способ переопределить его validate_slug
класс. Вот и все, спасибо вам, ребята, за ваш ответ!
EDIT3: не заметил, что allow_unicode=True
это может быть аргументом не только для slugify()
, но и для models.SlugField()
… Так что это было для меня окончательное решение…
Комментарии:
1. добавьте полную трассировку ошибок
Ответ №1:
когда вы вызываете super()
метод, вы не должны передавать self
его в качестве параметра. Итак, вместо вашего текущего кода:
def save_model(self, request, obj, form, change):
super(PostAdmin, self).save_model(self, request, obj, form)
вы должны вызвать параметр super()
without self
в качестве параметра и добавить отсутствующий change
в конце:
def save_model(self, request, obj, form, change):
super(PostAdmin, self).save_model(request, obj, form, change)
Комментарии:
1. Ну, да, это было глупо с моей стороны. Однако мой код по-прежнему не обладает нужной мне функциональностью. Теперь нет никакой ошибки, но форма администратора по-прежнему не позволяет мне сохранять. Я даже прокомментировал
prepopulated_fields = {'slug': ('title',)}
, было ли это причиной, но я получаю приглашениеEnter a valid “slug”...
перед выполнениемobj.slug = slugify(obj.title, allow_unicode=True)
. Итак, кажется, что есть другой метод, который я должен переопределить, но я не знаю, какой.2. да, так оно и есть — всегда есть еще одна проблема во время разработки. Однако объединение этих проблем в нерелевантные вопросы с помощью комментариев на самом деле не сработает, поэтому я бы посоветовал вам открыть это как новый вопрос.