Brian Gesiak
Brian Gesiak

Reputation: 6958

Why won't this override of the Model.save() function in Django work?

I am new to SO and Python/Django, so please bear with me.

In my generic blog app based on the tutorial at http://www.djangoproject.com/, I am trying to create slugs for posts when they are saved to the database by using the slugify() method on the post's title. Here is posts.models.py:

from django.db import models
from django.template.defaultfilters import slugify
import datetime

class Post( models.Model ):

    def __unicode__(self):
        return self.title

    title = models.CharField( max_length = 200 )
    slug  = models.SlugField( editable = False )
    body = models.TextField()
    pub_date = models.DateTimeField('date published')

    def save(self, *args, **kwargs):
        if not self.id:
            self.slug = slugify( self.title )
        super( Post, self ).save( *args, **kwargs )

Unfortunately, this throws the following exception upon attempting to start the server:

File "/Users/modocache/Programming/Django/blog/posts/models.py", line 24, in Post
super( Post, self ).save( *args, **kwargs )
NameError: name 'Post' is not defined

I am confused as to why NameError is thrown. I thought I was using the super() method wrong, but this works, despite it seeming like the same thing I'm attempting above:

class Foo( object ):
    def say_spam( self ):
        print "Spam!"

class Bar( Foo ):
    def say_spam( self ):
        print "Brought to you by:"
        super( Bar, self ).say_spam()
        print "Eggs!"

b = Bar()
b.say_spam()

So if this works, why doesn't the above Django snippet fail? This is especially puzzling considering djangoproject.com's documentation says this should work:

# http://docs.djangoproject.com/en/dev/topics/db/models/#overriding-model-methods

class Blog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.TextField()

    def save(self, *args, **kwargs):
        do_something()
        super(Blog, self).save(*args, **kwargs) # Call the "real" save() method.
        do_something_else()

Thanks for any and all help in advance, I'd really appreciate it!

Upvotes: 4

Views: 4088

Answers (2)

I'm wondering if you have an indentation error at your super() line -- do you have tabs and spaces mixed up?

Upon starting the server even typing in super(IDONTEXIST, self) should not throw an error until save() is called.

I can reproduce your error if I de-indent the super line.

Upvotes: 1

Ken Cochrane
Ken Cochrane

Reputation: 77335

modocache,

What version of django are you using? What you have there listed should work, I use that same logic in many of my own models, and it works fine.

According to this page: http://fosshelp.blogspot.com/2010/12/django-override-save-method-two-ways.html

you should be able to change the code to look like this (below), and it will do the same thing but won't reference the Post model.

 def save(self, *args, **kwargs):
    if not self.id:
        self.slug = slugify( self.title )
    models.Model.save(self, *args, **kwargs ) # <-- notice the self

Another point , instead of using "if not self.id:" it is generally better practice to use "if not self.pk:" instead. see these related links.

Django queries - id vs pk

http://docs.djangoproject.com/en/dev/ref/models/instances/#the-pk-property

How that helps.

Upvotes: 4

Related Questions