Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Merged to trunk r1152

git-svn-id: http://code.djangoproject.com/svn/django/branches/new-admin@1154 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit dbaf9c6f8d4c17013238958a9b2f3f8d7bcbb665 2 parents a4961a9 + 28bce49
Robert Wittams authored November 10, 2005
2  django/contrib/admin/templates/admin/index.html
@@ -57,7 +57,7 @@
57 57
             {% else %}
58 58
             <ul class="actionlist">
59 59
             {% for entry in admin_log %}
60  
-                <li class="{% if entry.is_addition %}addlink{% endif %}{% if entry.is_change %}changelink{% endif %}{% if entry.is_deletion %}deletelink{% endif %}">{% if not entry.is_deletion %}<a href="{{ entry.get_admin_url }}">{% endif %}{{ entry.object_repr }}{% if not entry.is_deletion %}</a>{% endif %}<br /><span class="mini quiet">{{ entry.get_content_type.name|capfirst }}</span></li>
  60
+                <li class="{% if entry.is_addition %}addlink{% endif %}{% if entry.is_change %}changelink{% endif %}{% if entry.is_deletion %}deletelink{% endif %}">{% if not entry.is_deletion %}<a href="{{ entry.get_admin_url }}">{% endif %}{{ entry.object_repr|escape }}{% if not entry.is_deletion %}</a>{% endif %}<br /><span class="mini quiet">{{ entry.get_content_type.name|capfirst }}</span></li>
61 61
             {% endfor %}
62 62
             </ul>
63 63
             {% endif %}
10  django/contrib/admin/views/main.py
@@ -113,7 +113,7 @@ def choices(self, cl):
113 113
                'query_string': cl.get_query_string({}, [self.lookup_kwarg]), 
114 114
                'display': _('All') }
115 115
         for val in self.lookup_choices:
116  
-            pk_val = getattr(val, self.field.rel.to.pk.column)
  116
+            pk_val = getattr(val, self.field.rel.to.pk.attname)
117 117
             yield { 'selected': self.lookup_val == str(pk_val), 
118 118
                     'query_string': cl.get_query_string( {self.lookup_kwarg: pk_val}),
119 119
                     'display' : val }
@@ -547,7 +547,7 @@ def render_change_form(opts, manipulator, app_label, context, add=False, change=
547 547
                               context_instance=context)
548 548
    
549 549
 def log_add_message(user, opts,manipulator,new_object):
550  
-    pk_value = getattr(new_object, opts.pk.column)
  550
+    pk_value = getattr(new_object, opts.pk.attname)
551 551
     log.log_action(user.id, opts.get_content_type_id(), pk_value, str(new_object), log.ADDITION)
552 552
 
553 553
 def add_stage(request, app_label, module_name, show_delete=False, form_url='', post_url='../', post_url_continue='../%s/', object_id_override=None):
@@ -566,7 +566,7 @@ def add_stage(request, app_label, module_name, show_delete=False, form_url='', p
566 566
             new_object = manipulator.save(new_data)
567 567
             log_add_message(request.user, opts,manipulator,new_object)
568 568
             msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name':opts.verbose_name, 'obj':new_object}
569  
-            pk_value = getattr(new_object,opts.pk.column)
  569
+            pk_value = getattr(new_object,opts.pk.attname)
570 570
             # Here, we distinguish between different save types by checking for
571 571
             # the presence of keys in request.POST.
572 572
             if request.POST.has_key("_continue"):
@@ -644,7 +644,7 @@ def change_stage(request, app_label, module_name, object_id):
644 644
             new_object = manipulator.save(new_data)
645 645
             log_change_message(request.user,opts,manipulator,new_object)
646 646
             msg = _('The %(name)s "%(obj)s" was changed successfully.') % {'name': opts.verbose_name, 'obj':new_object}
647  
-            pk_value = getattr(new_object,opts.pk.column)
  647
+            pk_value = getattr(new_object,opts.pk.attname)
648 648
             if request.POST.has_key("_continue"):
649 649
                 request.user.add_message(msg + ' ' + _("You may edit it again below."))
650 650
                 if request.REQUEST.has_key('_popup'):
@@ -738,7 +738,7 @@ def _get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current
738 738
                     # Display a link to the admin page.
739 739
                     nh(deleted_objects, current_depth, ['%s: <a href="../../../../%s/%s/%s/">%s</a>' % \
740 740
                         (capfirst(related.opts.verbose_name), related.opts.app_label, related.opts.module_name,
741  
-                        getattr(sub_obj, related.opts.pk.column), sub_obj), []])
  741
+                        getattr(sub_obj, related.opts.pk.attname), sub_obj), []])
742 742
                 _get_deleted_objects(deleted_objects, perms_needed, user, sub_obj, related.opts, current_depth+2)
743 743
         else:
744 744
             has_related_objs = False
8  django/core/formfields.py
@@ -309,6 +309,7 @@ def convert_post_data(self, new_data):
309 309
                new_data.setlist(name, [])
310 310
 
311 311
     def get_id(self):
  312
+    	"Returns the HTML 'id' attribute for this form field."
312 313
         return  FORM_FIELD_ID_PREFIX + self.field_name  
313 314
 ####################
314 315
 # GENERIC WIDGETS  #
