'MyDetailView' object has no attribute 'object'

I’m trying to work on a template with embedded form, that upon being submitted re-routes the user to the same template, but with an updated context. My View/Template were working fine, passing the correct context every time, until I implemented the form, which appears to have broken the view. Any help would be much appreciated. It would seem that I’m trying to get an ‘object’ attribute from the DetailView’s select object, but I don’t see how/why.

The view:

class BetTagPageView(LoginRequiredMixin, UserPassesTestMixin, DetailView):

    model = Bet
    template_name = "tags/bet_tag_page.html"

    def post(self, request, *args, **kwargs):

        context = self.get_context_data(**kwargs)

        return self.render_to_response(context)
    
    def get(self, request, *args, **kwargs):
        context = self.get_context_data(**kwargs)

        return self.render_to_response(context)


    def get_context_data(self, **kwargs): 
        context = super().get_context_data(**kwargs)  
        context["bet"] = self.get_object()
        print("debug line")
        print(context["bet"])
        context["inactive_tags"] = Tag.objects.exclude(associated_bets=context["bet"]).distinct()
        print(context["inactive_tags"])
        context["pk"] = self.get_object().pk
        print(context["pk"])
        return context
    

    def test_func(self):
        """Checks if bet owner is the same as the current user."""
        obj = self.get_object()
        return obj.bet_owner == self.request.user

The template form:

<form action={% url "bet_tag_page" pk=pk %} method="POST">
    {% csrf_token %}
    <select name="tag-select" class="form-select" multiple aria-label="no-label" style="width: 40%;">
    {% for tag in inactive_tags %}
        <option value="{{tag}}">{{tag}}</option>
    {% endfor %}
    </select>
    <button class="btn btn-success active border border-dark" style="margin: 20px;" type="submit">Assign one or more Tags to this Bet</button>
    <a class="btn btn-warning border border-dark" style="margin: 20px;" href="#" role="button">Create a new Tag</a>

</form>

The error:

BlockquoteInternal Server Error: /tags/bet_tag_page/3/
Traceback (most recent call last):
File “C:\Users\Central Gamer\Desktop\Python\Orange Bet Tracker.venv\Lib\site-packages\django\core\handlers\exception.py”, line 55, in inner
response = get_response(request)
^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\Central Gamer\Desktop\Python\Orange Bet Tracker.venv\Lib\site-packages\django\core\handlers\base.py”, line 197, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\Central Gamer\Desktop\Python\Orange Bet Tracker.venv\Lib\site-packages\django\views\generic\base.py”, line 104, in view
return self.dispatch(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\Central Gamer\Desktop\Python\Orange Bet Tracker.venv\Lib\site-packages\django\contrib\auth\mixins.py”, line 73, in dispatch
return super().dispatch(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\Central Gamer\Desktop\Python\Orange Bet Tracker.venv\Lib\site-packages\django\contrib\auth\mixins.py”, line 135, in dispatch
return super().dispatch(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\Central Gamer\Desktop\Python\Orange Bet Tracker.venv\Lib\site-packages\django\views\generic\base.py”, line 143, in dispatch
return handler(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\Central Gamer\Desktop\Python\Orange Bet Tracker\tags\views.py”, line 61, in get
context = self.get_context_data(**kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\Central Gamer\Desktop\Python\Orange Bet Tracker\tags\views.py”, line 67, in get_context_data
context = super().get_context_data(**kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\Central Gamer\Desktop\Python\Orange Bet Tracker.venv\Lib\site-packages\django\views\generic\detail.py”, line 95, in get_context_data
if self.object:
^^^^^^^^^^^
AttributeError: ‘BetTagPageView’ object has no attribute ‘object’
[30/Oct/2024 20:01:31] “GET /tags/bet_tag_page/3/ HTTP/1.1” 500 93204

It seems to me that the error appears to be caused by the self.object attribute not being initialized before invoking super().get_context_data(**kwargs) in your get_context_data method.

To fix this, you need to ensure that self.object is set before calling super().get_context_data(**kwargs).

Try this:

from django.views.generic.detail import DetailView
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.shortcuts import render
from .models import Bet, Tag

class BetTagPageView(LoginRequiredMixin, UserPassesTestMixin, DetailView):
    model = Bet
    template_name = "tags/bet_tag_page.html"

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()  # Ensure self.object is set
        context = self.get_context_data(**kwargs)
        # Handle form submission logic here
        return self.render_to_response(context)

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()  # Ensure self.object is set
        context = self.get_context_data(**kwargs)
        return self.render_to_response(context)

    def get_context_data(self, **kwargs): 
        context = super().get_context_data(**kwargs)  
        context["bet"] = self.get_object()
        print("debug line")
        print(context["bet"])
        context["inactive_tags"] = Tag.objects.exclude(associated_bets=context["bet"]).distinct()
        print(context["inactive_tags"])
        context["pk"] = self.get_object().pk
        print(context["pk"])
        return context

    def test_func(self):
        """Checks if bet owner is the same as the current user."""
        obj = self.get_object()
        return obj.bet_owner == self.request.user

1 Like

Thank you very much, that fixed it.

Side note: In situations like this, I recommend using FormView as the base class with the detail display being considered extra content for the template. The FormView is already designed to handle the flow around form submissions, potentially minimizing the additional code needed to make it work.