Index: django/contrib/admin/urls.py
===================================================================
--- django/contrib/admin/urls.py	(revision 4343)
+++ django/contrib/admin/urls.py	(working copy)
@@ -35,6 +35,8 @@
     # Add/change/delete/history
     ('^([^/]+)/([^/]+)/$', 'django.contrib.admin.views.main.change_list'),
     ('^([^/]+)/([^/]+)/add/$', 'django.contrib.admin.views.main.add_stage'),
+    ('^([^/]+)/([^/]+)/backup/$', 'django.contrib.admin.views.main.backup'),
+    ('^([^/]+)/([^/]+)/restore/$', 'django.contrib.admin.views.main.restore'),
     ('^([^/]+)/([^/]+)/(.+)/history/$', 'django.contrib.admin.views.main.history'),
     ('^([^/]+)/([^/]+)/(.+)/delete/$', 'django.contrib.admin.views.main.delete_stage'),
     ('^([^/]+)/([^/]+)/(.+)/$', 'django.contrib.admin.views.main.change_stage'),
Index: django/contrib/admin/views/main.py
===================================================================
--- django/contrib/admin/views/main.py	(revision 4343)
+++ django/contrib/admin/views/main.py	(working copy)
@@ -13,6 +13,8 @@
 from django.utils.html import escape
 from django.utils.text import capfirst, get_text_list
 import operator
+import cPickle
+from time import strftime, gmtime
 
 from django.contrib.admin.models import LogEntry, ADDITION, CHANGE, DELETION
 if not LogEntry._meta.installed:
@@ -767,3 +769,45 @@
                                'admin/%s/change_list.html' % app_label,
                                'admin/change_list.html'], context_instance=c)
 change_list = staff_member_required(never_cache(change_list))
+
+def backup(request, app_label, model_name):
+    model = models.get_model(app_label, model_name)
+    if model is None:
+        raise Http404("App %r, model %r, not found" % (app_label, model_name))
+    opts = model._meta
+
+    if not request.user.has_perm(app_label + '.' + opts.get_add_permission()):
+        raise PermissionDenied
+
+    objects = model.objects.all()
+    l=[]
+    for o in objects:
+        l.append(o)
+    response = HttpResponse(mimetype="text/plain")
+    response['Content-Disposition'] = 'attachment; filename=backup_%s__%s.txt' % (model_name, strftime('%c').replace(" ", "_"))
+    cPickle.dump(l, response)
+    return response
+    
+def restore(request, app_label, model_name):
+    model = models.get_model(app_label, model_name)
+    if model is None:
+        raise Http404("App %r, model %r, not found" % (app_label, model_name))
+    opts = model._meta
+
+    if not request.user.has_perm(app_label + '.' + opts.get_add_permission()):
+        raise PermissionDenied
+
+    c={"unloaded":True}
+    if request.FILES.has_key("restore_file"):
+        try:
+            objects=cPickle.loads(request.FILES["restore_file"]["content"])
+        except:
+            c={'unloaded':True, 'file_invalid':True}
+        else:
+            c={"objects_updated":[], "loaded":True}
+            for o in objects:
+                o.save()
+                c["objects_updated"].append(str(o))
+    return render_to_response(["admin/%s/%s/restore.html" % (app_label, model._meta.object_name.lower()),
+                               "admin/%s/restore.html" % app_label ,
+                               "admin/restore.html"], c)
\ No newline at end of file
Index: django/contrib/admin/templates/admin/change_list.html
===================================================================
--- django/contrib/admin/templates/admin/change_list.html	(revision 4343)
+++ django/contrib/admin/templates/admin/change_list.html	(working copy)
@@ -7,6 +7,7 @@
 {% block coltype %}flex{% endblock %}
 {% block content %}
 <div id="content-main">
+	<p><a href="backup/">{% trans 'Backup' %}</a> | <a href="restore/">{% trans 'Restore' %}</a></p>
 {% block object-tools %}
 {% if has_add_permission %}
 <ul class="object-tools"><li><a href="add/{% if is_popup %}?_popup=1{% endif %}" class="addlink">{% blocktrans with cl.opts.verbose_name|escape as name %}Add {{ name }}{% endblocktrans %}</a></li></ul>
Index: django/contrib/admin/templates/admin/restore.html
===================================================================
--- django/contrib/admin/templates/admin/restore.html	(revision 0)
+++ django/contrib/admin/templates/admin/restore.html	(revision 0)
@@ -0,0 +1,38 @@
+{% extends "admin/base_site.html" %}
+{% load i18n %}
+{% block userlinks %}<a href="../../../../doc/">{% trans 'Documentation' %}</a> / <a href="../../../../password_change/">{% trans 'Change password' %}</a> / <a href="../../../../logout/">{% trans 'Log out' %}</a>{% endblock %}
+
+{% block content %}
+{% if perms_lacking %}
+    <p>{% blocktrans with object|escape as escaped_object %}Restoring the {{ object_name }} '{{ escaped_object }}' would result in updating related objects, but your account doesn't have permission to update the following types of objects:{% endblocktrans %}</p>
+    <ul>
+    {% for obj in perms_lacking %}
+        <li>{{ obj|escape }}</li>
+    {% endfor %}
+    </ul>
+{% endif %}
+{% if unloaded %}
+	{% if file_invalid %}
+		<p>{% blocktrans %}Invalid file !{% endblocktrans %}</p>
+
+	{% else %}
+	    <p>{% blocktrans %}Caution ! You will override all the existing objects in the database !{% endblocktrans %}</p>
+	    <form action="" method="post" enctype="multipart/form-data">
+		<div>
+			<input type="file" name="restore_file">
+		</div>
+	    <div>
+	    <input type="submit" value="{% trans "Submit" %}" />
+	    </div>
+	    </form>
+	{% endif %}
+
+{% else %}
+	<p><p>{% blocktrans with object|escape as escaped_object %}Congratulation ! The following objects were updated :{% endblocktrans %}</p>
+    <ul>
+    {% for obj in objects_updated %}
+        <li>{{ obj|escape }}</li>
+    {% endfor %}
+	</ul>
+{% endif %}
+{% endblock %}