@@ -408,10 +409,10 @@ def __init__(self, field_name, choices=[], size=1, is_required=False, validator_
408 409
             self.member_name = member_name
409 410
 
410 411
     def render(self, data):
411  
-        str_data = str(data) # normalize to string
412 412
         output = ['<select id="%s" class="v%s%s" name="%s" size="%s">' % \
413  
-            (self.get_id(), self.__class__.__name__, 
  413
+            (self.get_id(), self.__class__.__name__,
414 414
              self.is_required and ' required' or '', self.field_name, self.size)]
  415
+        str_data = str(data) # normalize to string
415 416
         for value, display_name in self.choices:
416 417
             selected_html = ''
417 418
             if str(value) == str_data:
@@ -593,8 +594,7 @@ def isNonEmptyFile(self, field_data, all_data):
593 594
 
594 595
     def render(self, data):
595 596
         return '<input type="file" id="%s" class="v%s" name="%s" />' % \
596  
-            (self.get_id(), self.__class__.__name__,
597  
-            self.field_name)
  597
+            (self.get_id(), self.__class__.__name__, self.field_name)
598 598
 
599 599
     def html2python(data):
600 600
         if data is None:
23  django/core/management.py
@@ -108,7 +108,23 @@ def get_sql_delete(mod):
108 108
         cursor = db.db.cursor()
109 109
     except:
110 110
         cursor = None
  111
+
  112
+    # Determine whether the admin log table exists. It only exists if the
  113
+    # person has installed the admin app.
  114
+    try:
  115
+        if cursor is not None:
  116
+            # Check whether the table exists.
  117
+            cursor.execute("SELECT 1 FROM django_admin_log LIMIT 1")
  118
+    except:
  119
+        # The table doesn't exist, so it doesn't need to be dropped.
  120
+        db.db.rollback()
  121
+        admin_log_exists = False
  122
+    else:
  123
+        admin_log_exists = True
  124
+
111 125
     output = []
  126
+
  127
+    # Output DROP TABLE statements for standard application tables.
112 128
     for klass in mod._MODELS:
113 129
         try:
114 130
             if cursor is not None:
@@ -119,6 +135,8 @@ def get_sql_delete(mod):
119 135
             db.db.rollback()
120 136
         else:
121 137
             output.append("DROP TABLE %s;" % klass._meta.db_table)
  138
+
  139
+    # Output DROP TABLE statements for many-to-many tables.
122 140
     for klass in mod._MODELS:
123 141
         opts = klass._meta
124 142
         for f in opts.many_to_many:
@@ -140,8 +158,9 @@ def get_sql_delete(mod):
140 158
     # Delete from the admin log.
141 159
     if cursor is not None:
142 160
         cursor.execute("SELECT id FROM content_types WHERE package = %s", [app_label])
143  
-        for row in cursor.fetchall():
144  
-            output.append("DELETE FROM django_admin_log WHERE content_type_id = %s;" % row[0])
  161
+        if admin_log_exists:
  162
+            for row in cursor.fetchall():
  163
+                output.append("DELETE FROM django_admin_log WHERE content_type_id = %s;" % row[0])
145 164
 
146 165
     # Close database connection explicitly, in case this output is being piped
147 166
     # directly into a database client, to avoid locking issues.
94  django/core/meta/__init__.py
@@ -889,7 +889,7 @@ def method_init(opts, self, *args, **kwargs):
889 889
                 except KeyError:
890 890
                     try:
891 891
                         # Object instance wasn't passed in -- must be an ID.
892  
-                        val = kwargs.pop(f.column)
  892
+                        val = kwargs.pop(f.attname)
893 893
                     except KeyError:
894 894
                         val = f.get_default()
895 895
                 else:
@@ -901,17 +901,17 @@ def method_init(opts, self, *args, **kwargs):
901 901
                             val = getattr(rel_obj, f.rel.field_name)
902 902
                         except AttributeError:
903 903
                             raise TypeError, "Invalid value: %r should be a %s instance, not a %s" % (f.name, f.rel.to, type(rel_obj))
904  
-                setattr(self, f.column, val)
  904
+                setattr(self, f.attname, val)
905 905
             else:
906  
-                val = kwargs.pop(f.name, f.get_default())
907  
-                setattr(self, f.name, val)
  906
+                val = kwargs.pop(f.attname, f.get_default())
  907
+                setattr(self, f.attname, val)
908 908
         if kwargs:
909 909
             raise TypeError, "'%s' is an invalid keyword argument for this function" % kwargs.keys()[0]
910 910
     for i, arg in enumerate(args):
911  
-        setattr(self, opts.fields[i].column, arg)
  911
+        setattr(self, opts.fields[i].attname, arg)
912 912
 
913 913
 def method_eq(opts, self, other):
914  
-    return isinstance(other, self.__class__) and getattr(self, opts.pk.column) == getattr(other, opts.pk.column)
  914
+    return isinstance(other, self.__class__) and getattr(self, opts.pk.attname) == getattr(other, opts.pk.attname)
915 915
 
916 916
 def method_save(opts, self):
917 917
     # Run any pre-save hooks.
@@ -921,7 +921,7 @@ def method_save(opts, self):
921 921
     cursor = db.db.cursor()
922 922
 
923 923
     # First, try an UPDATE. If that doesn't update anything, do an INSERT.
924  
-    pk_val = getattr(self, opts.pk.column)
  924
+    pk_val = getattr(self, opts.pk.attname)
925 925
     pk_set = bool(pk_val)
926 926
     record_exists = True
927 927
     if pk_set:
@@ -929,33 +929,33 @@ def method_save(opts, self):
929 929
         cursor.execute("SELECT 1 FROM %s WHERE %s=%%s LIMIT 1" % (opts.db_table, opts.pk.column), [pk_val])
930 930
         # If it does already exist, do an UPDATE.
931 931
         if cursor.fetchone():
932  
-            db_values = [f.get_db_prep_save(f.pre_save(getattr(self, f.column), False)) for f in non_pks]
  932
+            db_values = [f.get_db_prep_save(f.pre_save(getattr(self, f.attname), False)) for f in non_pks]
933 933
             cursor.execute("UPDATE %s SET %s WHERE %s=%%s" % (opts.db_table, 
934  
-	            ','.join(['%s=%%s' % f.column for f in non_pks]), opts.pk.column),
  934
+                ','.join(['%s=%%s' % f.column for f in non_pks]), opts.pk.attname),
935 935
                 db_values + [pk_val])
936 936
         else:
937 937
             record_exists = False
938 938
     if not pk_set or not record_exists:
939 939
         field_names = [f.column for f in opts.fields if not isinstance(f, AutoField)]
940 940
         placeholders = ['%s'] * len(field_names)
941  
-        db_values = [f.get_db_prep_save(f.pre_save(getattr(self, f.column), True)) for f in opts.fields if not isinstance(f, AutoField)]
  941
+        db_values = [f.get_db_prep_save(f.pre_save(getattr(self, f.attname), True)) for f in opts.fields if not isinstance(f, AutoField)]
942 942
         if opts.order_with_respect_to:
943 943
             field_names.append('_order')
944 944
             # TODO: This assumes the database supports subqueries.
945 945
             placeholders.append('(SELECT COUNT(*) FROM %s WHERE %s = %%s)' % \
946 946
                 (opts.db_table, opts.order_with_respect_to.column))
947  
-            db_values.append(getattr(self, opts.order_with_respect_to.column))
  947
+            db_values.append(getattr(self, opts.order_with_respect_to.attname))
948 948
         cursor.execute("INSERT INTO %s (%s) VALUES (%s)" % (opts.db_table,
949 949
             ','.join(field_names), ','.join(placeholders)), db_values)
950 950
         if opts.has_auto_field:
951  
-            setattr(self, opts.pk.column, db.get_last_insert_id(cursor, opts.db_table, opts.pk.column))
  951
+            setattr(self, opts.pk.attname, db.get_last_insert_id(cursor, opts.db_table, opts.pk.column))
952 952
     db.db.commit()
953 953
     # Run any post-save hooks.
954 954
     if hasattr(self, '_post_save'):
955 955
         self._post_save()
956 956
 
957 957
 def method_delete(opts, self):
958  
-    assert getattr(self, opts.pk.column) is not None, "%r can't be deleted because it doesn't have an ID."
  958
+    assert getattr(self, opts.pk.attname) is not None, "%r can't be deleted because it doesn't have an ID."
959 959
     # Run any pre-delete hooks.
960 960
     if hasattr(self, '_pre_delete'):
961 961
         self._pre_delete()
@@ -974,15 +974,15 @@ def method_delete(opts, self):
974 974
                 sub_obj.delete()
975 975
     for related in opts.get_all_related_many_to_many_objects():
976 976
         cursor.execute("DELETE FROM %s WHERE %s_id=%%s" % (related.field.get_m2m_db_table(related.opts),
977  
-            self._meta.object_name.lower()), [getattr(self, opts.pk.column)])
  977
+            self._meta.object_name.lower()), [getattr(self, opts.pk.attname)])
978 978
     for f in opts.many_to_many:
