Fixed #10785 -- Corrected a case for foreign key lookup where the related object is a custom primary key. Thanks to Alex Gaynor for the patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@10952 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Russell Keith-Magee 2009-06-08 04:50:24 +00:00
parent 89df572c47
commit 6cd37e0a1f
3 changed files with 88 additions and 7 deletions

View File

@ -132,12 +132,13 @@ class RelatedField(object):
v, field = getattr(v, v._meta.pk.name), v._meta.pk v, field = getattr(v, v._meta.pk.name), v._meta.pk
except AttributeError: except AttributeError:
pass pass
if field: if not field:
if lookup_type in ('range', 'in'): field = self.rel.get_related_field()
v = [v] if lookup_type in ('range', 'in'):
v = field.get_db_prep_lookup(lookup_type, v) v = [v]
if isinstance(v, list): v = field.get_db_prep_lookup(lookup_type, v)
v = v[0] if isinstance(v, list):
v = v[0]
return v return v
if hasattr(value, 'as_sql') or hasattr(value, '_as_sql'): if hasattr(value, 'as_sql') or hasattr(value, '_as_sql'):
@ -958,4 +959,3 @@ class ManyToManyField(RelatedField, Field):
# A ManyToManyField is not represented by a single column, # A ManyToManyField is not represented by a single column,
# so return None. # so return None.
return None return None

View File

@ -0,0 +1,54 @@
import random
import string
from django.db import models
class MyWrapper(object):
def __init__(self, value):
self.value = value
def __repr__(self):
return "<%s: %s>" % (self.__class__.__name__, self.value)
def __unicode__(self):
return self.value
def __eq__(self, other):
if isinstance(other, self.__class__):
return self.value == other.value
return self.value == other
class MyAutoField(models.CharField):
__metaclass__ = models.SubfieldBase
def __init__(self, *args, **kwargs):
kwargs['max_length'] = 10
super(MyAutoField, self).__init__(*args, **kwargs)
def pre_save(self, instance, add):
value = getattr(instance, self.attname, None)
if not value:
value = MyWrapper(''.join(random.sample(string.lowercase, 10)))
setattr(instance, self.attname, value)
return value
def to_python(self, value):
if not value:
return
if not isinstance(value, MyWrapper):
value = MyWrapper(value)
return value
def get_db_prep_save(self, value):
if not value:
return
if isinstance(value, MyWrapper):
return unicode(value)
return value
def get_db_prep_value(self, value):
if not value:
return
if isinstance(value, MyWrapper):
return unicode(value)
return value

View File

@ -9,6 +9,8 @@ this behavior by explicitly adding ``primary_key=True`` to a field.
from django.conf import settings from django.conf import settings
from django.db import models, transaction, IntegrityError from django.db import models, transaction, IntegrityError
from fields import MyAutoField
class Employee(models.Model): class Employee(models.Model):
employee_code = models.IntegerField(primary_key=True, db_column = 'code') employee_code = models.IntegerField(primary_key=True, db_column = 'code')
first_name = models.CharField(max_length=20) first_name = models.CharField(max_length=20)
@ -28,6 +30,16 @@ class Business(models.Model):
def __unicode__(self): def __unicode__(self):
return self.name return self.name
class Bar(models.Model):
id = MyAutoField(primary_key=True, db_index=True)
def __unicode__(self):
return repr(self.pk)
class Foo(models.Model):
bar = models.ForeignKey(Bar)
__test__ = {'API_TESTS':""" __test__ = {'API_TESTS':"""
>>> dan = Employee(employee_code=123, first_name='Dan', last_name='Jones') >>> dan = Employee(employee_code=123, first_name='Dan', last_name='Jones')
>>> dan.save() >>> dan.save()
@ -121,6 +133,21 @@ DoesNotExist: Employee matching query does not exist.
... print "Fail with %s" % type(e) ... print "Fail with %s" % type(e)
Pass Pass
# Regression for #10785 -- Custom fields can be used for primary keys.
>>> new_bar = Bar.objects.create()
>>> new_foo = Foo.objects.create(bar=new_bar)
>>> f = Foo.objects.get(bar=new_bar.pk)
>>> f == new_foo
True
>>> f.bar == new_bar
True
>>> f = Foo.objects.get(bar=new_bar)
>>> f == new_foo
True
>>> f.bar == new_bar
True
"""} """}
# SQLite lets objects be saved with an empty primary key, even though an # SQLite lets objects be saved with an empty primary key, even though an