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):
self
.
unique_for_year
=
unique_for_year
if
isinstance
(
choices
,
collections
.
abc
.
Iterator
):
choices
=
list
(
choices
)
self
.
choices
=
choices
or
[]
self
.
choices
=
choices
self
.
help_text
=
help_text
self
.
db_index
=
db_index
self
.
db_column
=
db_column
...
...
@@ -443,7 +443,7 @@ class Field(RegisterLookupMixin):
"unique_for_date"
:
None
,
"unique_for_month"
:
None
,
"unique_for_year"
:
None
,
"choices"
:
[]
,
"choices"
:
None
,
"help_text"
:
''
,
"db_column"
:
None
,
"db_tablespace"
:
None
,
...
...
@@ -598,7 +598,7 @@ class Field(RegisterLookupMixin):
# Skip validation for non-editable fields.
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
:
if
isinstance
(
option_value
,
(
list
,
tuple
)):
# This is an optgroup, so look inside the group for
...
...
@@ -742,7 +742,7 @@ class Field(RegisterLookupMixin):
# such fields can't be deferred (we don't have a check for this).
if
not
getattr
(
cls
,
self
.
attname
,
None
):
setattr
(
cls
,
self
.
attname
,
DeferredAttribute
(
self
.
attname
))
if
self
.
choices
:
if
self
.
choices
is
not
None
:
setattr
(
cls
,
'get_
%
s_display'
%
self
.
name
,
partialmethod
(
cls
.
_get_FIELD_display
,
field
=
self
))
...
...
@@ -812,7 +812,7 @@ class Field(RegisterLookupMixin):
Return choices with a default blank choices included, for use
as <select> choices for this field.
"""
if
self
.
choices
:
if
self
.
choices
is
not
None
:
choices
=
list
(
self
.
choices
)
if
include_blank
:
blank_defined
=
any
(
choice
in
(
''
,
None
)
for
choice
,
_
in
self
.
flatchoices
)
...
...
@@ -840,6 +840,8 @@ class Field(RegisterLookupMixin):
def
_get_flatchoices
(
self
):
"""Flattened version of choices tuple."""
if
self
.
choices
is
None
:
return
[]
flat
=
[]
for
choice
,
value
in
self
.
choices
:
if
isinstance
(
value
,
(
list
,
tuple
)):
...
...
@@ -865,7 +867,7 @@ class Field(RegisterLookupMixin):
defaults
[
'show_hidden_initial'
]
=
True
else
:
defaults
[
'initial'
]
=
self
.
get_default
()
if
self
.
choices
:
if
self
.
choices
is
not
None
:
# Fields with choices get special treatment.
include_blank
=
(
self
.
blank
or
not
(
self
.
has_default
()
or
'initial'
in
kwargs
))
...
...
@@ -1018,7 +1020,7 @@ class BooleanField(Field):
return
self
.
to_python
(
value
)
def
formfield
(
self
,
**
kwargs
):
if
self
.
choices
:
if
self
.
choices
is
not
None
:
include_blank
=
not
(
self
.
has_default
()
or
'initial'
in
kwargs
)
defaults
=
{
'choices'
:
self
.
get_choices
(
include_blank
=
include_blank
)}
else
:
...
...
@@ -2080,7 +2082,7 @@ class TextField(Field):
# the value in the form field (to pass into widget for example).
return
super
()
.
formfield
(
**
{
'max_length'
:
self
.
max_length
,
**
({}
if
self
.
choices
else
{
'widget'
:
forms
.
Textarea
}),
**
({}
if
self
.
choices
is
not
None
else
{
'widget'
:
forms
.
Textarea
}),
**
kwargs
,
})
...
...
tests/model_fields/models.py
Dosyayı görüntüle @
16a5a2a2
...
...
@@ -50,6 +50,14 @@ class Whiz(models.Model):
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
):
c
=
models
.
IntegerField
(
choices
=
iter
(
Whiz
.
CHOICES
),
null
=
True
)
...
...
@@ -58,6 +66,14 @@ class WhizIterEmpty(models.Model):
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
):
d
=
models
.
DecimalField
(
max_digits
=
32
,
decimal_places
=
30
)
...
...
tests/model_fields/tests.py
Dosyayı görüntüle @
16a5a2a2
import
pickle
from
django
import
forms
from
django.core.exceptions
import
ValidationError
from
django.db
import
models
from
django.test
import
SimpleTestCase
,
TestCase
from
django.utils.functional
import
lazy
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):
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
):
"""
get_choices() interacts with get_FIELD_display() to return the expected
...
...
@@ -113,6 +160,7 @@ class ChoicesTests(SimpleTestCase):
self
.
assertEqual
(
Whiz
(
c
=
9
)
.
get_c_display
(),
9
)
# Invalid value
self
.
assertIsNone
(
Whiz
(
c
=
None
)
.
get_c_display
())
# Blank 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
):
"""
...
...
@@ -135,6 +183,11 @@ class ChoicesTests(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
):
choices
=
[(
''
,
'<><>'
),
(
'a'
,
'A'
)]
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