979 979
         cursor.execute("DELETE FROM %s WHERE %s_id=%%s" % (f.get_m2m_db_table(opts), self._meta.object_name.lower()),
980  
-            [getattr(self, opts.pk.column)])
981  
-    cursor.execute("DELETE FROM %s WHERE %s=%%s" % (opts.db_table, opts.pk.column), [getattr(self, opts.pk.column)])
  980
+            [getattr(self, opts.pk.attname)])
  981
+    cursor.execute("DELETE FROM %s WHERE %s=%%s" % (opts.db_table, opts.pk.column), [getattr(self, opts.pk.attname)])
982 982
     db.db.commit()
983  
-    setattr(self, opts.pk.column, None)
  983
+    setattr(self, opts.pk.attname, None)
984 984
     for f in opts.fields:
985  
-        if isinstance(f, FileField) and getattr(self, f.column):
  985
+        if isinstance(f, FileField) and getattr(self, f.attname):
986 986
             file_name = getattr(self, 'get_%s_filename' % f.name)()
987 987
             # If the file exists and no other object of this type references it,
988 988
             # delete it from the filesystem.
@@ -997,7 +997,7 @@ def method_get_next_in_order(opts, order_field, self):
997 997
         self._next_in_order_cache = opts.get_model_module().get_object(order_by=('_order',),
998 998
             where=['_order > (SELECT _order FROM %s WHERE %s=%%s)' % (opts.db_table, opts.pk.column),
999 999
                 '%s=%%s' % order_field.column], limit=1,
1000  
-            params=[getattr(self, opts.pk.column), getattr(self, order_field.column)])
  1000
+            params=[getattr(self, opts.pk.attname), getattr(self, order_field.attname)])
1001 1001
     return self._next_in_order_cache
1002 1002
 
1003 1003
 def method_get_previous_in_order(opts, order_field, self):
@@ -1005,7 +1005,7 @@ def method_get_previous_in_order(opts, order_field, self):
1005 1005
         self._previous_in_order_cache = opts.get_model_module().get_object(order_by=('-_order',),
1006 1006
             where=['_order < (SELECT _order FROM %s WHERE %s=%%s)' % (opts.db_table, opts.pk.column),
1007 1007
                 '%s=%%s' % order_field.column], limit=1,
1008  
-            params=[getattr(self, opts.pk.column), getattr(self, order_field.column)])
  1008
+            params=[getattr(self, opts.pk.attname), getattr(self, order_field.attname)])
1009 1009
     return self._previous_in_order_cache
1010 1010
 
1011 1011
 # RELATIONSHIP METHODS #####################
@@ -1014,7 +1014,7 @@ def method_get_previous_in_order(opts, order_field, self):
1014 1014
 def method_get_many_to_one(field_with_rel, self):
1015 1015
     cache_var = field_with_rel.get_cache_name()
1016 1016
     if not hasattr(self, cache_var):
