Skip to content

Commit 9c996d7

Browse files
committed
Clean up existing deprecation warnings. (#4166)
* Add Meta.fields = '__all__' to serializer classes where required. * Add explicit on_delete=models.CASCADE to ForeignKey fields. * Use '.remote_field' and '.model' in preference to '.rel' and '.to' when inspecting model fields. * Use new value_from_object in preference to internal _get_val_from_obj
1 parent 53a356a commit 9c996d7

19 files changed

+137
-61
lines changed

rest_framework/authtoken/migrations/0001_initial.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class Migration(migrations.Migration):
1717
fields=[
1818
('key', models.CharField(primary_key=True, serialize=False, max_length=40)),
1919
('created', models.DateTimeField(auto_now_add=True)),
20-
('user', models.OneToOneField(to=settings.AUTH_USER_MODEL, related_name='auth_token')),
20+
('user', models.OneToOneField(to=settings.AUTH_USER_MODEL, related_name='auth_token', on_delete=models.CASCADE)),
2121
],
2222
options={
2323
},

rest_framework/authtoken/migrations/0002_auto_20160226_1747.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,6 @@ class Migration(migrations.Migration):
2929
migrations.AlterField(
3030
model_name='token',
3131
name='user',
32-
field=models.OneToOneField(to=settings.AUTH_USER_MODEL, verbose_name='User', related_name='auth_token'),
32+
field=models.OneToOneField(to=settings.AUTH_USER_MODEL, verbose_name='User', related_name='auth_token', on_delete=models.CASCADE),
3333
),
3434
]

rest_framework/compat.py

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@
66
# flake8: noqa
77
from __future__ import unicode_literals
88

9+
import inspect
10+
911
import django
12+
from django.apps import apps
1013
from django.conf import settings
11-
from django.db import connection, transaction
14+
from django.core.exceptions import ImproperlyConfigured
15+
from django.db import connection, models, transaction
1216
from django.template import Context, RequestContext, Template
1317
from django.utils import six
1418
from django.views.generic import View
@@ -58,6 +62,7 @@ def distinct(queryset, base):
5862
return queryset.distinct()
5963

6064

65+
# Obtaining manager instances and names from model options differs after 1.10.
6166
def get_names_and_managers(options):
6267
if django.VERSION >= (1, 10):
6368
# Django 1.10 onwards provides a `.managers` property on the Options.
@@ -75,6 +80,54 @@ def get_names_and_managers(options):
7580
]
7681

7782

83+
# field.rel is deprecated from 1.9 onwards
84+
def get_remote_field(field, **kwargs):
85+
if 'default' in kwargs:
86+
if django.VERSION < (1, 9):
87+
return getattr(field, 'rel', kwargs['default'])
88+
return getattr(field, 'remote_field', kwargs['default'])
89+
90+
if django.VERSION < (1, 9):
91+
return field.rel
92+
return field.remote_field
93+
94+
95+
def _resolve_model(obj):
96+
"""
97+
Resolve supplied `obj` to a Django model class.
98+
99+
`obj` must be a Django model class itself, or a string
100+
representation of one. Useful in situations like GH #1225 where
101+
Django may not have resolved a string-based reference to a model in
102+
another model's foreign key definition.
103+
104+
String representations should have the format:
105+
'appname.ModelName'
106+
"""
107+
if isinstance(obj, six.string_types) and len(obj.split('.')) == 2:
108+
app_name, model_name = obj.split('.')
109+
resolved_model = apps.get_model(app_name, model_name)
110+
if resolved_model is None:
111+
msg = "Django did not return a model for {0}.{1}"
112+
raise ImproperlyConfigured(msg.format(app_name, model_name))
113+
return resolved_model
114+
elif inspect.isclass(obj) and issubclass(obj, models.Model):
115+
return obj
116+
raise ValueError("{0} is not a Django model".format(obj))
117+
118+
119+
def get_related_model(field):
120+
if django.VERSION < (1, 9):
121+
return _resolve_model(field.rel.to)
122+
return field.remote_field.model
123+
124+
125+
def value_from_object(field, obj):
126+
if django.VERSION < (1, 9):
127+
return field._get_val_from_obj(obj)
128+
field.value_from_object(obj)
129+
130+
78131
# contrib.postgres only supported from 1.8 onwards.
79132
try:
80133
from django.contrib.postgres import fields as postgres_fields

rest_framework/fields.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@
3030
from django.utils.translation import ugettext_lazy as _
3131

3232
from rest_framework import ISO_8601
33-
from rest_framework.compat import unicode_repr, unicode_to_repr
33+
from rest_framework.compat import (
34+
get_remote_field, unicode_repr, unicode_to_repr, value_from_object
35+
)
3436
from rest_framework.exceptions import ValidationError
3537
from rest_framework.settings import api_settings
3638
from rest_framework.utils import html, humanize_datetime, representation
@@ -1674,7 +1676,7 @@ def __init__(self, model_field, **kwargs):
16741676
self.validators.append(MaxLengthValidator(max_length, message=message))
16751677

