peperone
peperone

Reputation: 23

Generic DeleteView is returning django.db.models.query_utils.DeferredAttribute object at 0x04725628 - Django

Disclaimer: I'm just a novice trying to learn Django

Hello, I'm trying to refactor my code and modify all the views that I have created to be Class Based Views. I have an issue loading a form with DeleteView that is showing the data and at the same time is disabled. I have some success and the only thing that I cannot figure out how to do is to show the data instead of the message that appears now "<django.db.models.query_utils.DeferredAttribute object at 0x04725628>"

+models.py:

class Note(models.Model):
title = models.CharField(max_length=30)
image_url = models.URLField()
content = models.TextField()
owner = models.ForeignKey(Profile, default=8, on_delete=models.CASCADE)

def get_absolute_url(self):
    return reverse(self.pk)

def __str__(self):
    return f'{self.title}'

+forms.py

class NoteForm(forms.ModelForm):
class Meta:
    model = Note
    exclude = ('owner',)


class DeleteNoteForm(NoteForm):
def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    for (_, field) in self.fields.items():
        field.widget.attrs['readonly'] = True
        field.widget.attrs['disabled'] = True

+views.py

class DeleteNoteView(DeleteView):
model = Note
template_name = 'note-delete.html'
form_class = DeleteNoteForm
success_url = reverse_lazy('home page')

def get_context_data(self, **kwargs):
    data = super().get_context_data(**kwargs)
    data['form'] = self.form_class(instance=self.model)
    return data

+urls.py

path('delete/<int:pk>/', views.DeleteNoteView.as_view(), name='delete note'),

+template

        <!--note delete data form-->
    <div class="form">
        <form method="POST">
            {{ form }}
            {% csrf_token %}
            <input type="submit" value="Delete"/>
        </form>
    </div>
    <!--end note delete data form-->

If I use my view it works fine, but I want to modify it.

def delete_note(request, pk):
note = Note.objects.get(pk=pk)
if request.method=='GET':
    note_form = DeleteNoteForm(instance=note)
    context = {
        'note_form': note_form
    }
    return render(request, 'note-delete.html', context)
else:
    note.delete()
    return redirect('home page')

Could someone tell me where I'm wrong and how I can fix it or at least provide me a link with information to understand why this is happening?

Upvotes: 2

Views: 722

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477684

You are passing a reference to the model class in your DeleteNoteView, whereas you should use the object that is removed, so:

class DeleteNoteView(DeleteView):
    model = Note
    template_name = 'note-delete.html'
    form_class = DeleteNoteForm
    success_url = reverse_lazy('home page')
    
    def get_context_data(self, **kwargs):
        data = super().get_context_data(**kwargs)
        #       user self.object instead of self.model ↓
        data['form'] = self.form_class(instance=self.object)
        return data

I would also advise to filter the QuerySet such that it is impossible for another user (a user that is not the owner of a Note to remove that Note:

from django.contrib.auth.mixins import LoginRequiredMixin

class DeleteNoteView(LoginRequiredMixin, DeleteView):
    model = Note
    template_name = 'note-delete.html'
    form_class = DeleteNoteForm
    success_url = reverse_lazy('home page')

    def get_queryset(self, *args, **kwargs):
        return super().get_queryset(*args, **kwargs).filter(
            owner=self.request.user
        )
    
    def get_context_data(self, **kwargs):
        data = super().get_context_data(**kwargs)
        data['form'] = self.form_class(instance=self.object)
        return data

Upvotes: 2

Related Questions