1017  
-        val = getattr(self, field_with_rel.column)
  1017
+        val = getattr(self, field_with_rel.attname)
1018 1018
         mod = field_with_rel.rel.to.get_model_module()
1019 1019
         if val is None:
1020 1020
             raise getattr(mod, '%sDoesNotExist' % field_with_rel.rel.to.object_name)
@@ -1034,7 +1034,7 @@ def method_get_many_to_many(field_with_rel, self):
1034 1034
             field_with_rel.get_m2m_db_table(self._meta), rel.pk.column,
1035 1035
             rel.object_name.lower(), self._meta.object_name.lower(), rel.get_order_sql('a'))
1036 1036
         cursor = db.db.cursor()
1037  
-        cursor.execute(sql, [getattr(self, self._meta.pk.column)])
  1037
+        cursor.execute(sql, [getattr(self, self._meta.pk.attname)])
1038 1038
         setattr(self, cache_var, [getattr(mod, rel.object_name)(*row) for row in cursor.fetchall()])
1039 1039
     return getattr(self, cache_var)
1040 1040
 
@@ -1055,7 +1055,7 @@ def method_set_many_to_many(rel_field, self, id_list):
1055 1055
     rel = rel_field.rel.to
1056 1056
     m2m_table = rel_field.get_m2m_db_table(self._meta)
1057 1057
     cursor = db.db.cursor()
1058  
-    this_id = getattr(self, self._meta.pk.column)
  1058
+    this_id = getattr(self, self._meta.pk.attname)
1059 1059
     if ids_to_delete:
1060 1060
         sql = "DELETE FROM %s WHERE %s_id = %%s AND %s_id IN (%s)" % (m2m_table, self._meta.object_name.lower(), rel.object_name.lower(), ','.join(map(str, ids_to_delete)))
1061 1061
         cursor.execute(sql, [this_id])
@@ -1082,11 +1082,11 @@ def method_get_related(method_name, rel_mod, rel_field, self, **kwargs):
1082 1082
 # Handles adding related objects.
1083 1083
 # Example: Poll.add_choice()
1084 1084
 def method_add_related(rel_obj, rel_mod, rel_field, self, *args, **kwargs):
1085  
-    init_kwargs = dict(zip([f.name for f in rel_obj.fields if f != rel_field and not isinstance(f, AutoField)], args))
  1085
+    init_kwargs = dict(zip([f.attname for f in rel_obj.fields if f != rel_field and not isinstance(f, AutoField)], args))
1086 1086
     init_kwargs.update(kwargs)
1087 1087
     for f in rel_obj.fields:
1088 1088
         if isinstance(f, AutoField):
1089  
-            init_kwargs[f.name] = None
  1089
+            init_kwargs[f.attname] = None
1090 1090
     init_kwargs[rel_field.name] = self
1091 1091
     obj = rel_mod.Klass(**init_kwargs)
1092 1092
     obj.save()
@@ -1095,7 +1095,7 @@ def method_add_related(rel_obj, rel_mod, rel_field, self, *args, **kwargs):
1095 1095
 # Handles related many-to-many object retrieval.
1096 1096
 # Examples: Album.get_song(), Album.get_song_list(), Album.get_song_count()
1097 1097
 def method_get_related_many_to_many(method_name, opts, rel_mod, rel_field, self, **kwargs):
1098  
-    kwargs['%s__%s__exact' % (rel_field.name, opts.pk.name)] = getattr(self, opts.pk.column)
  1098
+    kwargs['%s__%s__exact' % (rel_field.name, opts.pk.name)] = getattr(self, opts.pk.attname)
1099 1099
     return getattr(rel_mod, method_name)(**kwargs)
1100 1100
 
1101 1101
 # Handles setting many-to-many related objects.
@@ -1104,7 +1104,7 @@ def method_set_related_many_to_many(rel_opts, rel_field, self, id_list):
1104 1104
     id_list = map(int, id_list) # normalize to integers
1105 1105
     rel = rel_field.rel.to
1106 1106
     m2m_table = rel_field.get_m2m_db_table(rel_opts)
1107  
-    this_id = getattr(self, self._meta.pk.column)
  1107
+    this_id = getattr(self, self._meta.pk.attname)
1108 1108
     cursor = db.db.cursor()
1109 1109
     cursor.execute("DELETE FROM %s WHERE %s_id = %%s" % (m2m_table, rel.object_name.lower()), [this_id])
1110 1110
     sql = "INSERT INTO %s (%s_id, %s_id) VALUES (%%s, %%s)" % (m2m_table, rel.object_name.lower(), rel_opts.object_name.lower())
@@ -1133,7 +1133,7 @@ def method_get_order(ordered_obj, self):
1133 1133
 
1134 1134
 def method_get_next_or_previous(get_object_func, field, is_next, self, **kwargs):
1135 1135
     kwargs.setdefault('where', []).append('%s %s %%s' % (field.column, (is_next and '>' or '<')))
1136  
-    kwargs.setdefault('params', []).append(str(getattr(self, field.name)))
  1136
+    kwargs.setdefault('params', []).append(str(getattr(self, field.attname)))
1137 1137
     kwargs['order_by'] = [(not is_next and '-' or '') + field.name]
1138 1138
     kwargs['limit'] = 1
1139 1139
     return get_object_func(**kwargs)
@@ -1141,18 +1141,18 @@ def method_get_next_or_previous(get_object_func, field, is_next, self, **kwargs)
1141 1141
 # CHOICE-RELATED METHODS ###################
1142 1142
 
1143 1143
 def method_get_display_value(field, self):
1144  
-    value = getattr(self, field.column)
  1144
+    value = getattr(self, field.attname)
1145 1145
     return dict(field.choices).get(value, value)
1146 1146
 
