different fields for add and change pages in admin

I couldn't get this working in django 1.6.5 using the above solutions. So I tried creating forms and having get_form serve those pre-defined forms depending on if the object exists or not:

models.py:

from django.db import models

class Project(models.Model):
    name = models.CharField('Project Name', max_length=255)
    slug = models.SlugField('Project Slug', max_length=255, unique=True)

forms.py: from django import forms from models import Project

class ProjectAddForm(forms.ModelForm):

    test = forms.Field()

    class Meta:
        model = Project


class ProjectEditForm(forms.ModelForm):

    class Meta:
        model = Project
        fields = ("name", 'slug')

admin.py

from django.contrib import admin
from models import Project
from forms import ProjectAddForm, ProjectEditForm


class ProjectAdmin(admin.ModelAdmin):

    def get_form(self, request, obj=None, **kwargs):
        # Proper kwargs are form, fields, exclude, formfield_callback
        if obj:
            self.form = ProjectEditForm
        else:
            self.form = ProjectAddForm
        return super(ProjectAdmin, self).get_form(request, obj, **kwargs)


admin.site.register(Project, ProjectAdmin)

Now I can intercept the non-persistent test field in the forms clean and do as I wish with it, just overwrite clean in the ProjectAddForm:

def clean(self):
    cleaned_data = super(ProjectAddForm, self).clean()
    test = cleaned_data.get("test")
    # Do logic here
    #raise forms.ValidationError("Passwords don't match.")
    return cleaned_data

This is an old question but I wanted to add that the add_view and change_view methods can be modified for this purpose:

class SoftwareVersionAdmin(ModelAdmin):
     ...
     def add_view(self,request,extra_content=None):
         self.exclude = ('product','version_number',)
         return super(SoftwareVersionAdmin,self).add_view(request)

     def change_view(self,request,object_id,extra_content=None):
         self.exclude = ('product','description',)
         return super(SoftwareVersionAdmin,self).change_view(request,object_id)

First have a look at source of ModelAdmin class' get_form and get_formsets methods located in django.contrib.admin.options.py. You can override those methods and use kwargs to get the behavior you want. For example:

class SoftwareVersionAdmin(ModelAdmin):
    def get_form(self, request, obj=None, **kwargs):
        # Proper kwargs are form, fields, exclude, formfield_callback
        if obj: # obj is not None, so this is a change page
            kwargs['exclude'] = ['foo', 'bar',]
        else: # obj is None, so this is an add page
            kwargs['fields'] = ['foo',]
        return super(SoftwareVersionAdmin, self).get_form(request, obj, **kwargs)

I don't think it's a good idea to override fields or exclude or form, because they are config attributes, so they would not initialize for every request.
I think the accepted answer by shanyu is a good solution.

Or we can use the method from UserAdmin:

def get_fieldsets(self, request, obj=None):                                  
    if not obj:                                                                                                 
        return self.add_fieldsets                                            
    return super(UserAdmin, self).get_fieldsets(request, obj)  

Remember to assign the add_fieldsets yourself. Unfortunately it doesn't fit my use case.

For Django 1.7. I don't know how they are implemented in other versions.