我想创建一个显示模型详细信息的DetailView页面,但是我想使用ModelFormMixin在DetailView页面中添加一个Comment部分。
这是我的views.py代码:
class PostDetailView(ModelFormMixin, DetailView):
model = UserPost
context_object_name='post_detail'
form_class = UserCommentForm
def get_context_data(self, *args, **kwargs):
context = super(PostDetailView, self).get_context_data(*args, **kwargs)
context['form'] = self.get_form()
return context
def get_absolute_url(self):
return reverse(request, 'basic_app:post_detail', kwargs={'pk':self.pk})
但是当我按下“提交”按钮时,它显示以下错误:
编辑部分:
browser image before clicking enter button
browser image after clicking enter button
很抱歉没有上传实际代码,因为上传大量代码太困难了。
答案 0 :(得分:0)
我认为以下代码将为您提供帮助。我很久以前编写了代码,但是它似乎可以解决您的问题(我没有使用taggit,所以我创建了PostTag模型):
型号:
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.utils.timezone import localtime
from django.urls import reverse
class User(AbstractUser):
pass
class PublishedManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(status='published')
class PostTag(models.Model):
name = models.CharField(max_length=40)
slug = models.SlugField(max_length=40)
def __str__(self):
return self.name
class Post(models.Model):
POST_STATUS = (('draft', 'Draft'), ('published', 'Published'))
title = models.CharField(max_length=100)
body = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='blog_posts')
created = models.DateTimeField(auto_now_add=True)
publish = models.DateTimeField(auto_now=True)
updated = models.DateTimeField(auto_now=True)
slug = models.SlugField(max_length=100, unique_for_date='publish')
status = models.CharField(max_length=10, choices=POST_STATUS, default='draft')
tags = models.ManyToManyField(PostTag, blank=True)
def get_absolute_url(self):
local_time = localtime(self.publish)
return reverse("blog:post_date_detail", args=[local_time.year, local_time.month, local_time.day, self.slug])
class Meta:
ordering = ('-publish',)
def __str__(self):
return self.title
objects = models.Manager() # The default manager.
published = PublishedManager() # Custom manager.
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
name = models.CharField(max_length=80)
email = models.EmailField()
body = models.TextField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
active = models.BooleanField(default=True)
def get_absolute_url(self):
local_time = localtime(self.post.publish)
return reverse("blog:post_date_detail", args=[local_time.year, local_time.month, local_time.day, self.post.slug])
class Meta:
ordering = ('created',)
def __str__(self):
return f'Comment by {self.name} on {self.post}'
观看次数:
from django.shortcuts import render, get_object_or_404, HttpResponseRedirect
from django.views.generic import ListView, DetailView, View
from django.views.generic.edit import FormView, SingleObjectMixin, CreateView
from django.views.generic.dates import YearArchiveView, MonthArchiveView, DateDetailView
from django.core.mail import send_mail
from django.db.models import Count
from .models import Post, User, Comment, PostTag
from .forms import EmailPostForm, CommentForm
class PostListView(ListView):
queryset = Post.published.all()
context_object_name = 'posts'
paginate_by = 4
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# si hay kwargs se actualiza el context
if self.kwargs:
context["tag"] = self.kwargs['tag_slug']
return context
def get_queryset(self):
tag = None
if self.kwargs:
tag_slug = self.kwargs['tag_slug']
tag = get_object_or_404(PostTag, slug=tag_slug)
posts = self.queryset.filter(tags__in=[tag])
return posts
return self.queryset
class PostYearArchiveView(YearArchiveView):
queryset = Post.published.all()
template_name = 'blog/post_list.html'
date_field = "publish"
context_object_name = 'posts'
make_object_list = True
paginate_by = 4
class PostMonthArchiveView(MonthArchiveView):
queryset = Post.published.all()
template_name = 'blog/post_list.html'
date_field = "publish"
context_object_name = 'posts'
month_format='%m'
paginate_by = 4
class PostDateDetailView(DateDetailView):
queryset = Post.published.all()
date_field = "publish"
month_format='%m'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
obj = self.get_object()
post_tags_pks = obj.tags.all().values_list('pk', flat=True)
related_posts = self.queryset.filter(tags__in=post_tags_pks).exclude(pk=obj.pk)
related_posts = related_posts.annotate(same_tags=Count('tags')).order_by('-same_tags','-publish')[:3]
context["related_posts"] = related_posts
comments = obj.comments.filter(active=True)
context["comments"] = comments
context['post_id'] = obj.pk
context['form'] = CommentForm()
return context
class NewComment(CreateView):
model = Comment
template_name = 'blog/post_detail.html'
form_class = CommentForm
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
post = context["form"].instance.post
context['post'] = post
post_tags_pks = post.tags.all().values_list('pk', flat=True)
related_posts = Post.published.filter(tags__in=post_tags_pks).exclude(pk=post.pk)
related_posts = related_posts.annotate(same_tags=Count('tags')).order_by('-same_tags','-publish')[:3]
context["related_posts"] = related_posts
comments = post.comments.filter(active=True)
context["comments"] = comments
return context
class PostDetail(View):
def get(self, request, *args, **kwargs):
view = PostDateDetailView.as_view()
return view(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
view = NewComment.as_view()
return view(request, *args, **kwargs)
class SharePostView(SingleObjectMixin, FormView):
form_class = EmailPostForm
template_name = 'blog/post_share.html'
success_url = '/blog'
context_object_name = 'posts'
queryset = Post.published.all()
def get(self, request, *args, **kwargs):
post = self.get_object()
context = {'post': post, 'form': self.form_class}
return render(request, self.template_name, context)
def form_valid(self, form):
post = self.get_object()
post_url = self.request.build_absolute_uri(post.get_absolute_url())
form.send_mail(post, post_url)
return super(SharePostView, self).form_valid(form)
注意事项:请参见get_context_data以将其他数据添加到上下文中:在这种情况下,标签,related_post,表单等... 我已经使用了3个视图。 DateDetailView(类似于DetailView)来显示页面(具有所需的上下文)。 CreateView管理POST方法并将注释保存到数据库中。我还添加了上下文以获取帖子信息。 最后是一个旨在管理相同URL的视图,但调用了适当的视图 当请求是GET或POST时。看到urls.py
URLS:
from django.urls import path
from blog import views
from blog.models import Post
app_name = 'blog'
urlpatterns = [
path("", views.PostListView.as_view(), name="post_list"),
path('tag/<slug:tag_slug>/', views.PostListView.as_view(), name='post_list_by_tag'),
path('<int:year>/', views.PostYearArchiveView.as_view(), name="post_year_archive"),
path('<int:year>/<int:month>/', views.PostMonthArchiveView.as_view(), name="post_month_numeric"),
path('<int:year>/<int:month>/<int:day>/<slug:slug>/', views.PostDetail.as_view(), name="post_date_detail"),
path('<int:pk>/share/', views.SharePostView.as_view(), name='post_share'),
]
评论表:
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('name', 'email', 'body', 'post')
widgets = {
'name': forms.TextInput(attrs={'placeholder': 'Name'}),
'email': forms.EmailInput(attrs={'placeholder': 'E-mail'}),
'body': forms.Textarea(attrs={'placeholder': 'Write your message here'}),
'post' : forms.HiddenInput(),
}
模板中的表单:
<form method="post" action="" novalidate>
{% csrf_token %}
<div class="input-group input-group-icon">
{{ form.name }}
<div class="input-icon"><i class="fas fa-user"></i></div>
{% if form.name.errors %}
{{form.name.errors}}
{% endif %}
</div>
<div class="input-group input-group-icon">
{{form.email }}
<div class="input-icon">
<i class="fas fa-envelope"></i>
</div>
{% if form.email.errors %}
{{form.email.errors}}
{% endif %}
</div>
<div class="msg">
<div class="input-group">{{form.body}}
{% if form.body.errors %}
{{form.body.errors}}
{% endif %}
</div>
</div>
<input type="hidden" name="post" value="{{ post.pk }}">
<div class="input-group send-reset">
<input type="submit" value="Enviar Comentario" />
</div>
</form>
注意事项:请参阅输入type = hidden以获取post.pk。这是保存comment.post字段所必需的。
我想我涵盖了您可能遇到的所有问题。希望对您有帮助!