1147 1147
 # FILE-RELATED METHODS #####################
1148 1148
 
1149 1149
 def method_get_file_filename(field, self):
1150  
-    return os.path.join(settings.MEDIA_ROOT, getattr(self, field.name))
  1150
+    return os.path.join(settings.MEDIA_ROOT, getattr(self, field.attname))
1151 1151
 
1152 1152
 def method_get_file_url(field, self):
1153  
-    if getattr(self, field.name): # value is not blank
  1153
+    if getattr(self, field.attname): # value is not blank
1154 1154
         import urlparse
1155  
-        return urlparse.urljoin(settings.MEDIA_URL, getattr(self, field.name)).replace('\\', '/')
  1155
+        return urlparse.urljoin(settings.MEDIA_URL, getattr(self, field.attname)).replace('\\', '/')
1156 1156
     return ''
1157 1157
 
1158 1158
 def method_get_file_size(field, self):
@@ -1177,7 +1177,7 @@ def method_save_file(field, self, filename, raw_contents):
1177 1177
             filename = filename[:dot_index] + '_' + filename[dot_index:]
1178 1178
 
1179 1179
     # Write the file to disk.
1180  
-    setattr(self, field.name, filename)
  1180
+    setattr(self, field.attname, filename)
1181 1181
     fp = open(getattr(self, 'get_%s_filename' % field.name)(), 'wb')
1182 1182
     fp.write(raw_contents)
1183 1183
     fp.close()
@@ -1504,7 +1504,7 @@ def function_get_in_bulk(opts, klass, *args, **kwargs):
1504 1504
     kwargs['where'] = ["%s.%s IN (%s)" % (opts.db_table, opts.pk.column, ",".join(['%s'] * len(id_list)))]
1505 1505
     kwargs['params'] = id_list
1506 1506
     obj_list = function_get_list(opts, klass, **kwargs)
1507  
-    return dict([(getattr(o, opts.pk.column), o) for o in obj_list])
  1507
+    return dict([(getattr(o, opts.pk.attname), o) for o in obj_list])
1508 1508
 
1509 1509
 def function_get_latest(opts, klass, does_not_exist_exception, **kwargs):
1510 1510
     kwargs['order_by'] = ('-' + opts.get_latest_by,)
@@ -1578,8 +1578,8 @@ def manipulator_init(opts, add, change, self, obj_key=None, follow=None):
1578 1578
                 lookup_kwargs = opts.one_to_one_field.rel.limit_choices_to
1579 1579
                 lookup_kwargs['%s__exact' % opts.one_to_one_field.rel.field_name] = obj_key
1580 1580
                 _ = opts.one_to_one_field.rel.to.get_model_module().get_object(**lookup_kwargs)
1581  
-                params = dict([(f.column, f.get_default()) for f in opts.fields])
1582  
-                params[opts.pk.column] = obj_key
  1581
+                params = dict([(f.attname, f.get_default()) for f in opts.fields])
  1582
+                params[opts.pk.attname] = obj_key
1583 1583
                 self.original_object = opts.get_model_module().Klass(**params)
1584 1584
             else:
1585 1585
                 raise
@@ -1610,14 +1610,14 @@ def manipulator_save(opts, klass, add, change, self, new_data):
1610 1610
             param = f.get_manipulator_new_data(new_data)
1611 1611
         else:
1612 1612
             if change:
1613  
-                param = getattr(self.original_object, f.column)
  1613
+                param = getattr(self.original_object, f.attname)
1614 1614
             else:
1615 1615
                 param = f.get_default()
1616  
-        params[f.column] = param    
  1616
+        params[f.attname] = param    
1617 1617
     
1618 1618
 
1619 1619
     if change:
1620  
-        params[opts.pk.column] = self.obj_key
  1620
+        params[opts.pk.attname] = self.obj_key
1621 1621
 
1622 1622
     # First, save the basic object itself.
1623 1623
     new_object = klass(**params)
@@ -1632,7 +1632,7 @@ def manipulator_save(opts, klass, add, change, self, new_data):
1632 1632
     if change:
1633 1633
         self.fields_added, self.fields_changed, self.fields_deleted = [], [], []
1634 1634
         for f in opts.fields:
1635  
-            if not f.primary_key and str(getattr(self.original_object, f.column)) != str(getattr(new_object, f.column)):
  1635
+            if not f.primary_key and str(getattr(self.original_object, f.attname)) != str(getattr(new_object, f.attname)):
1636 1636
                 self.fields_changed.append(f.verbose_name)
1637 1637
 
1638 1638
     # Save many-to-many objects. Example: Poll.set_sites()
@@ -1674,7 +1674,7 @@ def manipulator_save(opts, klass, add, change, self, new_data):
1674 1674
                 if change:
1675 1675
                     if rel_new_data[related.opts.pk.name][0]:
1676 1676
                         try:
1677  
-                            old_rel_obj = getattr(self.original_object, 'get_%s' % related.get_method_name_part() )(**{'%s__exact' % related.opts.pk.name: rel_new_data[related.opts.pk.name][0]})
  1677
+                            old_rel_obj = getattr(self.original_object, 'get_%s' % related.get_method_name_part() )(**{'%s__exact' % related.opts.pk.name: rel_new_data[related.opts.pk.attname][0]})
1678 1678
                         except ObjectDoesNotExist:
1679 1679
                             pass
1680 1680
 
@@ -1700,7 +1700,7 @@ def manipulator_save(opts, klass, add, change, self, new_data):
1700 1700
                     else:
1701 1701
                         param = f.get_manipulator_new_data(rel_new_data, rel=True)
1702 1702
                     if param != None:
1703  
-                       params[f.column] = param
  1703
+                       params[f.attname] = param
1704 1704
                     
1705 1705
 