16761678
def to_internal_value(self, data):
1677-
rel = getattr(self.model_field, 'rel', None)
1679+
rel = get_remote_field(self.model_field, default=None)
16781680
if rel is not None:
16791681
return rel.to._meta.get_field(rel.field_name).to_python(data)
16801682
return self.model_field.to_python(data)
@@ -1685,7 +1687,7 @@ def get_attribute(self, obj):
16851687
return obj
16861688

16871689
def to_representation(self, obj):
1688-
value = self.model_field._get_val_from_obj(obj)
1690+
value = value_from_object(self.model_field, obj)
16891691
if is_protected_type(value):
16901692
return value
16911693
return self.model_field.value_to_string(obj)

rest_framework/serializers.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1153,6 +1153,7 @@ class NestedSerializer(ModelSerializer):
11531153
class Meta:
11541154
model = relation_info.related_model
11551155
depth = nested_depth - 1
1156+
fields = '__all__'
11561157

11571158
field_class = NestedSerializer
11581159
field_kwargs = get_nested_relation_kwargs(relation_info)
@@ -1469,6 +1470,7 @@ class NestedSerializer(HyperlinkedModelSerializer):
14691470
class Meta:
14701471
model = relation_info.related_model
14711472
depth = nested_depth - 1
1473+
fields = '__all__'
14721474

14731475
field_class = NestedSerializer
14741476
field_kwargs = get_nested_relation_kwargs(relation_info)

rest_framework/utils/model_meta.py

Lines changed: 14 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,9 @@
55
66
Usage: `get_field_info(model)` returns a `FieldInfo` instance.
77
"""
8-
import inspect
98
from collections import OrderedDict, namedtuple
109

11-
from django.apps import apps
12-
from django.core.exceptions import ImproperlyConfigured
13-
from django.db import models
14-
from django.utils import six
10+
from rest_framework.compat import get_related_model, get_remote_field
1511

1612
FieldInfo = namedtuple('FieldResult', [
1713
'pk', # Model field instance
@@ -31,30 +27,6 @@
3127
])
3228

3329

34-
def _resolve_model(obj):
35-
"""
36-
Resolve supplied `obj` to a Django model class.
37-
38-
`obj` must be a Django model class itself, or a string
39-
representation of one. Useful in situations like GH #1225 where
40-
Django may not have resolved a string-based reference to a model in
41-
another model's foreign key definition.
42-
43-
String representations should have the format:
44-
'appname.ModelName'
45-
"""
46-
if isinstance(obj, six.string_types) and len(obj.split('.')) == 2:
47-
app_name, model_name = obj.split('.')
48-
resolved_model = apps.get_model(app_name, model_name)
49-
if resolved_model is None:
50-
msg = "Django did not return a model for {0}.{1}"
51-
raise ImproperlyConfigured(msg.format(app_name, model_name))
52-
return resolved_model
53-
elif inspect.isclass(obj) and issubclass(obj, models.Model):
54-
return obj
55-
raise ValueError("{0} is not a Django model".format(obj))
56-
57-
5830
def get_field_info(model):
5931
"""
6032
Given a model class, returns a `FieldInfo` instance, which is a
@@ -76,16 +48,19 @@ def get_field_info(model):
7648

7749
def _get_pk(opts):
7850
pk = opts.pk
79-
while pk.rel and pk.rel.parent_link:
51+
rel = get_remote_field(pk)
52+
53+
while rel and rel.parent_link:
8054
# If model is a child via multi-table inheritance, use parent's pk.
81-
pk = pk.rel.to._meta.pk
55+
pk = get_related_model(pk)._meta.pk
56+
rel = get_remote_field(pk)
8257

8358
return pk
8459

8560

8661
def _get_fields(opts):
8762
fields = OrderedDict()
88-
for field in [field for field in opts.fields if field.serialize and not field.rel]:
63+
for field in [field for field in opts.fields if field.serialize and not get_remote_field(field)]:
8964
fields[field.name] = field
9065

