Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
D
django
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
django
Commits
cc337a74
Kaydet (Commit)
cc337a74
authored
Eki 06, 2012
tarafından
Russell Keith-Magee
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Fixed #19069 -- Improved the error message when trying to query a swapped model.
Thanks to Preston Holmes for the suggestion.
üst
12f39be5
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
201 additions
and
17 deletions
+201
-17
manager.py
django/db/models/manager.py
+35
-2
models.py
tests/regressiontests/managers_regress/models.py
+13
-0
tests.py
tests/regressiontests/managers_regress/tests.py
+153
-15
No files found.
django/db/models/manager.py
Dosyayı görüntüle @
cc337a74
...
@@ -13,7 +13,11 @@ def ensure_default_manager(sender, **kwargs):
...
@@ -13,7 +13,11 @@ def ensure_default_manager(sender, **kwargs):
_default_manager if it's not a subclass of Manager).
_default_manager if it's not a subclass of Manager).
"""
"""
cls
=
sender
cls
=
sender
if
cls
.
_meta
.
abstract
or
cls
.
_meta
.
swapped
:
if
cls
.
_meta
.
abstract
:
setattr
(
cls
,
'objects'
,
AbstractManagerDescriptor
(
cls
))
return
elif
cls
.
_meta
.
swapped
:
setattr
(
cls
,
'objects'
,
SwappedManagerDescriptor
(
cls
))
return
return
if
not
getattr
(
cls
,
'_default_manager'
,
None
):
if
not
getattr
(
cls
,
'_default_manager'
,
None
):
# Create the default manager, if needed.
# Create the default manager, if needed.
...
@@ -58,7 +62,12 @@ class Manager(object):
...
@@ -58,7 +62,12 @@ class Manager(object):
# TODO: Use weakref because of possible memory leak / circular reference.
# TODO: Use weakref because of possible memory leak / circular reference.
self
.
model
=
model
self
.
model
=
model
# Only contribute the manager if the model is concrete
# Only contribute the manager if the model is concrete
if
not
model
.
_meta
.
abstract
and
not
model
.
_meta
.
swapped
:
if
model
.
_meta
.
abstract
:
setattr
(
model
,
name
,
AbstractManagerDescriptor
(
model
))
elif
model
.
_meta
.
swapped
:
setattr
(
model
,
name
,
SwappedManagerDescriptor
(
model
))
else
:
# if not model._meta.abstract and not model._meta.swapped:
setattr
(
model
,
name
,
ManagerDescriptor
(
self
))
setattr
(
model
,
name
,
ManagerDescriptor
(
self
))
if
not
getattr
(
model
,
'_default_manager'
,
None
)
or
self
.
creation_counter
<
model
.
_default_manager
.
creation_counter
:
if
not
getattr
(
model
,
'_default_manager'
,
None
)
or
self
.
creation_counter
<
model
.
_default_manager
.
creation_counter
:
model
.
_default_manager
=
self
model
.
_default_manager
=
self
...
@@ -224,6 +233,30 @@ class ManagerDescriptor(object):
...
@@ -224,6 +233,30 @@ class ManagerDescriptor(object):
return
self
.
manager
return
self
.
manager
class
AbstractManagerDescriptor
(
object
):
# This class provides a better error message when you try to access a
# manager on an abstract model.
def
__init__
(
self
,
model
):
self
.
model
=
model
def
__get__
(
self
,
instance
,
type
=
None
):
raise
AttributeError
(
"Manager isn't available;
%
s is abstract"
%
(
self
.
model
.
_meta
.
object_name
,
))
class
SwappedManagerDescriptor
(
object
):
# This class provides a better error message when you try to access a
# manager on a swapped model.
def
__init__
(
self
,
model
):
self
.
model
=
model
def
__get__
(
self
,
instance
,
type
=
None
):
raise
AttributeError
(
"Manager isn't available;
%
s has been swapped for '
%
s'"
%
(
self
.
model
.
_meta
.
object_name
,
self
.
model
.
_meta
.
swapped
))
class
EmptyManager
(
Manager
):
class
EmptyManager
(
Manager
):
def
get_query_set
(
self
):
def
get_query_set
(
self
):
return
self
.
get_empty_query_set
()
return
self
.
get_empty_query_set
()
tests/regressiontests/managers_regress/models.py
Dosyayı görüntüle @
cc337a74
...
@@ -10,14 +10,17 @@ class OnlyFred(models.Manager):
...
@@ -10,14 +10,17 @@ class OnlyFred(models.Manager):
def
get_query_set
(
self
):
def
get_query_set
(
self
):
return
super
(
OnlyFred
,
self
)
.
get_query_set
()
.
filter
(
name
=
'fred'
)
return
super
(
OnlyFred
,
self
)
.
get_query_set
()
.
filter
(
name
=
'fred'
)
class
OnlyBarney
(
models
.
Manager
):
class
OnlyBarney
(
models
.
Manager
):
def
get_query_set
(
self
):
def
get_query_set
(
self
):
return
super
(
OnlyBarney
,
self
)
.
get_query_set
()
.
filter
(
name
=
'barney'
)
return
super
(
OnlyBarney
,
self
)
.
get_query_set
()
.
filter
(
name
=
'barney'
)
class
Value42
(
models
.
Manager
):
class
Value42
(
models
.
Manager
):
def
get_query_set
(
self
):
def
get_query_set
(
self
):
return
super
(
Value42
,
self
)
.
get_query_set
()
.
filter
(
value
=
42
)
return
super
(
Value42
,
self
)
.
get_query_set
()
.
filter
(
value
=
42
)
class
AbstractBase1
(
models
.
Model
):
class
AbstractBase1
(
models
.
Model
):
name
=
models
.
CharField
(
max_length
=
50
)
name
=
models
.
CharField
(
max_length
=
50
)
...
@@ -29,6 +32,7 @@ class AbstractBase1(models.Model):
...
@@ -29,6 +32,7 @@ class AbstractBase1(models.Model):
manager2
=
OnlyBarney
()
manager2
=
OnlyBarney
()
objects
=
models
.
Manager
()
objects
=
models
.
Manager
()
class
AbstractBase2
(
models
.
Model
):
class
AbstractBase2
(
models
.
Model
):
value
=
models
.
IntegerField
()
value
=
models
.
IntegerField
()
...
@@ -38,6 +42,7 @@ class AbstractBase2(models.Model):
...
@@ -38,6 +42,7 @@ class AbstractBase2(models.Model):
# Custom manager
# Custom manager
restricted
=
Value42
()
restricted
=
Value42
()
# No custom manager on this class to make sure the default case doesn't break.
# No custom manager on this class to make sure the default case doesn't break.
class
AbstractBase3
(
models
.
Model
):
class
AbstractBase3
(
models
.
Model
):
comment
=
models
.
CharField
(
max_length
=
50
)
comment
=
models
.
CharField
(
max_length
=
50
)
...
@@ -45,6 +50,7 @@ class AbstractBase3(models.Model):
...
@@ -45,6 +50,7 @@ class AbstractBase3(models.Model):
class
Meta
:
class
Meta
:
abstract
=
True
abstract
=
True
@python_2_unicode_compatible
@python_2_unicode_compatible
class
Parent
(
models
.
Model
):
class
Parent
(
models
.
Model
):
name
=
models
.
CharField
(
max_length
=
50
)
name
=
models
.
CharField
(
max_length
=
50
)
...
@@ -54,6 +60,7 @@ class Parent(models.Model):
...
@@ -54,6 +60,7 @@ class Parent(models.Model):
def
__str__
(
self
):
def
__str__
(
self
):
return
self
.
name
return
self
.
name
# Managers from base classes are inherited and, if no manager is specified
# Managers from base classes are inherited and, if no manager is specified
# *and* the parent has a manager specified, the first one (in the MRO) will
# *and* the parent has a manager specified, the first one (in the MRO) will
# become the default.
# become the default.
...
@@ -64,6 +71,7 @@ class Child1(AbstractBase1):
...
@@ -64,6 +71,7 @@ class Child1(AbstractBase1):
def
__str__
(
self
):
def
__str__
(
self
):
return
self
.
data
return
self
.
data
@python_2_unicode_compatible
@python_2_unicode_compatible
class
Child2
(
AbstractBase1
,
AbstractBase2
):
class
Child2
(
AbstractBase1
,
AbstractBase2
):
data
=
models
.
CharField
(
max_length
=
25
)
data
=
models
.
CharField
(
max_length
=
25
)
...
@@ -71,6 +79,7 @@ class Child2(AbstractBase1, AbstractBase2):
...
@@ -71,6 +79,7 @@ class Child2(AbstractBase1, AbstractBase2):
def
__str__
(
self
):
def
__str__
(
self
):
return
self
.
data
return
self
.
data
@python_2_unicode_compatible
@python_2_unicode_compatible
class
Child3
(
AbstractBase1
,
AbstractBase3
):
class
Child3
(
AbstractBase1
,
AbstractBase3
):
data
=
models
.
CharField
(
max_length
=
25
)
data
=
models
.
CharField
(
max_length
=
25
)
...
@@ -78,6 +87,7 @@ class Child3(AbstractBase1, AbstractBase3):
...
@@ -78,6 +87,7 @@ class Child3(AbstractBase1, AbstractBase3):
def
__str__
(
self
):
def
__str__
(
self
):
return
self
.
data
return
self
.
data
@python_2_unicode_compatible
@python_2_unicode_compatible
class
Child4
(
AbstractBase1
):
class
Child4
(
AbstractBase1
):
data
=
models
.
CharField
(
max_length
=
25
)
data
=
models
.
CharField
(
max_length
=
25
)
...
@@ -89,6 +99,7 @@ class Child4(AbstractBase1):
...
@@ -89,6 +99,7 @@ class Child4(AbstractBase1):
def
__str__
(
self
):
def
__str__
(
self
):
return
self
.
data
return
self
.
data
@python_2_unicode_compatible
@python_2_unicode_compatible
class
Child5
(
AbstractBase3
):
class
Child5
(
AbstractBase3
):
name
=
models
.
CharField
(
max_length
=
25
)
name
=
models
.
CharField
(
max_length
=
25
)
...
@@ -99,10 +110,12 @@ class Child5(AbstractBase3):
...
@@ -99,10 +110,12 @@ class Child5(AbstractBase3):
def
__str__
(
self
):
def
__str__
(
self
):
return
self
.
name
return
self
.
name
# Will inherit managers from AbstractBase1, but not Child4.
# Will inherit managers from AbstractBase1, but not Child4.
class
Child6
(
Child4
):
class
Child6
(
Child4
):
value
=
models
.
IntegerField
()
value
=
models
.
IntegerField
()
# Will not inherit default manager from parent.
# Will not inherit default manager from parent.
class
Child7
(
Parent
):
class
Child7
(
Parent
):
pass
pass
tests/regressiontests/managers_regress/tests.py
Dosyayı görüntüle @
cc337a74
from
__future__
import
absolute_import
from
__future__
import
absolute_import
import
copy
from
django.conf
import
settings
from
django.db
import
models
from
django.db.models.loading
import
cache
from
django.test
import
TestCase
from
django.test
import
TestCase
from
django.test.utils
import
override_settings
from
.models
import
Child1
,
Child2
,
Child3
,
Child4
,
Child5
,
Child6
,
Child7
from
.models
import
(
Child1
,
Child2
,
Child3
,
Child4
,
Child5
,
Child6
,
Child7
,
AbstractBase1
,
AbstractBase2
,
AbstractBase3
,
)
class
ManagersRegressionTests
(
TestCase
):
class
ManagersRegressionTests
(
TestCase
):
def
test_managers
(
self
):
def
test_managers
(
self
):
a1
=
Child1
.
objects
.
create
(
name
=
'fred'
,
data
=
'a1'
)
Child1
.
objects
.
create
(
name
=
'fred'
,
data
=
'a1'
)
a2
=
Child1
.
objects
.
create
(
name
=
'barney'
,
data
=
'a2'
)
Child1
.
objects
.
create
(
name
=
'barney'
,
data
=
'a2'
)
b1
=
Child2
.
objects
.
create
(
name
=
'fred'
,
data
=
'b1'
,
value
=
1
)
Child2
.
objects
.
create
(
name
=
'fred'
,
data
=
'b1'
,
value
=
1
)
b2
=
Child2
.
objects
.
create
(
name
=
'barney'
,
data
=
'b2'
,
value
=
42
)
Child2
.
objects
.
create
(
name
=
'barney'
,
data
=
'b2'
,
value
=
42
)
c1
=
Child3
.
objects
.
create
(
name
=
'fred'
,
data
=
'c1'
,
comment
=
'yes'
)
Child3
.
objects
.
create
(
name
=
'fred'
,
data
=
'c1'
,
comment
=
'yes'
)
c2
=
Child3
.
objects
.
create
(
name
=
'barney'
,
data
=
'c2'
,
comment
=
'no'
)
Child3
.
objects
.
create
(
name
=
'barney'
,
data
=
'c2'
,
comment
=
'no'
)
d1
=
Child4
.
objects
.
create
(
name
=
'fred'
,
data
=
'd1'
)
Child4
.
objects
.
create
(
name
=
'fred'
,
data
=
'd1'
)
d2
=
Child4
.
objects
.
create
(
name
=
'barney'
,
data
=
'd2'
)
Child4
.
objects
.
create
(
name
=
'barney'
,
data
=
'd2'
)
e1
=
Child5
.
objects
.
create
(
name
=
'fred'
,
comment
=
'yes'
)
Child5
.
objects
.
create
(
name
=
'fred'
,
comment
=
'yes'
)
e2
=
Child5
.
objects
.
create
(
name
=
'barney'
,
comment
=
'no'
)
Child5
.
objects
.
create
(
name
=
'barney'
,
comment
=
'no'
)
f1
=
Child6
.
objects
.
create
(
name
=
'fred'
,
data
=
'f1'
,
value
=
42
)
Child6
.
objects
.
create
(
name
=
'fred'
,
data
=
'f1'
,
value
=
42
)
f2
=
Child6
.
objects
.
create
(
name
=
'barney'
,
data
=
'f2'
,
value
=
42
)
Child6
.
objects
.
create
(
name
=
'barney'
,
data
=
'f2'
,
value
=
42
)
g1
=
Child7
.
objects
.
create
(
name
=
'fred'
)
Child7
.
objects
.
create
(
name
=
'fred'
)
g2
=
Child7
.
objects
.
create
(
name
=
'barney'
)
Child7
.
objects
.
create
(
name
=
'barney'
)
self
.
assertQuerysetEqual
(
Child1
.
manager1
.
all
(),
[
"<Child1: a1>"
])
self
.
assertQuerysetEqual
(
Child1
.
manager1
.
all
(),
[
"<Child1: a1>"
])
self
.
assertQuerysetEqual
(
Child1
.
manager2
.
all
(),
[
"<Child1: a2>"
])
self
.
assertQuerysetEqual
(
Child1
.
manager2
.
all
(),
[
"<Child1: a2>"
])
...
@@ -54,3 +70,125 @@ class ManagersRegressionTests(TestCase):
...
@@ -54,3 +70,125 @@ class ManagersRegressionTests(TestCase):
"<Child7: fred>"
"<Child7: fred>"
]
]
)
)
def
test_abstract_manager
(
self
):
# Accessing the manager on an abstract model should
# raise an attribute error with an appropriate message.
try
:
AbstractBase3
.
objects
.
all
()
self
.
fail
(
'Should raise an AttributeError'
)
except
AttributeError
as
e
:
# This error message isn't ideal, but if the model is abstract and
# a lot of the class instantiation logic isn't invoked; if the
# manager is implied, then we don't get a hook to install the
# error-raising manager.
self
.
assertEqual
(
str
(
e
),
"type object 'AbstractBase3' has no attribute 'objects'"
)
def
test_custom_abstract_manager
(
self
):
# Accessing the manager on an abstract model with an custom
# manager should raise an attribute error with an appropriate
# message.
try
:
AbstractBase2
.
restricted
.
all
()
self
.
fail
(
'Should raise an AttributeError'
)
except
AttributeError
as
e
:
self
.
assertEqual
(
str
(
e
),
"Manager isn't available; AbstractBase2 is abstract"
)
def
test_explicit_abstract_manager
(
self
):
# Accessing the manager on an abstract model with an explicit
# manager should raise an attribute error with an appropriate
# message.
try
:
AbstractBase1
.
objects
.
all
()
self
.
fail
(
'Should raise an AttributeError'
)
except
AttributeError
as
e
:
self
.
assertEqual
(
str
(
e
),
"Manager isn't available; AbstractBase1 is abstract"
)
def
test_swappable_manager
(
self
):
try
:
# This test adds dummy models to the app cache. These
# need to be removed in order to prevent bad interactions
# with the flush operation in other tests.
old_app_models
=
copy
.
deepcopy
(
cache
.
app_models
)
old_app_store
=
copy
.
deepcopy
(
cache
.
app_store
)
settings
.
TEST_SWAPPABLE_MODEL
=
'managers_regress.Parent'
class
SwappableModel
(
models
.
Model
):
class
Meta
:
swappable
=
'TEST_SWAPPABLE_MODEL'
# Accessing the manager on a swappable model should
# raise an attribute error with a helpful message
try
:
SwappableModel
.
objects
.
all
()
self
.
fail
(
'Should raise an AttributeError'
)
except
AttributeError
as
e
:
self
.
assertEqual
(
str
(
e
),
"Manager isn't available; SwappableModel has been swapped for 'managers_regress.Parent'"
)
finally
:
del
settings
.
TEST_SWAPPABLE_MODEL
cache
.
app_models
=
old_app_models
cache
.
app_store
=
old_app_store
def
test_custom_swappable_manager
(
self
):
try
:
# This test adds dummy models to the app cache. These
# need to be removed in order to prevent bad interactions
# with the flush operation in other tests.
old_app_models
=
copy
.
deepcopy
(
cache
.
app_models
)
old_app_store
=
copy
.
deepcopy
(
cache
.
app_store
)
settings
.
TEST_SWAPPABLE_MODEL
=
'managers_regress.Parent'
class
SwappableModel
(
models
.
Model
):
stuff
=
models
.
Manager
()
class
Meta
:
swappable
=
'TEST_SWAPPABLE_MODEL'
# Accessing the manager on a swappable model with an
# explicit manager should raise an attribute error with a
# helpful message
try
:
SwappableModel
.
stuff
.
all
()
self
.
fail
(
'Should raise an AttributeError'
)
except
AttributeError
as
e
:
self
.
assertEqual
(
str
(
e
),
"Manager isn't available; SwappableModel has been swapped for 'managers_regress.Parent'"
)
finally
:
del
settings
.
TEST_SWAPPABLE_MODEL
cache
.
app_models
=
old_app_models
cache
.
app_store
=
old_app_store
def
test_explicit_swappable_manager
(
self
):
try
:
# This test adds dummy models to the app cache. These
# need to be removed in order to prevent bad interactions
# with the flush operation in other tests.
old_app_models
=
copy
.
deepcopy
(
cache
.
app_models
)
old_app_store
=
copy
.
deepcopy
(
cache
.
app_store
)
settings
.
TEST_SWAPPABLE_MODEL
=
'managers_regress.Parent'
class
SwappableModel
(
models
.
Model
):
objects
=
models
.
Manager
()
class
Meta
:
swappable
=
'TEST_SWAPPABLE_MODEL'
# Accessing the manager on a swappable model with an
# explicit manager should raise an attribute error with a
# helpful message
try
:
SwappableModel
.
objects
.
all
()
self
.
fail
(
'Should raise an AttributeError'
)
except
AttributeError
as
e
:
self
.
assertEqual
(
str
(
e
),
"Manager isn't available; SwappableModel has been swapped for 'managers_regress.Parent'"
)
finally
:
del
settings
.
TEST_SWAPPABLE_MODEL
cache
.
app_models
=
old_app_models
cache
.
app_store
=
old_app_store
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment