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
16a5a2a2
Kaydet (Commit)
16a5a2a2
authored
Ock 04, 2019
tarafından
Joshua Cannon
Kaydeden (comit)
Tim Graham
Ock 30, 2019
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Fixed #30076 -- Added Model.get_FOO_display() even if field's choices are empty.
üst
bae66e75
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
80 additions
and
9 deletions
+80
-9
__init__.py
django/db/models/fields/__init__.py
+10
-8
models.py
tests/model_fields/models.py
+16
-0
tests.py
tests/model_fields/tests.py
+54
-1
No files found.
django/db/models/fields/__init__.py
Dosyayı görüntüle @
16a5a2a2
...
@@ -153,7 +153,7 @@ class Field(RegisterLookupMixin):
...
@@ -153,7 +153,7 @@ class Field(RegisterLookupMixin):
self
.
unique_for_year
=
unique_for_year
self
.
unique_for_year
=
unique_for_year
if
isinstance
(
choices
,
collections
.
abc
.
Iterator
):
if
isinstance
(
choices
,
collections
.
abc
.
Iterator
):
choices
=
list
(
choices
)
choices
=
list
(
choices
)
self
.
choices
=
choices
or
[]
self
.
choices
=
choices
self
.
help_text
=
help_text
self
.
help_text
=
help_text
self
.
db_index
=
db_index
self
.
db_index
=
db_index
self
.
db_column
=
db_column
self
.
db_column
=
db_column
...
@@ -443,7 +443,7 @@ class Field(RegisterLookupMixin):
...
@@ -443,7 +443,7 @@ class Field(RegisterLookupMixin):
"unique_for_date"
:
None
,
"unique_for_date"
:
None
,
"unique_for_month"
:
None
,
"unique_for_month"
:
None
,
"unique_for_year"
:
None
,
"unique_for_year"
:
None
,
"choices"
:
[]
,
"choices"
:
None
,
"help_text"
:
''
,
"help_text"
:
''
,
"db_column"
:
None
,
"db_column"
:
None
,
"db_tablespace"
:
None
,
"db_tablespace"
:
None
,
...
@@ -598,7 +598,7 @@ class Field(RegisterLookupMixin):
...
@@ -598,7 +598,7 @@ class Field(RegisterLookupMixin):
# Skip validation for non-editable fields.
# Skip validation for non-editable fields.
return
return
if
self
.
choices
and
value
not
in
self
.
empty_values
:
if
self
.
choices
is
not
None
and
value
not
in
self
.
empty_values
:
for
option_key
,
option_value
in
self
.
choices
:
for
option_key
,
option_value
in
self
.
choices
:
if
isinstance
(
option_value
,
(
list
,
tuple
)):
if
isinstance
(
option_value
,
(
list
,
tuple
)):
# This is an optgroup, so look inside the group for
# This is an optgroup, so look inside the group for
...
@@ -742,7 +742,7 @@ class Field(RegisterLookupMixin):
...
@@ -742,7 +742,7 @@ class Field(RegisterLookupMixin):
# such fields can't be deferred (we don't have a check for this).
# such fields can't be deferred (we don't have a check for this).
if
not
getattr
(
cls
,
self
.
attname
,
None
):
if
not
getattr
(
cls
,
self
.
attname
,
None
):
setattr
(
cls
,
self
.
attname
,
DeferredAttribute
(
self
.
attname
))
setattr
(
cls
,
self
.
attname
,
DeferredAttribute
(
self
.
attname
))
if
self
.
choices
:
if
self
.
choices
is
not
None
:
setattr
(
cls
,
'get_
%
s_display'
%
self
.
name
,
setattr
(
cls
,
'get_
%
s_display'
%
self
.
name
,
partialmethod
(
cls
.
_get_FIELD_display
,
field
=
self
))
partialmethod
(
cls
.
_get_FIELD_display
,
field
=
self
))
...
@@ -812,7 +812,7 @@ class Field(RegisterLookupMixin):
...
@@ -812,7 +812,7 @@ class Field(RegisterLookupMixin):
Return choices with a default blank choices included, for use
Return choices with a default blank choices included, for use
as <select> choices for this field.
as <select> choices for this field.
"""
"""
if
self
.
choices
:
if
self
.
choices
is
not
None
:
choices
=
list
(
self
.
choices
)
choices
=
list
(
self
.
choices
)
if
include_blank
:
if
include_blank
:
blank_defined
=
any
(
choice
in
(
''
,
None
)
for
choice
,
_
in
self
.
flatchoices
)
blank_defined
=
any
(
choice
in
(
''
,
None
)
for
choice
,
_
in
self
.
flatchoices
)
...
@@ -840,6 +840,8 @@ class Field(RegisterLookupMixin):
...
@@ -840,6 +840,8 @@ class Field(RegisterLookupMixin):
def
_get_flatchoices
(
self
):
def
_get_flatchoices
(
self
):
"""Flattened version of choices tuple."""
"""Flattened version of choices tuple."""
if
self
.
choices
is
None
:
return
[]
flat
=
[]
flat
=
[]
for
choice
,
value
in
self
.
choices
:
for
choice
,
value
in
self
.
choices
:
if
isinstance
(
value
,
(
list
,
tuple
)):
if
isinstance
(
value
,
(
list
,
tuple
)):
...
@@ -865,7 +867,7 @@ class Field(RegisterLookupMixin):
...
@@ -865,7 +867,7 @@ class Field(RegisterLookupMixin):
defaults
[
'show_hidden_initial'
]
=
True
defaults
[
'show_hidden_initial'
]
=
True
else
:
else
:
defaults
[
'initial'
]
=
self
.
get_default
()
defaults
[
'initial'
]
=
self
.
get_default
()
if
self
.
choices
:
if
self
.
choices
is
not
None
:
# Fields with choices get special treatment.
# Fields with choices get special treatment.
include_blank
=
(
self
.
blank
or
include_blank
=
(
self
.
blank
or
not
(
self
.
has_default
()
or
'initial'
in
kwargs
))
not
(
self
.
has_default
()
or
'initial'
in
kwargs
))
...
@@ -1018,7 +1020,7 @@ class BooleanField(Field):
...
@@ -1018,7 +1020,7 @@ class BooleanField(Field):
return
self
.
to_python
(
value
)
return
self
.
to_python
(
value
)
def
formfield
(
self
,
**
kwargs
):
def
formfield
(
self
,
**
kwargs
):
if
self
.
choices
:
if
self
.
choices
is
not
None
:
include_blank
=
not
(
self
.
has_default
()
or
'initial'
in
kwargs
)
include_blank
=
not
(
self
.
has_default
()
or
'initial'
in
kwargs
)
defaults
=
{
'choices'
:
self
.
get_choices
(
include_blank
=
include_blank
)}
defaults
=
{
'choices'
:
self
.
get_choices
(
include_blank
=
include_blank
)}
else
:
else
:
...
@@ -2080,7 +2082,7 @@ class TextField(Field):
...
@@ -2080,7 +2082,7 @@ class TextField(Field):
# the value in the form field (to pass into widget for example).
# the value in the form field (to pass into widget for example).
return
super
()
.
formfield
(
**
{
return
super
()
.
formfield
(
**
{
'max_length'
:
self
.
max_length
,
'max_length'
:
self
.
max_length
,
**
({}
if
self
.
choices
else
{
'widget'
:
forms
.
Textarea
}),
**
({}
if
self
.
choices
is
not
None
else
{
'widget'
:
forms
.
Textarea
}),
**
kwargs
,
**
kwargs
,
})
})
...
...
tests/model_fields/models.py
Dosyayı görüntüle @
16a5a2a2
...
@@ -50,6 +50,14 @@ class Whiz(models.Model):
...
@@ -50,6 +50,14 @@ class Whiz(models.Model):
c
=
models
.
IntegerField
(
choices
=
CHOICES
,
null
=
True
)
c
=
models
.
IntegerField
(
choices
=
CHOICES
,
null
=
True
)
class
WhizDelayed
(
models
.
Model
):
c
=
models
.
IntegerField
(
choices
=
(),
null
=
True
)
# Contrived way of adding choices later.
WhizDelayed
.
_meta
.
get_field
(
'c'
)
.
choices
=
Whiz
.
CHOICES
class
WhizIter
(
models
.
Model
):
class
WhizIter
(
models
.
Model
):
c
=
models
.
IntegerField
(
choices
=
iter
(
Whiz
.
CHOICES
),
null
=
True
)
c
=
models
.
IntegerField
(
choices
=
iter
(
Whiz
.
CHOICES
),
null
=
True
)
...
@@ -58,6 +66,14 @@ class WhizIterEmpty(models.Model):
...
@@ -58,6 +66,14 @@ class WhizIterEmpty(models.Model):
c
=
models
.
CharField
(
choices
=
iter
(()),
blank
=
True
,
max_length
=
1
)
c
=
models
.
CharField
(
choices
=
iter
(()),
blank
=
True
,
max_length
=
1
)
class
Choiceful
(
models
.
Model
):
no_choices
=
models
.
IntegerField
(
null
=
True
)
empty_choices
=
models
.
IntegerField
(
choices
=
(),
null
=
True
)
with_choices
=
models
.
IntegerField
(
choices
=
[(
1
,
'A'
)],
null
=
True
)
empty_choices_bool
=
models
.
BooleanField
(
choices
=
())
empty_choices_text
=
models
.
TextField
(
choices
=
())
class
BigD
(
models
.
Model
):
class
BigD
(
models
.
Model
):
d
=
models
.
DecimalField
(
max_digits
=
32
,
decimal_places
=
30
)
d
=
models
.
DecimalField
(
max_digits
=
32
,
decimal_places
=
30
)
...
...
tests/model_fields/tests.py
Dosyayı görüntüle @
16a5a2a2
import
pickle
import
pickle
from
django
import
forms
from
django
import
forms
from
django.core.exceptions
import
ValidationError
from
django.db
import
models
from
django.db
import
models
from
django.test
import
SimpleTestCase
,
TestCase
from
django.test
import
SimpleTestCase
,
TestCase
from
django.utils.functional
import
lazy
from
django.utils.functional
import
lazy
from
.models
import
(
from
.models
import
(
Bar
,
Foo
,
RenamedField
,
VerboseNameField
,
Whiz
,
WhizIter
,
WhizIterEmpty
,
Bar
,
Choiceful
,
Foo
,
RenamedField
,
VerboseNameField
,
Whiz
,
WhizDelayed
,
WhizIter
,
WhizIterEmpty
,
)
)
...
@@ -103,6 +105,51 @@ class BasicFieldTests(SimpleTestCase):
...
@@ -103,6 +105,51 @@ class BasicFieldTests(SimpleTestCase):
class
ChoicesTests
(
SimpleTestCase
):
class
ChoicesTests
(
SimpleTestCase
):
@classmethod
def
setUpClass
(
cls
):
super
()
.
setUpClass
()
cls
.
no_choices
=
Choiceful
.
_meta
.
get_field
(
'no_choices'
)
cls
.
empty_choices
=
Choiceful
.
_meta
.
get_field
(
'empty_choices'
)
cls
.
empty_choices_bool
=
Choiceful
.
_meta
.
get_field
(
'empty_choices_bool'
)
cls
.
empty_choices_text
=
Choiceful
.
_meta
.
get_field
(
'empty_choices_text'
)
cls
.
with_choices
=
Choiceful
.
_meta
.
get_field
(
'with_choices'
)
def
test_choices
(
self
):
self
.
assertIsNone
(
self
.
no_choices
.
choices
)
self
.
assertEqual
(
self
.
empty_choices
.
choices
,
())
self
.
assertEqual
(
self
.
with_choices
.
choices
,
[(
1
,
'A'
)])
def
test_flatchoices
(
self
):
self
.
assertEqual
(
self
.
no_choices
.
flatchoices
,
[])
self
.
assertEqual
(
self
.
empty_choices
.
flatchoices
,
[])
self
.
assertEqual
(
self
.
with_choices
.
flatchoices
,
[(
1
,
'A'
)])
def
test_check
(
self
):
self
.
assertEqual
(
Choiceful
.
check
(),
[])
def
test_invalid_choice
(
self
):
model_instance
=
None
# Actual model instance not needed.
self
.
no_choices
.
validate
(
0
,
model_instance
)
msg
=
"['Value 99 is not a valid choice.']"
with
self
.
assertRaisesMessage
(
ValidationError
,
msg
):
self
.
empty_choices
.
validate
(
99
,
model_instance
)
with
self
.
assertRaisesMessage
(
ValidationError
,
msg
):
self
.
with_choices
.
validate
(
99
,
model_instance
)
def
test_formfield
(
self
):
no_choices_formfield
=
self
.
no_choices
.
formfield
()
self
.
assertIsInstance
(
no_choices_formfield
,
forms
.
IntegerField
)
fields
=
(
self
.
empty_choices
,
self
.
with_choices
,
self
.
empty_choices_bool
,
self
.
empty_choices_text
,
)
for
field
in
fields
:
with
self
.
subTest
(
field
=
field
):
self
.
assertIsInstance
(
field
.
formfield
(),
forms
.
ChoiceField
)
class
GetFieldDisplayTests
(
SimpleTestCase
):
def
test_choices_and_field_display
(
self
):
def
test_choices_and_field_display
(
self
):
"""
"""
get_choices() interacts with get_FIELD_display() to return the expected
get_choices() interacts with get_FIELD_display() to return the expected
...
@@ -113,6 +160,7 @@ class ChoicesTests(SimpleTestCase):
...
@@ -113,6 +160,7 @@ class ChoicesTests(SimpleTestCase):
self
.
assertEqual
(
Whiz
(
c
=
9
)
.
get_c_display
(),
9
)
# Invalid value
self
.
assertEqual
(
Whiz
(
c
=
9
)
.
get_c_display
(),
9
)
# Invalid value
self
.
assertIsNone
(
Whiz
(
c
=
None
)
.
get_c_display
())
# Blank value
self
.
assertIsNone
(
Whiz
(
c
=
None
)
.
get_c_display
())
# Blank value
self
.
assertEqual
(
Whiz
(
c
=
''
)
.
get_c_display
(),
''
)
# Empty value
self
.
assertEqual
(
Whiz
(
c
=
''
)
.
get_c_display
(),
''
)
# Empty value
self
.
assertEqual
(
WhizDelayed
(
c
=
0
)
.
get_c_display
(),
'Other'
)
# Delayed choices
def
test_iterator_choices
(
self
):
def
test_iterator_choices
(
self
):
"""
"""
...
@@ -135,6 +183,11 @@ class ChoicesTests(SimpleTestCase):
...
@@ -135,6 +183,11 @@ class ChoicesTests(SimpleTestCase):
class
GetChoicesTests
(
SimpleTestCase
):
class
GetChoicesTests
(
SimpleTestCase
):
def
test_empty_choices
(
self
):
choices
=
[]
f
=
models
.
CharField
(
choices
=
choices
)
self
.
assertEqual
(
f
.
get_choices
(
include_blank
=
False
),
choices
)
def
test_blank_in_choices
(
self
):
def
test_blank_in_choices
(
self
):
choices
=
[(
''
,
'<><>'
),
(
'a'
,
'A'
)]
choices
=
[(
''
,
'<><>'
),
(
'a'
,
'A'
)]
f
=
models
.
CharField
(
choices
=
choices
)
f
=
models
.
CharField
(
choices
=
choices
)
...
...
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