1706 1706
                     # Related links are a special case, because we have to
@@ -1731,13 +1731,13 @@ def manipulator_save(opts, klass, add, change, self, new_data):
1731 1731
                             self.fields_added.append('%s "%s"' % (related.opts.verbose_name, new_rel_obj))
1732 1732
                         else:
1733 1733
                             for f in related.opts.fields:
1734  
-                                if not f.primary_key and f != related.field and str(getattr(old_rel_obj, f.column)) != str(getattr(new_rel_obj, f.column)):
  1734
+                                if not f.primary_key and f != related.field and str(getattr(old_rel_obj, f.attname)) != str(getattr(new_rel_obj, f.attname)):
1735 1735
                                     self.fields_changed.append('%s for %s "%s"' % (f.verbose_name, related.opts.verbose_name, new_rel_obj))
1736 1736
 
1737 1737
                     # Save many-to-many objects.
1738 1738
                     for f in related.opts.many_to_many:
1739 1739
                         if child_follow.get(f.name, None) and not f.rel.edit_inline:
1740  
-                            was_changed = getattr(new_rel_obj, 'set_%s' % f.name)(rel_new_data[f.name])
  1740
+                            was_changed = getattr(new_rel_obj, 'set_%s' % f.name)(rel_new_data[f.attname])
1741 1741
                             if change and was_changed:
1742 1742
                                 self.fields_changed.append('%s for %s "%s"' % (f.verbose_name, related.opts.verbose_name, new_rel_obj))
1743 1743
 
