Index: django/contrib/admin/options.py
===================================================================
--- django/contrib/admin/options.py	(revision 5005)
+++ django/contrib/admin/options.py	(working copy)
@@ -1,6 +1,7 @@
 from django import oldforms, template
 from django import newforms as forms
 from django.contrib.admin import widgets
+from django.newforms.widgets import DisplayWidget
 from django.core.exceptions import ImproperlyConfigured, PermissionDenied
 from django.db import models
 from django.http import Http404, HttpResponse, HttpResponseRedirect
@@ -111,6 +112,8 @@
     fields = None
     raw_id_fields = ()
     prepopulated_fields = {}
+    # this list contains fields that will only be changed when adding an object. They'll only be displayed in change forms
+    readonly_fields = ()
     filter_vertical = ()
     filter_horizontal = ()
 
@@ -201,37 +204,52 @@
         for fs in self.fieldsets(request):
             yield fs
 
-    def formfield_for_dbfield(self, db_field, **kwargs):
+    def formfield_for_dbfield_add(self, db_field, override_readonly=True, **kwargs):
         """
+        call formfield_for_dbfield with override_readonly = True. Used for admin add object forms
+        """
+        return self.formfield_for_dbfield(db_field, override_readonly, **kwargs)
+        
+    def formfield_for_dbfield(self, db_field, override_readonly=False, **kwargs):
+        """
         Hook for specifying the form Field instance for a given database Field
         instance.
 
         If kwargs are given, they're passed to the form Field's constructor.
         """
+        # specify that this value cannot be edited by the user. The formfield will decide how to render this.
+        # The override is used by the create form to set the value. 
+        this_field_is_readonly = False
+        if not override_readonly and db_field.name in self.readonly_fields:
+            this_field_is_readonly = True
+            kwargs['widget'] = DisplayWidget
+            
         # For ManyToManyFields with a filter interface, use a special Widget.
         if isinstance(db_field, models.ManyToManyField) and db_field.name in (self.filter_vertical + self.filter_horizontal):
             kwargs['widget'] = widgets.FilteredSelectMultiple(db_field.verbose_name, (db_field.name in self.filter_vertical))
             return db_field.formfield(**kwargs)
 
         # For DateTimeFields, use a special field and widget.
-        if isinstance(db_field, models.DateTimeField):
+        if isinstance(db_field, models.DateTimeField) and not this_field_is_readonly:
             return forms.SplitDateTimeField(required=not db_field.blank,
                 widget=widgets.AdminSplitDateTime(), label=capfirst(db_field.verbose_name),
                 help_text=db_field.help_text, **kwargs)
 
         # For DateFields, add a custom CSS class.
-        if isinstance(db_field, models.DateField):
+        if isinstance(db_field, models.DateField) and not this_field_is_readonly:
             kwargs['widget'] = forms.TextInput(attrs={'class': 'vDateField', 'size': '10'})
             return db_field.formfield(**kwargs)
 
         # For TimeFields, add a custom CSS class.
-        if isinstance(db_field, models.TimeField):
+        if isinstance(db_field, models.TimeField) and not this_field_is_readonly:
             kwargs['widget'] = forms.TextInput(attrs={'class': 'vTimeField', 'size': '8'})
             return db_field.formfield(**kwargs)
 
         # For ForeignKey or ManyToManyFields, use a special widget.
         if isinstance(db_field, (models.ForeignKey, models.ManyToManyField)):
-            if isinstance(db_field, models.ForeignKey) and db_field.name in self.raw_id_fields:
+            if this_field_is_readonly:
+                pass # the displaywidget will take care of it !
+            elif isinstance(db_field, models.ForeignKey) and db_field.name in self.raw_id_fields:
                 kwargs['widget'] = widgets.ForeignKeyRawIdWidget(db_field.rel)
                 return db_field.formfield(**kwargs)
             else:
@@ -392,7 +410,7 @@
             # Object list will give 'Permission Denied', so go back to admin home
             post_url = '../../../'
 
-        ModelForm = forms.form_for_model(model, formfield_callback=self.formfield_for_dbfield)
+        ModelForm = forms.form_for_model(model, formfield_callback=self.formfield_for_dbfield_add)
 
         if request.POST:
             new_data = request.POST.copy()
@@ -443,6 +461,11 @@
             new_data = request.POST.copy()
             if opts.has_field_type(models.FileField):
                 new_data.update(request.FILES)
+            # get the values for readonly fields from the object, because they are displayed as strings instead of widgets and thus are not part of the POST request 
+            for fieldname in self.readonly_fields:
+                fieldvalue = getattr(obj, fieldname)
+                new_data[fieldname] = fieldvalue
+                
             form = ModelForm(new_data)
 
             if form.is_valid():
@@ -507,6 +530,7 @@
         "The 'delete' admin view for this model."
         from django.contrib.contenttypes.models import ContentType
         from django.contrib.admin.models import LogEntry, DELETION
+        from django.contrib.admin.views.main import _get_deleted_objects
         opts = self.model._meta
         app_label = opts.app_label
 
Index: django/contrib/admin/filterspecs.py
===================================================================
--- django/contrib/admin/filterspecs.py	(revision 5005)
+++ django/contrib/admin/filterspecs.py	(working copy)
@@ -158,7 +158,7 @@
     def __init__(self, f, request, params, model):
         super(AllValuesFilterSpec, self).__init__(f, request, params, model)
         self.lookup_val = request.GET.get(f.name, None)
-        self.lookup_choices = model._meta.admin.manager.distinct().order_by(f.name).values(f.name)
+        self.lookup_choices = model._default_manager.distinct().order_by(f.name).values(f.name)
 
     def title(self):
         return self.field.verbose_name
Index: django/newforms/widgets.py
===================================================================
--- django/newforms/widgets.py	(revision 5005)
+++ django/newforms/widgets.py	(working copy)
@@ -3,7 +3,7 @@
 """
 
 __all__ = (
-    'Widget', 'TextInput', 'PasswordInput', 'HiddenInput', 'MultipleHiddenInput',
+    'Widget', 'DisplayWidget', 'TextInput', 'PasswordInput', 'HiddenInput', 'MultipleHiddenInput',
     'FileInput', 'Textarea', 'CheckboxInput',
     'Select', 'NullBooleanSelect', 'SelectMultiple', 'RadioSelect', 'CheckboxSelectMultiple',
     'MultiWidget', 'SplitDateTimeWidget',
@@ -66,6 +66,30 @@
         return id_
     id_for_label = classmethod(id_for_label)
 
+class DisplayWidget(Widget):
+    """
+    Base class for all read-only pseudo-widgets. Those are used by the admin interface to display read-only values
+    """
+    def __init__(self, choices=None, attrs=None):        
+        self.attrs = attrs or {}
+        self.choices = choices
+    
+    def render(self, name, value, attrs=None):
+        # lookup choices values
+        if self.choices is not None:
+            for (primary_key, name) in self.choices:
+                if value == primary_key:
+                    value = name
+                    break
+        # and replace special values by strings to improve readability
+        if value is None: 
+            value = '[Null]'
+        if value == '':
+            value = '[Blank]'
+        
+        return smart_unicode(value)
+    
+
 class Input(Widget):
     """
     Base class for all <input> widgets (except type='checkbox' and
