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
3d4a8261
Kaydet (Commit)
3d4a8261
authored
Ock 23, 2015
tarafından
Andriy Sokolovskiy
Kaydeden (comit)
Markus Holtermann
Ock 27, 2015
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
[1.7.x] Fixed #24104 -- Fixed check to look on field.get_internal_type() instead of class instance
üst
6dc6ec21
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
109 additions
and
8 deletions
+109
-8
schema.py
django/db/backends/schema.py
+2
-3
schema.py
django/db/backends/sqlite3/schema.py
+4
-5
1.7.4.txt
docs/releases/1.7.4.txt
+4
-0
fields.py
tests/schema/fields.py
+54
-0
tests.py
tests/schema/tests.py
+45
-0
No files found.
django/db/backends/schema.py
Dosyayı görüntüle @
3d4a8261
...
...
@@ -3,7 +3,6 @@ import operator
from
django.db.backends.creation
import
BaseDatabaseCreation
from
django.db.backends.utils
import
truncate_name
from
django.db.models.fields.related
import
ManyToManyField
from
django.db.transaction
import
atomic
from
django.utils.encoding
import
force_bytes
from
django.utils.log
import
getLogger
...
...
@@ -359,7 +358,7 @@ class BaseDatabaseSchemaEditor(object):
table instead (for M2M fields)
"""
# Special-case implicit M2M tables
if
isinstance
(
field
,
ManyToManyField
)
and
field
.
rel
.
through
.
_meta
.
auto_created
:
if
field
.
get_internal_type
()
==
'ManyToManyField'
and
field
.
rel
.
through
.
_meta
.
auto_created
:
return
self
.
create_model
(
field
.
rel
.
through
)
# Get the column's definition
definition
,
params
=
self
.
column_sql
(
model
,
field
,
include_default
=
True
)
...
...
@@ -403,7 +402,7 @@ class BaseDatabaseSchemaEditor(object):
but for M2Ms may involve deleting a table.
"""
# Special-case implicit M2M tables
if
isinstance
(
field
,
ManyToManyField
)
and
field
.
rel
.
through
.
_meta
.
auto_created
:
if
field
.
get_internal_type
()
==
'ManyToManyField'
and
field
.
rel
.
through
.
_meta
.
auto_created
:
return
self
.
delete_model
(
field
.
rel
.
through
)
# It might not actually have a column behind it
if
field
.
db_parameters
(
connection
=
self
.
connection
)[
'type'
]
is
None
:
...
...
django/db/backends/sqlite3/schema.py
Dosyayı görüntüle @
3d4a8261
...
...
@@ -4,7 +4,6 @@ from decimal import Decimal
from
django.utils
import
six
from
django.apps.registry
import
Apps
from
django.db.backends.schema
import
BaseDatabaseSchemaEditor
from
django.db.models.fields.related
import
ManyToManyField
class
DatabaseSchemaEditor
(
BaseDatabaseSchemaEditor
):
...
...
@@ -70,7 +69,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
for
field
in
create_fields
:
body
[
field
.
name
]
=
field
# Choose a default and insert it into the copy map
if
not
isinstance
(
field
,
ManyToManyField
)
:
if
not
field
.
get_internal_type
()
==
'ManyToManyField'
:
mapping
[
field
.
column
]
=
self
.
quote_value
(
self
.
effective_default
(
field
)
)
...
...
@@ -93,7 +92,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
del
body
[
field
.
name
]
del
mapping
[
field
.
column
]
# Remove any implicit M2M tables
if
isinstance
(
field
,
ManyToManyField
)
and
field
.
rel
.
through
.
_meta
.
auto_created
:
if
field
.
get_internal_type
()
==
'ManyToManyField'
and
field
.
rel
.
through
.
_meta
.
auto_created
:
return
self
.
delete_model
(
field
.
rel
.
through
)
# Work inside a new app registry
apps
=
Apps
()
...
...
@@ -172,7 +171,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
table instead (for M2M fields)
"""
# Special-case implicit M2M tables
if
isinstance
(
field
,
ManyToManyField
)
and
field
.
rel
.
through
.
_meta
.
auto_created
:
if
field
.
get_internal_type
()
==
'ManyToManyField'
and
field
.
rel
.
through
.
_meta
.
auto_created
:
return
self
.
create_model
(
field
.
rel
.
through
)
self
.
_remake_table
(
model
,
create_fields
=
[
field
])
...
...
@@ -182,7 +181,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
but for M2Ms may involve deleting a table.
"""
# M2M fields are a special case
if
isinstance
(
field
,
ManyToManyField
)
:
if
field
.
get_internal_type
()
==
'ManyToManyField'
:
# For implicit M2M tables, delete the auto-created table
if
field
.
rel
.
through
.
_meta
.
auto_created
:
self
.
delete_model
(
field
.
rel
.
through
)
...
...
docs/releases/1.7.4.txt
Dosyayı görüntüle @
3d4a8261
...
...
@@ -20,3 +20,7 @@ Bugfixes
* Prevented the ``static.serve`` view from producing ``ResourceWarning``\s in
certain circumstances (security fix regression, :ticket:`24193`).
* Fixed schema check for ``ManyToManyField`` to look for internal type instead
of checking class instance, so you can write custom m2m-like fields with the
same behavior. (:ticket:`24104`).
tests/schema/fields.py
0 → 100644
Dosyayı görüntüle @
3d4a8261
from
django.db.models.fields.related
import
(
create_many_to_many_intermediary_model
,
ManyToManyField
,
ManyToManyRel
,
RelatedField
,
RECURSIVE_RELATIONSHIP_CONSTANT
,
ReverseManyRelatedObjectsDescriptor
,
)
from
django.utils.functional
import
curry
class
CustomManyToManyField
(
RelatedField
):
"""
Ticket #24104 - Need to have a custom ManyToManyField,
which is not an inheritor of ManyToManyField.
"""
def
__init__
(
self
,
to
,
db_constraint
=
True
,
swappable
=
True
,
**
kwargs
):
try
:
to
.
_meta
except
AttributeError
:
to
=
str
(
to
)
kwargs
[
'verbose_name'
]
=
kwargs
.
get
(
'verbose_name'
,
None
)
kwargs
[
'rel'
]
=
ManyToManyRel
(
to
,
related_name
=
kwargs
.
pop
(
'related_name'
,
None
),
related_query_name
=
kwargs
.
pop
(
'related_query_name'
,
None
),
limit_choices_to
=
kwargs
.
pop
(
'limit_choices_to'
,
None
),
symmetrical
=
kwargs
.
pop
(
'symmetrical'
,
to
==
RECURSIVE_RELATIONSHIP_CONSTANT
),
through
=
kwargs
.
pop
(
'through'
,
None
),
through_fields
=
kwargs
.
pop
(
'through_fields'
,
None
),
db_constraint
=
db_constraint
,
)
self
.
swappable
=
swappable
self
.
db_table
=
kwargs
.
pop
(
'db_table'
,
None
)
if
kwargs
[
'rel'
]
.
through
is
not
None
:
assert
self
.
db_table
is
None
,
"Cannot specify a db_table if an intermediary model is used."
super
(
CustomManyToManyField
,
self
)
.
__init__
(
**
kwargs
)
def
contribute_to_class
(
self
,
cls
,
name
):
if
self
.
rel
.
symmetrical
and
(
self
.
rel
.
to
==
"self"
or
self
.
rel
.
to
==
cls
.
_meta
.
object_name
):
self
.
rel
.
related_name
=
"
%
s_rel_+"
%
name
super
(
CustomManyToManyField
,
self
)
.
contribute_to_class
(
cls
,
name
)
if
not
self
.
rel
.
through
and
not
cls
.
_meta
.
abstract
and
not
cls
.
_meta
.
swapped
:
self
.
rel
.
through
=
create_many_to_many_intermediary_model
(
self
,
cls
)
setattr
(
cls
,
self
.
name
,
ReverseManyRelatedObjectsDescriptor
(
self
))
self
.
m2m_db_table
=
curry
(
self
.
_get_m2m_db_table
,
cls
.
_meta
)
def
get_internal_type
(
self
):
return
'ManyToManyField'
# Copy those methods from ManyToManyField because they don't call super() internally
contribute_to_related_class
=
ManyToManyField
.
__dict__
[
'contribute_to_related_class'
]
set_attributes_from_rel
=
ManyToManyField
.
__dict__
[
'set_attributes_from_rel'
]
_get_m2m_attr
=
ManyToManyField
.
__dict__
[
'_get_m2m_attr'
]
_get_m2m_reverse_attr
=
ManyToManyField
.
__dict__
[
'_get_m2m_reverse_attr'
]
_get_m2m_db_table
=
ManyToManyField
.
__dict__
[
'_get_m2m_db_table'
]
tests/schema/tests.py
Dosyayı görüntüle @
3d4a8261
...
...
@@ -7,6 +7,7 @@ from django.db.models.fields import (BinaryField, BooleanField, CharField, Integ
PositiveIntegerField
,
SlugField
,
TextField
)
from
django.db.models.fields.related
import
ForeignKey
,
ManyToManyField
,
OneToOneField
from
django.db.transaction
import
atomic
from
.fields
import
CustomManyToManyField
from
.models
import
(
Author
,
AuthorWithDefaultHeight
,
AuthorWithM2M
,
Book
,
BookWithLongName
,
BookWithSlug
,
BookWithM2M
,
Tag
,
TagIndexed
,
TagM2MTest
,
TagUniqueRename
,
UniqueTest
,
Thing
,
TagThrough
,
BookWithM2MThrough
,
AuthorTag
,
AuthorWithM2MThrough
,
...
...
@@ -1310,3 +1311,47 @@ class SchemaTests(TransactionTestCase):
cursor
.
execute
(
"SELECT surname FROM schema_author;"
)
item
=
cursor
.
fetchall
()[
0
]
self
.
assertEqual
(
item
[
0
],
None
if
connection
.
features
.
interprets_empty_strings_as_nulls
else
''
)
def
test_custom_manytomanyfield
(
self
):
"""
#24104 - Schema editors should look for internal type of field
"""
# Create the tables
with
connection
.
schema_editor
()
as
editor
:
editor
.
create_model
(
AuthorWithM2M
)
editor
.
create_model
(
TagM2MTest
)
# Create an M2M field
new_field
=
CustomManyToManyField
(
"schema.TagM2MTest"
,
related_name
=
"authors"
)
new_field
.
contribute_to_class
(
AuthorWithM2M
,
"tags"
)
# Ensure there's no m2m table there
self
.
assertRaises
(
DatabaseError
,
self
.
column_classes
,
new_field
.
rel
.
through
)
try
:
# Add the field
with
connection
.
schema_editor
()
as
editor
:
editor
.
add_field
(
AuthorWithM2M
,
new_field
,
)
# Ensure there is now an m2m table there
columns
=
self
.
column_classes
(
new_field
.
rel
.
through
)
self
.
assertEqual
(
columns
[
'tagm2mtest_id'
][
0
],
"IntegerField"
)
# "Alter" the field. This should not rename the DB table to itself.
with
connection
.
schema_editor
()
as
editor
:
editor
.
alter_field
(
AuthorWithM2M
,
new_field
,
new_field
,
)
# Remove the M2M table again
with
connection
.
schema_editor
()
as
editor
:
editor
.
remove_field
(
AuthorWithM2M
,
new_field
,
)
# Ensure there's no m2m table there
self
.
assertRaises
(
DatabaseError
,
self
.
column_classes
,
new_field
.
rel
.
through
)
finally
:
# Cleanup model states
AuthorWithM2M
.
_meta
.
local_many_to_many
.
remove
(
new_field
)
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