Most of the data in your webapp will be associated with a user (for e.g., I’m the author of this post). django.contrib.auth comes with the User model that handles a lot of basic functionality for dealing with users. Here’s some basic reading.

Some people like to subclass User to add their own pieces of data, others prefer to create a separate UserProfile model. This post assumes that you already know how you’re going to deal with user profiles. What I’ll be talking about is associating models with a specific users. Given that:

from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=100)
    body = models.TextField(null=True, blank=True)

I wanted a generic way to add a user to any model. I didn’t want to add a user as a foreign key to Post, and then come back later and have to add it to the comment model as well (if the requirement came up). I wanted a generic way to attach a user to whichever model I wanted. There’ll be other ways to do this (and feel free to point them out), but I went with this:

from django.db import models
from django.contrib.auth.models import User

class UserData(models.Model):
    user = models.ForeignKey(User, editable=False)
    class Meta:
        abstract = True

class Post(UserData):
    title =  models.CharField(max_length=100)
    body =  models.TextField(null=True, blank=True)

Anything that inherits from UserData will have the user field in it. I’ve kept editable=False so that the user doesn’t appear in any forms. However, by keeping editable=False, if you use a PostForm to create/edit, you’ll have to set the user field manually (because user is a required field) in your view like so:


post_form = PostForm(request.POST)

temp_post = post_form.save(commit=False)
temp_post.user = request.user
temp_post.save()

Another variation would be to create a UserDataForm and then inherit your PostForm from it:

class UserDataForm(models.ModelForm):
                        
    # Overriding save allows us to add the user from the request    
    def save(self, user, commit=True):
        # get the instance so we can add the user to it.
        instance = super(UserDataForm, self).save(commit=False)
        instance.user = user

        # Do we need to save all changes now?
        if commit:
            instance.save()
            self.save_m2m()

        return instance

class PostForm(UserDataForm):
    class Meta:
        model = Post

# in your view
def save_post(request):
     post_form = PostForm(request.POST)
     post_form.save(user=request.user)

Interested in hearing how others deal with the same issue.

Trackback

only 1 comment

  1. Hi admin, i must say you have high quality content here. Your page can go viral.
    You need initial traffic boost only. How to get it?
    Search for; Mertiso’s tips go viral

Add your comment