Django / Как ссылаться на конкретную новость в просмотрах, чтобы можно было оставить комментарий на сайте через форму?
При отправке формы на сайте значение "news_id" не подтягивается в базу данных (в таблицу с комментариями). Соответственно, не понятно, к какой новости был оставлен комментарий, чтобы потом его опубликовать.
В коде присутствуют русские символы, но они никак не влияют на суть проблемы.
модели:
class News(models.Model):
title = models.CharField(max_length=255, verbose_name="Заголовок")
slug = models.CharField(max_length=255, unique=True, db_index=True, verbose_name="URL")
content = models.TextField(verbose_name="Содержимое")
photo = models.ImageField(upload_to="news/%Y/%m/%d/", verbose_name="Изображение")
video = models.URLField(max_length=255, blank=True, null=True, verbose_name="Ссылка на видео")
time_update = models.DateTimeField(auto_now=True, verbose_name="Время изменения")
category = models.ForeignKey("NewsCategories", on_delete=models.PROTECT, verbose_name="Категория")
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("show_news", kwargs={"news_slug": self.slug})
class Meta:
verbose_name = "Новость"
verbose_name_plural = "Новости"
ordering = ["-time_update"]
class Comments(models.Model):
news = models.ForeignKey(
News,
on_delete=models.CASCADE,
related_name='comments_news',
verbose_name="Новость"
)
user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="Автор комментария")
time_create = models.DateTimeField(auto_now_add=True, verbose_name="Время создания")
content = models.TextField(verbose_name="Содержимое")
status = models.BooleanField(verbose_name="Публикация комментария", default=False)
def __str__(self):
return self.content
class Meta:
verbose_name = "Комментарий"
verbose_name_plural = "Комментарии"
ordering = ["-time_create"]
Формы:
class CommentForm(forms.ModelForm):
content = forms.CharField(
label='Добавить комментарий',
widget=forms.Textarea(attrs={'rows': '4', 'class': 'form-control'}))
class Meta:
model = Comments
fields = ['content']
utils:
class DataMixin:
def get_user_context(self, **kwargs):
context = kwargs
cats = NewsCategories.objects.annotate(Count('news'))
context["cats"] = cats
if "category_selected" not in context:
context["category_selected"] = 0
return context
просмотров:
class ShowNews(DataMixin, DetailView, FormView):
model = News
template_name = "main_app/show_news.html"
slug_url_kwarg = "news_slug"
context_object_name = "news"
form_class = CommentForm
def get_context_data(self, *, object_list=None, **kwargs):
context = super().get_context_data(**kwargs)
c_def = self.get_user_context(title=context["news"])
return dict(list(context.items()) + list(c_def.items()))
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.user = request.user
comment.save()
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
return render(request, self.template_name, self.get_context_data())
html:
<div class="col-md-10 offset-md-1">
{% with news.comments_news.count as comments %}
<p>
<h3>Комментарии ({{ comments }})</h3>
</p>
{% endwith %}
</div>
<div class="col-md-10 offset-md-1 bg-white rounded-start-top-0 p-3 rounded">
{% for comment in news.comments_news.all %}
<p>{{ comment.user }} написал(а) {{ comment.time_create }}</p>
{{ comment.content|linebreaks }}
<hr>
{% endfor %}
</div>
{% if user.is_authenticated %}
<form class="col-md-10 offset-md-1" method="POST">
{% csrf_token %}
<div class="form-error">{{ form.non_field_errors }}</div>
{% for f in form %}
<p>
<label class="form-label">{{ f.label }}:</label>
{{ f }}
</p>
<div class="form-error">{{ f.errors }}</div>
{% endfor %}
<div>
<button type="submit" class="btn btn-color" onclick="alert('Ваш комментарий отправлен на проверку.')">Отправить</button>
</div>
</form>
{% endif %}
Я понимаю, что нужно как-то получить объект модели News в файле views, но все методы, которые я нашел, не принесли успеха.
Простите :( за мой английский, я не носитель языка :)
Вы не предоставляете News
объект или id ни в представлениях, ни в html-форме. Добавьте 'news'
в поля комментария и правильный ввод в html-форму:
# forms
class Meta:
model = Comments
fields = ['content', 'news']
# html
<form class="col-md-10 offset-md-1" method="POST">
{% csrf_token %}
<input id="news_id" name="news_id" value="{{ news.id }}" type="hidden">
...
Результат был следующим:
<div class="col-md-10 offset-md-1 bg-white rounded-start-top-0 p-3 rounded">
{% for comment in news.comments_news.all %}
{% if comment.status == True %}
<p>{{ comment.user }} написал(а) {{ comment.time_create }}</p>
{{ comment.content|linebreaks }}
<hr>
{% endif %}
{% endfor %}
</div>
{% if user.is_authenticated %}
<form class="col-md-10 offset-md-1" method="POST">
{% csrf_token %}
<input id="id_news" name="news" value="{{ news.id }}" type="hidden">
<div class="form-error">{{ form.non_field_errors }}</div>
<p>
<label class="form-label">{{ form.content.label }}:</label>
{{ form.content }}
</p>
<div class="form-error">{{ form.content.errors }}</div>
<div>
<button type="submit" class="btn btn-color" onclick="alert('Ваш комментарий отправлен на проверку.')">Отправить</button>
</div>
</form>