Trying to convert a function based view to a generic detail view

Creating a comment system for a ticket django project. I’ve completed most of the functionality for the comment, except I’m not quite sure how to implement the POST method so that I can use the frontend to create comments. If I use the admin site, it works and shows up in the view, but I get an error when I try to submit using the frontend form. I’m not sure how to proceed, any help is much appreciated.

Traceback


Traceback (most recent call last):
  File "C:\Users\mikha\bug_env\lib\site-packages\django\db\backends\utils.py", line 85, in _execute
    return self.cursor.execute(sql, params)
  File "C:\Users\mikha\bug_env\lib\site-packages\django\db\backends\sqlite3\base.py", line 416, in execute
    return Database.Cursor.execute(self, query, params)

The above exception (NOT NULL constraint failed: tickets_comment.ticket_id) was the direct cause of the following exception:
  File "C:\Users\mikha\bug_env\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
    response = get_response(request)
  File "C:\Users\mikha\bug_env\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\mikha\bug_env\lib\site-packages\django\views\generic\base.py", line 69, in view
    return self.dispatch(request, *args, **kwargs)
  File "C:\Users\mikha\bug_env\lib\site-packages\django\views\generic\base.py", line 101, in dispatch
    return handler(request, *args, **kwargs)
  File "C:\Users\mikha\issuetracker\tickets\views.py", line 73, in post
    user_comment.save()
  File "C:\Users\mikha\bug_env\lib\site-packages\mptt\models.py", line 1096, in save
    super().save(*args, **kwargs)
  File "C:\Users\mikha\bug_env\lib\site-packages\django\db\models\base.py", line 743, in save
    self.save_base(using=using, force_insert=force_insert,
  File "C:\Users\mikha\bug_env\lib\site-packages\django\db\models\base.py", line 780, in save_base
    updated = self._save_table(
  File "C:\Users\mikha\bug_env\lib\site-packages\django\db\models\base.py", line 885, in _save_table
    results = self._do_insert(cls._base_manager, using, fields, returning_fields, raw)
  File "C:\Users\mikha\bug_env\lib\site-packages\django\db\models\base.py", line 923, in _do_insert
    return manager._insert(
  File "C:\Users\mikha\bug_env\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "C:\Users\mikha\bug_env\lib\site-packages\django\db\models\query.py", line 1301, in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
  File "C:\Users\mikha\bug_env\lib\site-packages\django\db\models\sql\compiler.py", line 1441, in execute_sql
    cursor.execute(sql, params)
  File "C:\Users\mikha\bug_env\lib\site-packages\django\db\backends\utils.py", line 99, in execute
    return super().execute(sql, params)
  File "C:\Users\mikha\bug_env\lib\site-packages\django\db\backends\utils.py", line 67, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "C:\Users\mikha\bug_env\lib\site-packages\django\db\backends\utils.py", line 76, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "C:\Users\mikha\bug_env\lib\site-packages\django\db\backends\utils.py", line 80, in _execute
    with self.db.wrap_database_errors:
  File "C:\Users\mikha\bug_env\lib\site-packages\django\db\utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "C:\Users\mikha\bug_env\lib\site-packages\django\db\backends\utils.py", line 85, in _execute
    return self.cursor.execute(sql, params)
  File "C:\Users\mikha\bug_env\lib\site-packages\django\db\backends\sqlite3\base.py", line 416, in execute
    return Database.Cursor.execute(self, query, params)

Here’s the original function based view

def ticket_single(request, post):

    ticket = get_object_or_404(Ticket, slug=ticket, status='published')

    allcomments = ticket.comments.filter(status=True)
    
    user_comment = None

    if request.method == 'POST':
        comment_form = NewCommentForm(request.POST)
        if comment_form.is_valid():
            user_comment = comment_form.save(commit=False)
            user_comment.ticket = ticket
            user_comment.save()
            return HttpResponseRedirect('/' + ticket.slug)
    else:
        comment_form = NewCommentForm()
    return render(request, 'ticket_detail.html', {'ticket': ticket, 'comments':  user_comment, 'comments': comments, 'comment_form': comment_form, 'allcomments': allcomments, })

Here’s what I have so far in the DetailView

class TicketDetailView(DetailView):
    model = Ticket

    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['comments'] = Comment.objects.filter(ticket=self.object)
        context['comment_form'] = NewCommentForm()
        return context
    
    def post(self, request, *args, **kwargs):
        if request.method == 'POST':
            comment_form = NewCommentForm(request.POST)
            if comment_form.is_valid():
                user_comment = comment_form.save(commit=False)
                user_comment.save()
                return render(request, 'ticket_detail.html', {'comments': user_comment, 'comment_form': comment_form})
            

A DetailView is designed to be a Display view, not an Edit view.

This is the wrong view to be trying to use for this purpose. You probably can get this to work, but what you’re really managed to do here is force the round peg into a square hole.

Given that you’re working with two different models here, (Ticket and Comment), none of the Django supplied edit CBVs are really a good fit for this purpose.

First, I suggest you re-evaluate your decision as to why you think there’s a benefit to be gained by changing what you have, to using a CBV intended for a different purpose.

If you still think there’s a benefit there, then what you’re really trying to build here would be best serviced by an UpdateView containing a formset for Comment or just a FormView where you don’t end up fighting model-specific functionality.