@@ -1777,7 +1777,7 @@ def manipulator_validator_unique_together(field_name_list, opts, self, field_dat
1777 1777
     for f in field_list[1:]:
1778 1778
         # This is really not going to work for fields that have different form fields, eg DateTime 
1779 1779
         # This validation needs to occur after html2python to be effective. 
1780  
-        field_val = all_data.get(f.column, None)
  1780
+        field_val = all_data.get(f.attname, None)
1781 1781
         if field_val is None:
1782 1782
             # This will be caught by another validator, assuming the field
1783 1783
             # doesn't have blank=True.
@@ -1791,7 +1791,7 @@ def manipulator_validator_unique_together(field_name_list, opts, self, field_dat
1791 1791
         old_obj = mod.get_object(**kwargs)
1792 1792
     except ObjectDoesNotExist:
1793 1793
         return
1794  
-    if hasattr(self, 'original_object') and getattr(self.original_object, opts.pk.column) == getattr(old_obj, opts.pk.column):
  1794
+    if hasattr(self, 'original_object') and getattr(self.original_object, opts.pk.attname) == getattr(old_obj, opts.pk.attname):
1795 1795
         pass
1796 1796
     else:
1797 1797
         raise validators.ValidationError, "%s with this %s already exists for the given %s." % \
@@ -1817,7 +1817,7 @@ def manipulator_validator_unique_for_date(from_field, date_field, opts, lookup_t
1817 1817
     except ObjectDoesNotExist:
1818 1818
         return
1819 1819
     else:
1820  
-        if hasattr(self, 'original_object') and getattr(self.original_object, opts.pk.column) == getattr(old_obj, opts.pk.column):
  1820
+        if hasattr(self, 'original_object') and getattr(self.original_object, opts.pk.attname) == getattr(old_obj, opts.pk.attname):
1821 1821
             pass
1822 1822
         else:
1823 1823
             format_string = (lookup_type == 'date') and '%B %d, %Y' or '%B %Y'
33  django/core/meta/fields.py
@@ -55,10 +55,24 @@ def manipulator_validator_unique(f, opts, self, field_data, all_data):
55 55
         old_obj = opts.get_model_module().get_object(**{'%s__%s' % (f.name, lookup_type): field_data})
56 56
     except ObjectDoesNotExist:
57 57
         return
58  
-    if hasattr(self, 'original_object') and getattr(self.original_object, opts.pk.column) == getattr(old_obj, opts.pk.column):
  58
+    if hasattr(self, 'original_object') and getattr(self.original_object, opts.pk.attname) == getattr(old_obj, opts.pk.attname):
59 59
         return
60 60
     raise validators.ValidationError, "%s with this %s already exists." % (capfirst(opts.verbose_name), f.verbose_name)
61 61
 
  62
+# A guide to Field parameters:
  63
+#
  64
+#   * name:      The name of the field specifed in the model.
  65
+#   * attname:   The attribute to use on the model object. This is the same as
  66
+#                "name", except in the case of ForeignKeys, where "_id" is
  67
+#                appended.
  68
+#   * db_column: The db_column specified in the model (or None).
  69
+#   * column:    The database column for this field. This is the same as
  70
+#                "attname", except if db_column is specified.
  71
+#
  72
+# Code that introspects values, or does other dynamic things, should use
  73
+# attname. For example, this gets the primary key value of object "obj":
  74
+#
  75
+#     getattr(obj, opts.pk.attname)
62 76
 class BoundField(object):
63 77
     def __init__(self, field, field_mapping, original):
64 78
         self.field = field
@@ -129,19 +143,20 @@ def __init__(self, verbose_name=None, name=None, primary_key=False,
129 143
         self.creation_counter = Field.creation_counter
130 144
         Field.creation_counter += 1
131 145
 
132  
-        # Set the name of the database column.
133  
-        self.column = self.get_db_column()
  146
+        self.attname, self.column = self.get_attname_column()
134 147
 
135 148
     def set_name(self, name):
136 149
         self.name = name
137 150
         self.verbose_name = self.verbose_name or name.replace('_', ' ')
138  
-        self.column = self.get_db_column()
  151
+        self.attname, self.column = self.get_attname_column()
139 152
 
140  
-    def get_db_column(self):
141  
-        if self.db_column: return self.db_column
  153
+    def get_attname_column(self):
142 154
         if isinstance(self.rel, ManyToOne):
143  
-            return '%s_id' % self.name
144  
-        return self.name
  155
+            attname = '%s_id' % self.name
  156
+        else:
  157
+            attname = self.name
  158
+        column = self.db_column or attname
  159
+        return attname, column
145 160
 
146 161
     def get_cache_name(self):
147 162
         return '_%s_cache' % self.name
@@ -297,7 +312,7 @@ def get_choices(self, include_blank=True, blank_choice=BLANK_CHOICE_DASH):
297 312
         if self.choices:
298 313
             return first_choice + list(self.choices)
299 314
         rel_obj = self.rel.to
300  
-        return first_choice + [(getattr(x, rel_obj.pk.column), str(x)) for x in rel_obj.get_model_module().get_list(**self.rel.limit_choices_to)]
  315
+        return first_choice + [(getattr(x, rel_obj.pk.attlist), str(x)) for x in rel_obj.get_model_module().get_list(**self.rel.limit_choices_to)]
301 316
 
302 317
     def get_choices_default(self):
303 318
         if(self.radio_admin):
4  django/models/auth.py
@@ -13,7 +13,7 @@ class META:
13 13
         ordering = ('package', 'codename')
14 14
 
15 15
     def __repr__(self):
16  
-        return "%s | %s" % (self.package, self.name)
  16
+        return "%s | %s" % (self.package_id, self.name)
17 17
 
18 18
 class Group(meta.Model):
19 19
     name = meta.CharField(_('name'), maxlength=80, unique=True)
@@ -103,7 +103,7 @@ def get_group_permissions(self):
103 103
     def get_all_permissions(self):
104 104
         if not hasattr(self, '_perm_cache'):
105 105
             import sets
106  
-            self._perm_cache = sets.Set(["%s.%s" % (p.package, p.codename) for p in self.get_permission_list()])
  106
+            self._perm_cache = sets.Set(["%s.%s" % (p.package_id, p.codename) for p in self.get_permission_list()])
107 107
             self._perm_cache.update(self.get_group_permissions())
108 108
         return self._perm_cache
109 109
 
4  django/models/core.py
@@ -48,11 +48,11 @@ class META:
48 48
         unique_together = (('package', 'python_module_name'),)
49 49
 
50 50
     def __repr__(self):
51  
-        return "%s | %s" % (self.package, self.name)
  51
+        return "%s | %s" % (self.package_id, self.name)
52 52
 
53 53
     def get_model_module(self):
54 54
         "Returns the Python model module for accessing this type of content."
55  
-        return __import__('django.models.%s.%s' % (self.package, self.python_module_name), '', '', [''])
  55
+        return __import__('django.models.%s.%s' % (self.package_id, self.python_module_name), '', '', [''])
56 56
 
57 57
     def get_object_for_this_type(self, **kwargs):
58 58
         """
10  tests/othertests/dateformat.py
@@ -30,9 +30,7 @@
30 30
 >>> format(my_birthday, 'S')
31 31
 'th'
32 32
 >>> format(my_birthday, 't')
33  
-Traceback (most recent call last):
34  
-    ...
35  
-NotImplementedError
  33
+'31'
36 34
 >>> format(my_birthday, 'T')
37 35
 'CET'
38 36
 >>> format(my_birthday, 'U')
@@ -63,11 +61,13 @@
63 61
 '1979 188 CET'
64 62
 """
65 63
 
66  
-from django.utils import dateformat
67  
-format = dateformat.format
  64
+from django.utils import dateformat, translation
68 65
 import datetime, os, time
69 66
 
  67
+format = dateformat.format
70 68
 os.environ['TZ'] = 'Europe/Copenhagen'
  69
+translation.activate('en-us')
  70
+
71 71
 time.tzset()
72 72
 
73 73
 my_birthday = datetime.datetime(1979, 7, 7, 22, 00)
2  tests/testapp/models/__init__.py
... ...
@@ -1,4 +1,4 @@
1 1
 __all__ = ['basic', 'repr', 'custom_methods', 'many_to_one', 'many_to_many',
2 2
            'ordering', 'lookup', 'get_latest', 'm2m_intermediary', 'one_to_one',
3 3
            'm2o_recursive', 'm2o_recursive2', 'save_delete_hooks', 'custom_pk',
4  
-           'subclassing', 'many_to_one_null']
  4
+           'subclassing', 'many_to_one_null', 'custom_columns']
53  tests/testapp/models/custom_columns.py
... ...
@@ -0,0 +1,53 @@
  1
+"""
  2
+17. Custom column names
  3
+
  4
+If your database column name is different than your model attribute, use the
  5
+``db_column`` parameter. Note that you'll use the field's name, not its column
  6
+name, in API usage.
  7
+"""
  8
+
  9
+from django.core import meta
  10
+
  11
+class Person(meta.Model):
  12
+    first_name = meta.CharField(maxlength=30, db_column='firstname')
  13
+    last_name = meta.CharField(maxlength=30, db_column='last')
  14
+
  15
+    def __repr__(self):
  16
+        return '%s %s' % (self.first_name, self.last_name)
  17
+
  18
+API_TESTS = """
  19
+# Create a Person.
  20
+>>> p = persons.Person(first_name='John', last_name='Smith')
  21
+>>> p.save()
  22
+
  23
+>>> p.id
  24
+1
  25
+
  26
+>>> persons.get_list()
  27
+[John Smith]
  28
+
  29
+>>> persons.get_list(first_name__exact='John')
  30
+[John Smith]
  31
+
  32
+>>> persons.get_object(first_name__exact='John')
  33
+John Smith
  34
+
  35
+>>> persons.get_list(firstname__exact='John')
  36
+Traceback (most recent call last):
  37
+    ...
  38
+TypeError: got unexpected keyword argument 'firstname__exact'
  39
+
  40
+>>> p = persons.get_object(last_name__exact='Smith')
  41
+>>> p.first_name
  42
+'John'
  43
+>>> p.last_name
  44
+'Smith'
  45
+>>> p.firstname
  46
+Traceback (most recent call last):
  47
+    ...
  48
+AttributeError: 'Person' object has no attribute 'firstname'
  49
+>>> p.last
  50
+Traceback (most recent call last):
  51
+    ...
  52
+AttributeError: 'Person' object has no attribute 'last'
  53
+"""
33  tests/testapp/models/lookup.py
@@ -18,18 +18,24 @@ def __repr__(self):
18 18
 API_TESTS = """
19 19
 # Create a couple of Articles.
20 20
 >>> from datetime import datetime
21  
->>> a1 = articles.Article(id=None, headline='Article 1', pub_date=datetime(2005, 7, 26))
  21
+>>> a1 = articles.Article(headline='Article 1', pub_date=datetime(2005, 7, 26))
22 22
 >>> a1.save()
23  
->>> a2 = articles.Article(id=None, headline='Article 2', pub_date=datetime(2005, 7, 27))
  23
+>>> a2 = articles.Article(headline='Article 2', pub_date=datetime(2005, 7, 27))
24 24
 >>> a2.save()
25  
->>> a3 = articles.Article(id=None, headline='Article 3', pub_date=datetime(2005, 7, 27))
  25
+>>> a3 = articles.Article(headline='Article 3', pub_date=datetime(2005, 7, 27))
26 26
 >>> a3.save()
27  
->>> a4 = articles.Article(id=None, headline='Article 4', pub_date=datetime(2005, 7, 28))
  27
+>>> a4 = articles.Article(headline='Article 4', pub_date=datetime(2005, 7, 28))
28 28
 >>> a4.save()
  29
+>>> a5 = articles.Article(headline='Article 5', pub_date=datetime(2005, 8, 1, 9, 0))
  30
+>>> a5.save()
  31
+>>> a6 = articles.Article(headline='Article 6', pub_date=datetime(2005, 8, 1, 8, 0))
  32
+>>> a6.save()
29 33
 
30 34
 # get_iterator() is just like get_list(), but it's a generator.
31 35
 >>> for a in articles.get_iterator():
32 36
 ...     print a.headline
  37
+Article 5
  38
+Article 6
33 39
 Article 4
34 40
 Article 2
35 41
 Article 3
@@ -42,7 +48,7 @@ def __repr__(self):
42 48
 
43 49
 # get_count() returns the number of objects matching search criteria.
44 50
 >>> articles.get_count()
45  
-4L
  51
+6L
46 52
 >>> articles.get_count(pub_date__exact=datetime(2005, 7, 27))
47 53
 2L
48 54
 >>> articles.get_count(headline__startswith='Blah blah')
@@ -61,10 +67,10 @@ def __repr__(self):
61 67
 # dictionaries instead of object instances -- and you can specify which fields
62 68
 # you want to retrieve.
63 69
 >>> articles.get_values(fields=['headline'])
64  
-[{'headline': 'Article 4'}, {'headline': 'Article 2'}, {'headline': 'Article 3'}, {'headline': 'Article 1'}]
  70
+[{'headline': 'Article 5'}, {'headline': 'Article 6'}, {'headline': 'Article 4'}, {'headline': 'Article 2'}, {'headline': 'Article 3'}, {'headline': 'Article 1'}]
65 71
 >>> articles.get_values(pub_date__exact=datetime(2005, 7, 27), fields=['id'])
66 72
 [{'id': 2}, {'id': 3}]
67  
->>> articles.get_values(fields=['id', 'headline']) == [{'id': 4, 'headline': 'Article 4'}, {'id': 2, 'headline': 'Article 2'}, {'id': 3, 'headline': 'Article 3'}, {'id': 1, 'headline': 'Article 1'}]
  73
+>>> articles.get_values(fields=['id', 'headline']) == [{'id': 5, 'headline': 'Article 5'}, {'id': 6, 'headline': 'Article 6'}, {'id': 4, 'headline': 'Article 4'}, {'id': 2, 'headline': 'Article 2'}, {'id': 3, 'headline': 'Article 3'}, {'id': 1, 'headline': 'Article 1'}]
68 74
 True
69 75
 
70 76
 # get_values_iterator() is just like get_values(), but it's a generator.
@@ -72,6 +78,8 @@ def __repr__(self):
72 78
 ...     i = d.items()
73 79
 ...     i.sort()
74 80
 ...     i
  81
+[('headline', 'Article 5'), ('id', 5)]
  82
+[('headline', 'Article 6'), ('id', 6)]
75 83
 [('headline', 'Article 4'), ('id', 4)]
76 84
 [('headline', 'Article 2'), ('id', 2)]
77 85
 [('headline', 'Article 3'), ('id', 3)]
@@ -84,4 +92,15 @@ def __repr__(self):
84 92
 >>> a2.get_previous_by_pub_date()
85 93
 Article 1
86 94
 
  95
+# get_next_by_FOO() and get_previous_by_FOO() take the time into account.
  96
+>>> a4.get_next_by_pub_date()
  97
+Article 6
  98
+>>> a5.get_next_by_pub_date()
  99
+Traceback (most recent call last):
  100
+    ...
  101
+ArticleDoesNotExist: Article does not exist for ...
  102
+>>> a6.get_previous_by_pub_date()
  103
+Article 4
  104
+>>> a5.get_previous_by_pub_date()
  105
+Article 6
87 106
 """

0 notes on commit dbaf9c6

Please sign in to comment.
Something went wrong with that request. Please try again.