# UpdateView in a modal window

**URL:** <https://forum.djangoproject.com/t/updateview-in-a-modal-window/22212>\
**Category:** Forms & APIs\
**Created:** [July 11, 2023, 9:14am UTC](https://forum.djangoproject.com/t/updateview-in-a-modal-window/22212 "2023-07-11T09:14:55Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![ponponmaru1012](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/ponponmaru1012/32/14737_2.png) [@ponponmaru1012](https://forum.djangoproject.com/u/ponponmaru1012)\
**Post date:** [July 11, 2023, 9:14am UTC](https://forum.djangoproject.com/t/updateview-in-a-modal-window/22212/1 "2023-07-11T09:14:55Z")

</div>

## Introduction

I’m developing an article publishing application. Then, in the article detail page(DetailView), I’m implementing display/create/edit/delete functions for comments on the article. I’d like to design edit/delete comments functions are in a modal window.The comment delete function worked correctly, **but the comment edit function did not work properly.** I have no idea for improvement despite my survey, so please tell me what the problem is or what I should do.

## Premise

The functional requirements for the article detail page (article\_detail.html) are as follows

・display of article contents  
・edit/delete articles (only if the requesting user is the author of the article)  
・displaying comments on articles  
・creating comments on articles  
・edit/delete comments (only if the requesting user is the author of the comment)

Of these functions, editing/deleting an article is handled on a separate page to which the user transitions. On the other hand, the creation of comments and editing/deleting of comments will be handled in the article detail page, and especially editing/deleting of comments will be handled in a modal dialog.

## Codes

#### model.py

The models are `CustomUser` for user information, `Article` for articles, and `Comment` for comments on articles.The `CustomUser` is an extension of the `AbstractUser` class.In order to use markdown format, the `content` of `the Article` and the `text` of `the Comment` use the `MDTextField` class.

```auto
from mdeditor.fields import MDTextField

class CustomUser(AbstractUser):

    username = models.CharField(
        _("username"),
        max_length=30,
        help_text='Required 30 characters or fewer.',
        unique=True,
        error_messages={
            'unique': _("This Username already exists."),
        },)

    email = models.EmailField(
        _('email'),
        unique=True,
        error_messages={
            'unique': _("A user with that email address already exists."),
        },)
    
    class Meta:
        verbose_name_plural = 'CustomUser'

class Article(models.Model):

    post_user = models.ForeignKey(CustomUser, verbose_name='Post User', on_delete=models.CASCADE, related_name='name',)
    title = models.CharField(verbose_name='title', max_length=50,)
    content = MDTextField()
    created_at = models.DateField(verbose_name='created_at', auto_now_add=True,)

    class Meta:
        verbose_name_plural = 'Article'

    def __str__ (self):
        return self.title

class Comment(models.Model):
 
    writer = models.ForeignKey(CustomUser, on_delete=models.CASCADE,)
    text = MDTextField()
    target = models.ForeignKey(Article, on_delete=models.CASCADE,)
    created_at = models.DateField(verbose_name='created_at', auto_now_add=True,)
    updated_at = models.DateField(verbose_name='updated_at', auto_now=True,)

    def __str__ (self):
        return self.text[:20]

```

#### forms.py

I use `CommentCreateForm`, which extends `ModelForm`, to create and edit comments.

```auto
class CommentCreateForm(forms.ModelForm):
    class Meta:
        model = Comment
        fields = ("text",)

```

#### url.py

Editing comments is done in a modal window in the article detail page, so there is no dedicated page for this purpose.

```auto
app_name = 'article'

urlpatterns = [
    path('article_detail/<int:pk>', views.ArticleDetailView.as_view(), name='article_detail'),
    path('<int:pk>/comment/update', views.CommentUpdateView.as_view(), name='comment_update'),
    path('<int:pk>/comment/delete', views.CommentDeleteView.as_view(), name='comment_delete'),
]

```

#### views.py

The article detail page is displayed in `ArticleDetailView`, and comments associated with the article are returned to the template as context data.Regarding context data, `context['form']` for creating comments and `context['comment_form']` for editing comments in a modal window

```auto
class ArticleDetailView(generic.DetailView):
    model = Article
    template_name = 'article_detail.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['form'] = CommentCreateForm()
        context['comment_form'] = CommentCreateForm()
         context['comment_form'] = CommentCreateForm()
        context['comment_list'] = Comment.objects.select_related('target').filter(target=self.kwargs['pk'])

        return context

class CommentUpdateView(generic.UpdateView, LoginRequiredMixin):
    model = Comment
    form_class = CommentCreateForm
    template_name = 'article_detail.html'

    def get_success_url(self):
        return reverse_lazy('article:article_detail', kwargs={'pk': self.kwargs['pk']})

    def form_valid(self, form):
        messages.success(self.request, 'Your comment has been successfully updated.')
        return super().form_valid(form)

    def form_invalid(self, form):
        messages.error(self.request, 'Failed to correct comment.')
        return super().form_invalid(form)

class CommentDeleteView(generic.DeleteView, LoginRequiredMixin):
    model = Comment
    template_name = 'article_detail.html'

    def get_success_url(self):
        article = Article.objects.get(comment__pk=self.kwargs['pk'])
        return reverse_lazy('article:article_detail', kwargs={'pk': article.pk})

    def delete(self, request, *args, **kwargs):
        messages.success(self.request, "Comment has been Deleted")
        return super().delete(request, *args, **kwargs)

```

#### templates(article\_detail.html)

The modal display trigger for edit/delete comments is set to the pull-down list item associated with each comment.To abbreviate the code, only the comment display area is described.

```auto
{% if comment_list %}
    <section class="comment-list">
      <h2 id="comments" class="comment-title"><i class="fa-regular fa-comments"></i> comment</h2>
      {% for comment in comment_list %}
      <div class="commets-list">
        <li class="comment even thread-even depth-1 parent" id="comment-18730" style="list-style:none">
          <div id="div-comment-18730" class="comment-body article">
            <div class="comment-author vcard">
                <img alt="icon" {% if comment.writer.icon %} src="{{ comment.writer.icon.url }}" {% else %} src="{% static 'img/default_icon.png' %}" {% endif %} class="avatar avatar-55 photo" height="55" width="55">
                  <a href="{% url 'article:userpage' comment.writer %}">{{ comment.writer }}</a>
            </div>
            <div class="comment-meta commentmetadata">
              <p>{{ comment.created_at|date:"Y-m-j" }}</p>
            </div>

            {% if user == comment.writer %}
            <ul class="navbar-nav">
              <li class="nav-item dropdown">
                <a class="nav-link" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                  <img class="rounded-circle u-box-shadow-sm mr-2" width="25" height="25" src="{% static 'img/three_dots_icon.png' %}" alt="Icon">
                </a>
                <div class="dropdown-menu" aria-labelledby="navbarDropdown">
                  <a class="dropdown-item" id="showModal" data-toggle="modal" data-target="#commentModal-{{ comment.pk }}">Edit</a>                                   
                  <a class="dropdown-item" id="showModal2" data-toggle="modal" data-target="#deleteModal-{{ comment.pk }}">Delete</a>
                </div>

                <!-- Comment Edit Modal Dialog -->
                <div class="modal fade bd-example-modal-lg" id="commentModal-{{ comment.pk }}" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
                  <div class="modal-dialog modal-lg" role="document">
                    <div class="modal-content">
                      <div class="modal-header">
                        <h5 class="modal-title" id="exampleModalLabel">Modify Your Comment</h5>
                        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                          <span aria-hidden="true">&times;</span>
                        </button>
                      </div>
                      <div class="modal-body">
                        <form class="text-center w-md-75 mx-auto" method="POST" enctype="multipart/form-data" action="{% url 'article:comment_update' comment.pk %}">
                          {% csrf_token %}
                          {{ form.non_field_errors }}
                          {{ form.media }}

                          {% for field in comment_form %}                        
                          <div class="col-xl-12 form-group mb-4">
                            {{ field|markdown|safe }}
                            {{ field.errors }}
                          </div>
                          {% endfor %}
                        </form>
                      </div>
                      <div class="modal-footer">
                        <button type="button" class="btn btn-lg btn-primary py-3 px-4" data-dismiss="modal">Cancel</button>
                        <button type="submit" class="btn btn-lg btn-primary py-3 px-4">Save changes</button>
                      </div>
                    </div>
                  </div>
                </div>

                <!-- Comment Delete Modal Dialog -->
                <div class="modal fade bd-example-modal-lg" id="deleteModal-{{ comment.pk }}" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
                  <div class="modal-dialog modal-lg" role="document">
                    <div class="modal-content">
                      <div class="modal-header">
                        <h5 class="modal-title" id="exampleModalLabel">Do you really want to delete your comment?</h5>
                        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                          <span aria-hidden="true">&times;</span>
                        </button>
                      </div>
                      <div class="modal-body">
                        <p>{{ comment.text|markdown|safe }}</p>
                      </div>
                      <div class="modal-footer">
                        <form method="POST" action="{% url 'article:comment_delete' comment.pk %}">
                          {% csrf_token %}
                          <button type="button" class="btn btn-lg btn-primary py-3 px-4" data-dismiss="modal">Cancel</button>
                          <button type="submit" class="btn btn-lg btn-primary py-3 px-4">Delete</button>
                        </form>
                      </div>
                    </div>
                  </div>
                </div>

              </li>
            </ul>
            {% endif %}

          <div class="comment-content">
            <p>{{ comment.text|markdown|safe }}</p>
          </div>
          <div class="reply">
            <a class="comment-reply-link" href="#"><span class="fa fa-comment-o"></span> Reply</a>
          </div>
        </div>
        </li>
      </div>
      {% endfor %}
    </section>
    {% endif %}

```

## Issues

As shown in the image, the markdown editor is displayed in a modal window, but the data before editing is not displayed and cannot be entered, and pressing the “save changes” button does not take the user to the URL specified in `reverse_lazy`.

 ![スクリーンショット 2023-07-11 18.12.10](https://us1.discourse-cdn.com/flex026/uploads/djangoproject/original/2X/c/c4888744e96665a35cf2a2f1e8b8159ccceb5ba7.png)

On the other hand, the ability to delete comments functioned correctly. I checked for typing errors in the modal dialog information (html id and form action specification values) and in the url pattern string, but found no such errors. I think it is probably due to the override method of `get_context_data()` in views.py, but I didn’t know how to correct it.

---

<div class="post-metadata">

**Author:** ![addwebsolution](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/addwebsolution/32/23762_2.png) [@addwebsolution](https://forum.djangoproject.com/u/addwebsolution)\
**Post date:** [July 11, 2023, 9:57am UTC](https://forum.djangoproject.com/t/updateview-in-a-modal-window/22212/2 "2023-07-11T09:57:52Z")

</div>

> [@ponponmaru1012](#):
>
> ```auto
> class ArticleDetailView(generic.DetailView):
> model = Article
> template_name = 'article_detail.html'
> 
> def get_context_data(self, **kwargs):
> context = super().get_context_data(**kwargs)
> context['form'] = CommentCreateForm()
> context['comment_form'] = CommentCreateForm()
> context['comment_form'] = CommentCreateForm()
> context['comment_list'] = Comment.objects.select_related('target').filter(target=self.kwargs['pk'])
> 
> ```

In this view you have passed context[‘comment\_form’] 2 times

```auto
        context['comment_form'] = CommentCreateForm()
        context['comment_form'] = CommentCreateForm()

```

also here `CommentCreateForm()` you have to pass the instance of that detail object to show old data

> [@ponponmaru1012](#):
>
> `{{ field|markdown|safe }}`

here you don’t need to pass `safe` only `{{ field|markdown }}` needed

---

<div class="post-metadata">

**Author:** ![ponponmaru1012](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/ponponmaru1012/32/14737_2.png) [@ponponmaru1012](https://forum.djangoproject.com/u/ponponmaru1012)\
**Post date:** [July 11, 2023, 10:33am UTC](https://forum.djangoproject.com/t/updateview-in-a-modal-window/22212/3 "2023-07-11T10:33:46Z")

</div>

Thank you for your comment.  
I immediately corrected following two points

・fix passing `context['comment_form'] = CommentCreateForm()` 2 times to 1 times  
・fix `{{ field|markdown|safe }}` to `{{ field|markdown }}`

Then, What i should do is passing the `CommentCreateForm()` instance of to show old data. But I have no idea how to code the following part. This is because `self.kwargs['pk']` is the field value of the record in the parent model, `Article`. I don’t know how to use this value to specify the desired record from the child model `Comment`.

```auto
class ArticleDetailView(generic.DetailView):
    model = Article
    template_name = 'article_detail.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['form'] = CommentCreateForm()

        comment = 'I have no idea how to code here'
        context['comment_form'] = CommentCreateForm(instance=comment)

        context['comment_list'] = Comment.objects.select_related('target').filter(target=self.kwargs['pk'])

        return context

```