9166
return fields
@@ -100,10 +75,10 @@ def _get_forward_relationships(opts):
10075
Returns an `OrderedDict` of field names to `RelationInfo`.
10176
"""
10277
forward_relations = OrderedDict()
103-
for field in [field for field in opts.fields if field.serialize and field.rel]:
78+
for field in [field for field in opts.fields if field.serialize and get_remote_field(field)]:
10479
forward_relations[field.name] = RelationInfo(
10580
model_field=field,
106-
related_model=_resolve_model(field.rel.to),
81+
related_model=get_related_model(field),
10782
to_many=False,
10883
to_field=_get_to_field(field),
10984
has_through_model=False
@@ -113,12 +88,12 @@ def _get_forward_relationships(opts):
11388
for field in [field for field in opts.many_to_many if field.serialize]:
11489
forward_relations[field.name] = RelationInfo(
11590
model_field=field,
116-
related_model=_resolve_model(field.rel.to),
91+
related_model=get_related_model(field),
11792
to_many=True,
11893
# manytomany do not have to_fields
11994
to_field=None,
12095
has_through_model=(
121-
not field.rel.through._meta.auto_created
96+
not get_remote_field(field).through._meta.auto_created
12297
)
12398
)
12499

@@ -141,7 +116,7 @@ def _get_reverse_relationships(opts):
141116
reverse_relations[accessor_name] = RelationInfo(
142117
model_field=None,
143118
related_model=related,
144-
to_many=relation.field.rel.multiple,
119+
to_many=get_remote_field(relation.field).multiple,
145120
to_field=_get_to_field(relation.field),
146121
has_through_model=False
147122
)
@@ -158,8 +133,8 @@ def _get_reverse_relationships(opts):
158133
# manytomany do not have to_fields
159134
to_field=None,
160135
has_through_model=(
161-
(getattr(relation.field.rel, 'through', None) is not None) and
162-
not relation.field.rel.through._meta.auto_created
136+
(getattr(get_remote_field(relation.field), 'through', None) is not None) and
137+
not get_remote_field(relation.field).through._meta.auto_created
163138
)
164139
)
165140

tests/test_authentication.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929

3030
class CustomToken(models.Model):
3131
key = models.CharField(max_length=40, primary_key=True)
32-
user = models.OneToOneField(User)
32+
user = models.OneToOneField(User, on_delete=models.CASCADE)
3333

3434

3535
class CustomTokenAuthentication(TokenAuthentication):

tests/test_filters.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
class FilterableItemSerializer(serializers.ModelSerializer):
2727
class Meta:
2828
model = FilterableItem
29+
fields = '__all__'
2930

3031
# Basic filter on a list view.
3132
class FilterFieldsRootView(generics.ListCreateAPIView):
@@ -336,6 +337,7 @@ class SearchFilterModel(models.Model):
336337
class SearchFilterSerializer(serializers.ModelSerializer):
337338
class Meta:
338339
model = SearchFilterModel
340+
fields = '__all__'
339341

340342

341343
class SearchFilterTests(TestCase):
@@ -461,6 +463,7 @@ class SearchFilterModelM2M(models.Model):
461463
class SearchFilterM2MSerializer(serializers.ModelSerializer):
462464
class Meta:
463465
model = SearchFilterModelM2M
466+
fields = '__all__'
464467

465468

466469
class SearchFilterM2MTests(TestCase):
@@ -504,13 +507,13 @@ class OrderingFilterModel(models.Model):
504507

505508

506509
class OrderingFilterRelatedModel(models.Model):
507-
related_object = models.ForeignKey(OrderingFilterModel,
508-
related_name="relateds")
510+
related_object = models.ForeignKey(OrderingFilterModel, related_name="relateds", on_delete=models.CASCADE)
509511

510512

511513
class OrderingFilterSerializer(serializers.ModelSerializer):
512514
class Meta:
513515
model = OrderingFilterModel
516+
fields = '__all__'
514517

515518

516519
class DjangoFilterOrderingModel(models.Model):
@@ -524,6 +527,7 @@ class Meta:
524527
class DjangoFilterOrderingSerializer(serializers.ModelSerializer):
525528
class Meta:
526529
model = DjangoFilterOrderingModel
530+
fields = '__all__'
527531

528532

529533
class DjangoFilterOrderingTests(TestCase):

tests/test_generics.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,13 @@ class Comment(RESTFrameworkModel):
3333
class BasicSerializer(serializers.ModelSerializer):
3434
class Meta:
3535
model = BasicModel
36+
fields = '__all__'
3637

3738

3839
class ForeignKeySerializer(serializers.ModelSerializer):
3940
class Meta:
4041
model = ForeignKeySource
42+
fields = '__all__'
4143

4244

4345
class SlugSerializer(serializers.ModelSerializer):
@@ -414,6 +416,7 @@ class ClassASerializer(serializers.ModelSerializer):
414416

415417
class Meta:
416418
model = ClassA
419+
fields = '__all__'
417420

418421

419422
class ExampleView(generics.ListCreateAPIView):
@@ -461,6 +464,7 @@ class Meta:
461464
class DynamicSerializer(serializers.ModelSerializer):
462465
class Meta:
463466
model = TwoFieldModel
467+
fields = '__all__'
464468
return DynamicSerializer
465469

466470

tests/test_metadata.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ class ExampleSerializer(serializers.ModelSerializer):
300300

301301
class Meta:
302302
model = Parent
303+
fields = '__all__'
303304

304305
class ExampleView(views.APIView):
305306
"""Example view."""

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy