Django UpdateView AttributeError 'UserPostUpdateView' 对象没有属性 'publish'
Django UpdateView AttributeError 'UserPostUpdateView' object has no attribute 'publish'
编辑后尝试保存表单时出现错误。如果我重写 get_context_date
(当前已注释掉),加载表单时会出现错误。
我已经查看了有关此问题的文档和以前的问题。 运行 的那些人已经覆盖了 post()
而我没有。所以我不知道为什么会这样,也不知道如何解决。非常感谢任何帮助。
回溯
Traceback (most recent call last):
File "/usr/local/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/usr/local/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python3.8/site-packages/django/views/generic/base.py", line 70, in view
return self.dispatch(request, *args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/django/contrib/auth/mixins.py", line 71, in dispatch
return super().dispatch(request, *args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/django/views/generic/base.py", line 98, in dispatch
return handler(request, *args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/django/views/generic/edit.py", line 194, in post
return super().post(request, *args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/django/views/generic/edit.py", line 142, in post
return self.form_valid(form)
File "/code/mysite/create/views.py", line 22, in form_valid
return super().form_valid(form)
File "/usr/local/lib/python3.8/site-packages/django/views/generic/edit.py", line 126, in form_valid
return super().form_valid(form)
File "/usr/local/lib/python3.8/site-packages/django/views/generic/edit.py", line 57, in form_valid
return HttpResponseRedirect(self.get_success_url())
File "/code/mysite/create/views.py", line 25, in get_success_url
return reverse_lazy("create:user_post_detail", kwargs={"year": self.publish.year, "month": self.publish.month, "day": self.publish.day, "slug": self.slug})
Exception Type: AttributeError at /create/my_collideas/2021/7/28/title-2-by-user2/edit/
Exception Value: 'UserPostUpdateView' object has no attribute 'publish'
#models.py
from django.core.validators import MinValueValidator
from django.db import models
from django.urls import reverse
from django.utils import timezone
from django.utils.text import slugify
from ckeditor.fields import RichTextField
import sys
sys.path.append("..") # Adds higher directory to python modules path.
from userauth.models import CustomUser
class UserPost(models.Model):
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
publish = models.DateField(default=timezone.now, validators=[MinValueValidator(timezone.now().date(), message="The date cannot be in the past!")])
created = models.DateTimeField(auto_now_add=True, editable=False)
updated = models.DateTimeField(auto_now=True, editable=False)
STATUS_CHOICES = (
('draft', 'Draft'),
('published', 'Published'),
)
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default="draft")
active = models.BooleanField(default=True, help_text="Allows moderator to unpublish posts if set to false") # Allows moderators to hide offensive posts
inactive_message = models.TextField(max_length=500, blank=True, help_text="Enter the reason for setting this post to inactive")
title = models.CharField(max_length=300, unique_for_date="publish", help_text="You must enter a title")
slug = models.SlugField(max_length=350, unique_for_date="publish")
content = RichTextField(config_name='awesome_ckeditor', help_text="You must enter some content")
def save(self, *args, **kwargs):
if not self.id:
# Newly created object, so set slug
self.slug = slugify(self.title)
return super(UserPost, self).save(*args, **kwargs)
def get_absolute_url(self):
return reverse("create:detail", kwargs={"year": self.publish.year, "month": self.publish.month, "day": self.publish.day, "slug": self.slug})
def __str__(self):
return self.title
class Meta:
verbose_name = "User Post"
verbose_name_plural = "User Posts"
ordering = ("-publish",)
#views.py
from django.forms import DateInput
from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse_lazy
from django.utils import timezone
from django.views.generic import ListView, DetailView
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from .models import UserPost
class OwnerMixin(object):
"""Returns only user's objects to prevent others from accessing."""
def get_queryset(self):
qs = super().get_queryset()
return qs.filter(user=self.request.user)
class OwnerEditMixin(object):
"""Sets user pk"""
def form_valid(self, form):
form.instance.user = self.request.user
return super().form_valid(form)
def get_success_url(self):
return reverse_lazy("create:user_post_detail", kwargs={"year": self.publish.year, "month": self.publish.month, "day": self.publish.day, "slug": self.slug})
class UserPostCreateView(LoginRequiredMixin, OwnerEditMixin ,CreateView):
model = UserPost
fields = ["publish", "status", "title", "content"]
template_name = "create/post.html"
def get_form(self):
form = super().get_form()
form.fields['publish'].widget = DateInput(attrs={'type': 'date'})
return form
class UserPostUpdateView(LoginRequiredMixin, OwnerMixin, OwnerEditMixin, UpdateView):
model = UserPost
fields = ["publish", "status", "title", "content"]
template_name = "create/post_edit.html"
def get_form(self):
form = super().get_form()
form.fields['publish'].widget = DateInput(attrs={'type': 'date'})
return form
# def get_context_data(self, **kwargs):
# context = super().get_context_data(**kwargs)
# context['publish'] = self.publish
# return context
class PostList(ListView):
"""Landing page for create app. Shows list of posts."""
model = UserPost
paginate_by = 2
context_object_name = "post_list"
template_name = "create/post_list.html"
def get_queryset(self):
"""Return published posts (not including those set to be published in the future)."""
return UserPost.objects.filter(publish__lte=timezone.now(), active=True, status="published").order_by('-publish')
class PostListByUser(ListView):
"""Shows list of posts by user"""
model = UserPost
paginate_by = 2
context_object_name = "post_list"
template_name = "create/post_list_by_user.html"
def get_queryset(self):
"""Return published posts (not including those set to be published in the future or active=false)."""
return UserPost.objects.filter(user__slug=self.kwargs['slug'], publish__lte=timezone.now(), active=True, status="published").order_by('-publish')
class PostDetail(DetailView):
"""Shows post detail."""
model = UserPost
context_object_name = "post_detail"
template_name = "create/post_detail.html"
# slug_url_kwarg = "slug"
def get_queryset(self):
"""Return published post (not including those set to be published in the future or active=false)."""
return UserPost.objects.filter(publish__lte=timezone.now(), active=True, status="published")
class UserPostList(LoginRequiredMixin, OwnerMixin, ListView):
"""Shows post list to user even if it is draft or unpublished"""
model = UserPost
context_object_name = "user_post_detail"
template_name = "create/user_post_list.html"
class UserPostDetail(LoginRequiredMixin, OwnerMixin, DetailView):
"""Shows post detail to user even if it is draft or unpublished"""
model = UserPost
context_object_name = "user_post_detail"
template_name = "create/user_post_detail.html"
class UserPostDeleteView(LoginRequiredMixin, OwnerMixin, DeleteView):
model = UserPost
template_name = "create/delete.html"
def get_success_url(self, *args, **kwargs):
return reverse_lazy('create:user_post_list', args=[self.kwargs['slug']])
#urls.py
from django.urls import path
from .views import PostList, PostListByUser, PostDetail, UserPostCreateView, UserPostList, UserPostDetail, UserPostUpdateView, UserPostDeleteView
# Refer to https://docs.djangoproject.com/en/3.2/intro/tutorial04/#amend-urlconf
app_name = "create"
urlpatterns = [
path("collideas/", PostList.as_view(), name="index"),
path("collideas/<slug:slug>", PostListByUser.as_view(), name="posts_by_user"),
path("my_collidea/", UserPostCreateView.as_view(), name="post"),
path("my_collideas/", UserPostList.as_view(), name="user_post_list"),
path("my_collideas/<int:year>/<int:month>/<int:day>/<slug:slug>/", UserPostDetail.as_view(), name="user_post_detail"),
path("collideas/<int:year>/<int:month>/<int:day>/<slug:slug>/", PostDetail.as_view(), name="detail"),
path("my_collideas/<int:year>/<int:month>/<int:day>/<slug:slug>/edit/", UserPostUpdateView.as_view(), name="edit"),
path("my_collideas/<int:year>/<int:month>/<int:day>/<slug:slug>/delete/", UserPostDeleteView.as_view(), name="delete"),
]
self
指的是视图,而不是对象,因此您应该使用:
class OwnerEditMixin(object):
# …
def get_success_url(self):
return reverse_lazy(
'create:user_post_detail',
kwargs={
# ↓ use self.object
'year': self.<strong>object</strong>.publish.year,
'month': self.<strong>object</strong>.publish.month,
'day': self.<strong>object</strong>.publish.day,
'slug': self.<strong>object</strong>.slug
}
编辑后尝试保存表单时出现错误。如果我重写 get_context_date
(当前已注释掉),加载表单时会出现错误。
我已经查看了有关此问题的文档和以前的问题。 运行 的那些人已经覆盖了 post()
而我没有。所以我不知道为什么会这样,也不知道如何解决。非常感谢任何帮助。
回溯
Traceback (most recent call last):
File "/usr/local/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/usr/local/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python3.8/site-packages/django/views/generic/base.py", line 70, in view
return self.dispatch(request, *args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/django/contrib/auth/mixins.py", line 71, in dispatch
return super().dispatch(request, *args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/django/views/generic/base.py", line 98, in dispatch
return handler(request, *args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/django/views/generic/edit.py", line 194, in post
return super().post(request, *args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/django/views/generic/edit.py", line 142, in post
return self.form_valid(form)
File "/code/mysite/create/views.py", line 22, in form_valid
return super().form_valid(form)
File "/usr/local/lib/python3.8/site-packages/django/views/generic/edit.py", line 126, in form_valid
return super().form_valid(form)
File "/usr/local/lib/python3.8/site-packages/django/views/generic/edit.py", line 57, in form_valid
return HttpResponseRedirect(self.get_success_url())
File "/code/mysite/create/views.py", line 25, in get_success_url
return reverse_lazy("create:user_post_detail", kwargs={"year": self.publish.year, "month": self.publish.month, "day": self.publish.day, "slug": self.slug})
Exception Type: AttributeError at /create/my_collideas/2021/7/28/title-2-by-user2/edit/
Exception Value: 'UserPostUpdateView' object has no attribute 'publish'
#models.py
from django.core.validators import MinValueValidator
from django.db import models
from django.urls import reverse
from django.utils import timezone
from django.utils.text import slugify
from ckeditor.fields import RichTextField
import sys
sys.path.append("..") # Adds higher directory to python modules path.
from userauth.models import CustomUser
class UserPost(models.Model):
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
publish = models.DateField(default=timezone.now, validators=[MinValueValidator(timezone.now().date(), message="The date cannot be in the past!")])
created = models.DateTimeField(auto_now_add=True, editable=False)
updated = models.DateTimeField(auto_now=True, editable=False)
STATUS_CHOICES = (
('draft', 'Draft'),
('published', 'Published'),
)
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default="draft")
active = models.BooleanField(default=True, help_text="Allows moderator to unpublish posts if set to false") # Allows moderators to hide offensive posts
inactive_message = models.TextField(max_length=500, blank=True, help_text="Enter the reason for setting this post to inactive")
title = models.CharField(max_length=300, unique_for_date="publish", help_text="You must enter a title")
slug = models.SlugField(max_length=350, unique_for_date="publish")
content = RichTextField(config_name='awesome_ckeditor', help_text="You must enter some content")
def save(self, *args, **kwargs):
if not self.id:
# Newly created object, so set slug
self.slug = slugify(self.title)
return super(UserPost, self).save(*args, **kwargs)
def get_absolute_url(self):
return reverse("create:detail", kwargs={"year": self.publish.year, "month": self.publish.month, "day": self.publish.day, "slug": self.slug})
def __str__(self):
return self.title
class Meta:
verbose_name = "User Post"
verbose_name_plural = "User Posts"
ordering = ("-publish",)
#views.py
from django.forms import DateInput
from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse_lazy
from django.utils import timezone
from django.views.generic import ListView, DetailView
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from .models import UserPost
class OwnerMixin(object):
"""Returns only user's objects to prevent others from accessing."""
def get_queryset(self):
qs = super().get_queryset()
return qs.filter(user=self.request.user)
class OwnerEditMixin(object):
"""Sets user pk"""
def form_valid(self, form):
form.instance.user = self.request.user
return super().form_valid(form)
def get_success_url(self):
return reverse_lazy("create:user_post_detail", kwargs={"year": self.publish.year, "month": self.publish.month, "day": self.publish.day, "slug": self.slug})
class UserPostCreateView(LoginRequiredMixin, OwnerEditMixin ,CreateView):
model = UserPost
fields = ["publish", "status", "title", "content"]
template_name = "create/post.html"
def get_form(self):
form = super().get_form()
form.fields['publish'].widget = DateInput(attrs={'type': 'date'})
return form
class UserPostUpdateView(LoginRequiredMixin, OwnerMixin, OwnerEditMixin, UpdateView):
model = UserPost
fields = ["publish", "status", "title", "content"]
template_name = "create/post_edit.html"
def get_form(self):
form = super().get_form()
form.fields['publish'].widget = DateInput(attrs={'type': 'date'})
return form
# def get_context_data(self, **kwargs):
# context = super().get_context_data(**kwargs)
# context['publish'] = self.publish
# return context
class PostList(ListView):
"""Landing page for create app. Shows list of posts."""
model = UserPost
paginate_by = 2
context_object_name = "post_list"
template_name = "create/post_list.html"
def get_queryset(self):
"""Return published posts (not including those set to be published in the future)."""
return UserPost.objects.filter(publish__lte=timezone.now(), active=True, status="published").order_by('-publish')
class PostListByUser(ListView):
"""Shows list of posts by user"""
model = UserPost
paginate_by = 2
context_object_name = "post_list"
template_name = "create/post_list_by_user.html"
def get_queryset(self):
"""Return published posts (not including those set to be published in the future or active=false)."""
return UserPost.objects.filter(user__slug=self.kwargs['slug'], publish__lte=timezone.now(), active=True, status="published").order_by('-publish')
class PostDetail(DetailView):
"""Shows post detail."""
model = UserPost
context_object_name = "post_detail"
template_name = "create/post_detail.html"
# slug_url_kwarg = "slug"
def get_queryset(self):
"""Return published post (not including those set to be published in the future or active=false)."""
return UserPost.objects.filter(publish__lte=timezone.now(), active=True, status="published")
class UserPostList(LoginRequiredMixin, OwnerMixin, ListView):
"""Shows post list to user even if it is draft or unpublished"""
model = UserPost
context_object_name = "user_post_detail"
template_name = "create/user_post_list.html"
class UserPostDetail(LoginRequiredMixin, OwnerMixin, DetailView):
"""Shows post detail to user even if it is draft or unpublished"""
model = UserPost
context_object_name = "user_post_detail"
template_name = "create/user_post_detail.html"
class UserPostDeleteView(LoginRequiredMixin, OwnerMixin, DeleteView):
model = UserPost
template_name = "create/delete.html"
def get_success_url(self, *args, **kwargs):
return reverse_lazy('create:user_post_list', args=[self.kwargs['slug']])
#urls.py
from django.urls import path
from .views import PostList, PostListByUser, PostDetail, UserPostCreateView, UserPostList, UserPostDetail, UserPostUpdateView, UserPostDeleteView
# Refer to https://docs.djangoproject.com/en/3.2/intro/tutorial04/#amend-urlconf
app_name = "create"
urlpatterns = [
path("collideas/", PostList.as_view(), name="index"),
path("collideas/<slug:slug>", PostListByUser.as_view(), name="posts_by_user"),
path("my_collidea/", UserPostCreateView.as_view(), name="post"),
path("my_collideas/", UserPostList.as_view(), name="user_post_list"),
path("my_collideas/<int:year>/<int:month>/<int:day>/<slug:slug>/", UserPostDetail.as_view(), name="user_post_detail"),
path("collideas/<int:year>/<int:month>/<int:day>/<slug:slug>/", PostDetail.as_view(), name="detail"),
path("my_collideas/<int:year>/<int:month>/<int:day>/<slug:slug>/edit/", UserPostUpdateView.as_view(), name="edit"),
path("my_collideas/<int:year>/<int:month>/<int:day>/<slug:slug>/delete/", UserPostDeleteView.as_view(), name="delete"),
]
self
指的是视图,而不是对象,因此您应该使用:
class OwnerEditMixin(object):
# …
def get_success_url(self):
return reverse_lazy(
'create:user_post_detail',
kwargs={
# ↓ use self.object
'year': self.<strong>object</strong>.publish.year,
'month': self.<strong>object</strong>.publish.month,
'day': self.<strong>object</strong>.publish.day,
'slug': self.<strong>object</strong>.slug
}