Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python Django Class-based Views Customizing Class-based Views Custom Mixin

Simon Amz
Simon Amz
4,606 Points

I don't succeed to set the 'success_message'.

Hi there,

I don't succeed to set the success message, despite of the right syntaxe.

ANy ideas?

articles/views.py
from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.urlresolvers import reverse_lazy
from django.views import generic

from . import mixins
from . import models


class ArticleList(generic.ListView):
    model = models.Article


class ArticleDetail(generic.DeleteView, generic.DetailView):
    model = models.Article
    template_name = 'articles/article_detail.html'


class ArticleCreate(LoginRequiredMixin, generic.CreateView, mixins.SuccessMessageMixin):
    fields = ('title', 'body', 'author', 'published')
    model = models.Article
    success_message = "Article created!"

class ArticleUpdate(LoginRequiredMixin, generic.UpdateView, mixins.SuccessMessageMixin):
    fields = ('title', 'body', 'author', 'published')
    model = models.Article

    def get_success_message(self):
        obj = self.get_object()
        return "{} updated!".format(obj)


class ArticleDelete(LoginRequiredMixin, generic.DeleteView):
    model = models.Article
    success_url = reverse_lazy('articles:list')


class ArticleSearch(generic.ListView):
    model = models.Article

    def get_queryset(self):
        qs = super().get_queryset()
        term = self.kwargs.get('term')
        if term:
            return qs.filter(body__icontains=term)
        return qs.none()
articles/mixins.py
from django.contrib import messages

class SuccessMessageMixin:
    success_message=""

    def get_success_message(self):
        return self.success_message

    def form_valid(self, form):
        messages.success(self.request, self.get_success_message())
        return super(form).form_valid(form)

7 Answers

Henrik Christensen
seal-mask
.a{fill-rule:evenodd;}techdegree
Henrik Christensen
Python Web Development Techdegree Student 38,322 Points

in your form_valid method, what happens if you just pass super() instead of super(form)?

return super().form_valid(form)  # try this
return super(form).form_valid(form)  # instead of this
Simon Amz
Simon Amz
4,606 Points

I changed the order like in the video, and I add in the updateView (obj.title), however, the error still occurs.

in articles/views.py

from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.urlresolvers import reverse_lazy
from django.views import generic

from . import mixins
from . import models


class ArticleList(generic.ListView):
    model = models.Article


class ArticleDetail(generic.DeleteView, generic.DetailView):
    model = models.Article
    template_name = 'articles/article_detail.html'


class ArticleCreate(LoginRequiredMixin, mixins.SuccessMessageMixin, generic.CreateView):
    fields = ('title', 'body', 'author', 'published')
    model = models.Article
    success_message = "Article created!"


class ArticleUpdate(LoginRequiredMixin, mixins.SuccessMessageMixin, generic.UpdateView):
    fields = ('title', 'body', 'author', 'published')
    model = models.Article

    def get_success_message(self):
        obj = self.get_object()
        return "{} updated!".format(obj.title)


class ArticleDelete(LoginRequiredMixin, generic.DeleteView):
    model = models.Article
    success_url = reverse_lazy('articles:list')


class ArticleSearch(generic.ListView):
    model = models.Article

    def get_queryset(self):
        qs = super().get_queryset()
        term = self.kwargs.get('term')
        if term:
            return qs.filter(body__icontains=term)
        return qs.none()

in articles/mixins.py

from django.contrib import messages

class SuccessMessageMixin:
    success_message = ""

    def get_success_message(self):
        return self.success_message

    def form_valid(self, form):
        messages.success(self.request, self.get_success_message())
        return super(ModelFormMixin, self).form_valid(form)

The error seems to come from the ArticleView, "Hmm, didn't get the right success message from 'ArticleCreate'

Henrik Christensen
seal-mask
.a{fill-rule:evenodd;}techdegree
Henrik Christensen
Python Web Development Techdegree Student 38,322 Points

try call self.object() instead of self.object().title, like this:

    def get_success_message(self):
        return "{} updated!".format(self.object())
Simon Amz
Simon Amz
4,606 Points

The same error occurs with these versions:

def get_success_message(self):
        return "{} updated!".format(self.object())
def get_success_message(self):
        return "{} updated!".format(self.get_object())
def get_success_message(self):
        obj = self.get_object()
        return "{} updated!".format(obj)
def get_success_message(self):
        obj = self.object()
        return "{} updated!".format(obj)
def get_success_message(self):
        obj = self.get_object()
        return "{} updated!".format(obj.title)
def get_success_message(self):
        obj = self.object()
        return "{} updated!".format(obj.title)

Nothing works, but following the error message it comes from the 'ArticleCreate' and not the 'ArticleUpdate'

Henrik Christensen
seal-mask
.a{fill-rule:evenodd;}techdegree
Henrik Christensen
Python Web Development Techdegree Student 38,322 Points

I don't know how to explain that in english, sorry :-P

But usually I just use super() because I've noticed that super(something here, self) and super() is the same (I might be wrong) - I think it's just a personal preference :-)

Simon Amz
Simon Amz
4,606 Points

Hi Henrik,

Indeed, it works. in ccbv.co.uk, they wrote:

ModelFormMixin If the form is valid, save the associated model.

def form_valid(self, form): """ If the form is valid, save the associated model. """ self.object = form.save() return super(ModelFormMixin, self).form_valid(form)

How do we know if in the mixin we have to make super(form) or super(ModelFormMixin, self) or super() only?