Home > other >  Django / How to refer to a specific news in views so that it is possible to leave a comment on the s
Django / How to refer to a specific news in views so that it is possible to leave a comment on the s

Time:08-15

When submitting a form on the site, the "news_id" value is not pulled into the database (into the table with comments). Accordingly, it is not clear to which news a comment was left so that it could be published later.

There are Russian symbols in the code, but they do not affect the essence of the problem in any way.

models:

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"]

forms:

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

views:

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 >
        {% with news.comments_news.count as comments %}
          <p>
            <h3>Комментарии ({{ comments }})</h3>
          </p>
        {% endwith %}
      </div>
      <div >
        {% 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  method="POST">
        {% csrf_token %}
        <div >{{ form.non_field_errors }}</div>
        {% for f in form %}
          <p>
            <label >{{ f.label }}:</label>
            {{ f }}
          </p>
          <div >{{ f.errors }}</div>
        {% endfor %}
        <div>
          <button type="submit"  onclick="alert('Ваш комментарий отправлен на проверку.')">Отправить</button>
        </div>
      </form>
      {% endif %}

I understand that you need to somehow get the News model object in the views file, but all the methods that I found were not successful.

CodePudding user response:

You are not providing News object or id in neither views nor html form. Add 'news' to fields of the comment and proper input to html form:

# forms

class Meta:
    model = Comments
    fields = ['content', 'news']

# html

<form  method="POST">
    {% csrf_token %}
    <input id="news_id" name="news_id" value="{{ news.id }}" type="hidden">
    ...

CodePudding user response:

The result was the following:

<div >
  {% 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  method="POST">
  {% csrf_token %}
  <input id="id_news" name="news" value="{{ news.id }}" type="hidden">
  <div >{{ form.non_field_errors }}</div>
  <p>
    <label >{{ form.content.label }}:</label>
    {{ form.content }}
  </p>
  <div >{{ form.content.errors }}</div>
  <div>
    <button type="submit"  onclick="alert('Ваш комментарий отправлен на проверку.')">Отправить</button>
  </div>
</form>
  • Related