I created a model comments and it was easy to display comments at the bot of post , but how am I suppose to make a form to add comment in same page as art_detail
.
I mean I have to use a CreateView
but ArtDetailView()
uses DetailView
so i cant put both in one view, and when i put them i separated views only one of views send data to template
model:
class Comment(models.Model):
writer = models.ForeignKey(get_user_model(),on_delete=models.CASCADE)
art = models.ForeignKey(Art,on_delete=models.CASCADE)
text = models.TextField(max_length=500)
date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.writer.username
views:
class CommentView(CreateView):
model = Comment
template_name = 'art_detail.html'
fields = ['text']
def form_valid(self, form):
form.instance.art = Art.objects.get(id=self.id)
form.instance.writer = self.request.user
return super().form_valid(form)
class ArtDetailView(DetailView):
model = Art
template_name = 'art_detail.html'
to handle this comments idk even if i need a url
or not ?
can you please help with this problem
CodePudding user response:
You can create a form and use it by mixing both views like this :
class ArtDetailView(FormView, DetailView):
model = Art
form_class = CommentForm
def get_context_data(self, **kwargs):
context = super(ArtDetailView, self).get_context_data(**kwargs)
context['form'] = self.get_form()
return context
def post(self, request, *args, **kwargs):
return FormView.post(self, request, *args, **kwargs)
CodePudding user response:
CBV and FBV can achieve the same results, however seeing them in FBV can help you understand your view more than CBV. Below is an example of how you would apply this in a a FBV:
views.py
def post(request, pk):
form = CommentForm()
post = Post.objects.get(id=pk)
if request.method == "POST":
form = CommentForm(request.POST)
if form.is_valid():
comment = form.cleaned_data['comment']
comment = form.save(commit=False)
comment.post = post
comment.save()
return redirect('post_page', id=post.pk)
else:
return render(request, 'post_page.html', {'post': post, 'form':form})
return render(request, 'post_page.html', {'post': post, 'form':form})
models.py
class Post(models.Model):
post_title = models.CharField(max_length=200, null=True, blank=True)
post_description = models.CharField(max_length=200, null=True, blank=True)
post_complete = models.TextField(max_length=2000, null=True, blank=True)
class Comment(models.Model):
comment = models.CharField(null=True, blank=False, max_length=500, verbose_name="Comment")
commentor = models.CharField(max_length=50)
post_related = models.ForeignKey(Post, related_name="comments", on_delete=models.CASCADE, null=True)
forms.py
class CommentForm(forms.ModelForm):
commentor = forms.CharField(max_length = 40, label = False, required = True,error_messages={'required': 'Name is required'},
widget=forms.TextInput(attrs={
'oninvalid': "this.setCustomValidity('Name is required')",
'onchange': "this.setCustomValidity('')",
'class': 'form-control', 'placeholder': 'Name:'}))
comment = forms.CharField(max_length = 500, label = False, required = True,error_messages={'required': 'Comment is required'},
widget=forms.Textarea(attrs={
'oninvalid': "this.setCustomValidity('Comment is required')",
'onchange': "this.setCustomValidity('')",
'class': 'form-control', 'placeholder': 'Comment:'}))
class Meta:
model = Comment
fields = ['name','comment']
post_page.html (page that includes both post and related comments)
{{post.title}}
{{post.description}}
{{post.complete}}
{% for comment in post.comments.all %}
{{comment.commentor}}
{{comment.comment}}
{% endfor %}
urls.py
path('post_page/<pk>/', views.post, name='post_page'),
When linking to the post, make sure to add post.pk in href
Hope this helps