mirror of https://github.com/django/django.git
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:
parent
89df572c47
commit
6cd37e0a1f
|
@ -132,12 +132,13 @@ class RelatedField(object):
|
|||
v, field = getattr(v, v._meta.pk.name), v._meta.pk
|
||||
except AttributeError:
|
||||
pass
|
||||
if field:
|
||||
if lookup_type in ('range', 'in'):
|
||||
v = [v]
|
||||
v = field.get_db_prep_lookup(lookup_type, v)
|
||||
if isinstance(v, list):
|
||||
v = v[0]
|
||||
if not field:
|
||||
field = self.rel.get_related_field()
|
||||
if lookup_type in ('range', 'in'):
|
||||
v = [v]
|
||||
v = field.get_db_prep_lookup(lookup_type, v)
|
||||
if isinstance(v, list):
|
||||
v = v[0]
|
||||
return v
|
||||
|
||||
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,
|
||||
# so return None.
|
||||
return None
|
||||
|
||||
|
|
|
@ -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
|
|
@ -9,6 +9,8 @@ this behavior by explicitly adding ``primary_key=True`` to a field.
|
|||
from django.conf import settings
|
||||
from django.db import models, transaction, IntegrityError
|
||||
|
||||
from fields import MyAutoField
|
||||
|
||||
class Employee(models.Model):
|
||||
employee_code = models.IntegerField(primary_key=True, db_column = 'code')
|
||||
first_name = models.CharField(max_length=20)
|
||||
|
@ -28,6 +30,16 @@ class Business(models.Model):
|
|||
def __unicode__(self):
|
||||
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':"""
|
||||
>>> dan = Employee(employee_code=123, first_name='Dan', last_name='Jones')
|
||||
>>> dan.save()
|
||||
|
@ -121,6 +133,21 @@ DoesNotExist: Employee matching query does not exist.
|
|||
... print "Fail with %s" % type(e)
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue