Daudidenno
Daudidenno

Reputation: 47

What causes "no attribute 'object_list' when I purposely csuse HTML error

I am writing a django ListView with FormMixin, but it can't handle form errors. The model limits input to 140 characters, when I inspect and change limit to 200 and submit I get

'PostListView' object has no attribute 'object_list'"

Here's the code

class PostListView(FormMixin, generic.ListView):
    model = Post
    form_class = PostForm
    paginate_by = 10
    template_name = 'index.html'

    def get_success_url(self):
        return reverse('index')

    def post(self, request, *args, **kwargs):
        form = PostForm(request.POST)
        if form.is_valid():
            form.save()
            return super().form_valid(form)
        else:
            return self.form_invalid(form)

With everything working normally, it saves the data and displays the list. On error, no error, it fails.

EDIT

As @crimsonpython24 has said, ListView is for displaying data. I opted to use a basic view

def index(request):
    '''deal with post method first'''
    if request.method == 'POST':
        form = PostForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect(reverse('index'))
    
    else:
        form = PostForm
    
    posts = Post.objects.all()
    return render(request, 'index.html', {'form':form, 'posts':posts})

This allows for invalid form data to be returned for correction, and also allows viewing of posts

Upvotes: 1

Views: 337

Answers (1)

crimsonpython24
crimsonpython24

Reputation: 2383

The point is that ListView is only supposed to view objects. If you have a form in your view, try to go for one of the edit views, which lets you create, update, and delete (now I'm assuming that you also handle a form in this view).

I can't exactly describe how ListView causes your problem other than it does not fit your purpose and there are better alternatives.

EDIT

Now you're concatenating a FormView and ListView. However, I will still recommend going for a FormView as a ListView doesn't have a form_class attribute. It's easy, though. Let's say you have this FormView class:

class ContactView(FormView):
    template_name = 'contact.html'
    form_class = ContactForm        # Now you can simply do this to your form
    success_url = '/thanks/'

    def form_valid(self, form):
        form.send_email()
        return super().form_valid(form)

and then simply pass in context data to make it behave partially like a ListView:

class ContactView(FormView):
    # whatever you have here already

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['now'] = timezone.now()
        return context

So now your new view will render both your form and context data. Seeing as both these views don't require a primary key to operate, I don't see any problem implmenting this.

Upvotes: 2

Related Questions