Skip to content

Commit 1577303

Browse files
committed
Update PictureField to support multiple aspect_ratios and file_types
1 parent 715bfc6 commit 1577303

File tree

3 files changed

+22
-54
lines changed

3 files changed

+22
-54
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -246,15 +246,15 @@ class PictureSerializer(serializers.Serializer):
246246
picture = PictureField()
247247
```
248248

249-
The response can be restricted to a single aspect ratio and image source, by
250-
providing the `aspect_ratio` and `image_source` arguments to the field.
249+
The response can be restricted to a fewer aspect ratios and file types, by
250+
providing the `aspect_ratios` and `file_types` arguments to the DRF field.
251251

252252
```python
253253
from rest_framework import serializers
254254
from pictures.contrib.rest_framework import PictureField
255255

256256
class PictureSerializer(serializers.Serializer):
257-
picture = PictureField(aspect_ratio="16/9", image_source="WEBP")
257+
picture = PictureField(aspect_ratios=["16/9"], file_types=["WEBP"])
258258
```
259259

260260
You also may provide optional GET parameters to the serializer,

pictures/contrib/rest_framework.py

Lines changed: 17 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ def default(obj):
1919
class PictureField(serializers.ReadOnlyField):
2020
"""Read-only field for all aspect ratios and sizes of the image."""
2121

22-
def __init__(self, aspect_ratio=None, image_source=None, **kwargs):
23-
self.aspect_ratio = aspect_ratio
24-
self.image_source = image_source
22+
def __init__(self, aspect_ratios=None, file_types=None, **kwargs):
2523
super().__init__(**kwargs)
24+
self.aspect_ratios = aspect_ratios or []
25+
self.file_types = file_types or []
2626

2727
def to_representation(self, obj: PictureFieldFile):
2828
if not obj:
@@ -34,35 +34,20 @@ def to_representation(self, obj: PictureFieldFile):
3434
"height": obj.height,
3535
}
3636

37-
# if aspect_ratio is set, only return that aspect ratio to reduce payload size
38-
if self.aspect_ratio and self.image_source:
39-
try:
40-
sizes = obj.aspect_ratios[self.aspect_ratio][self.image_source]
41-
except KeyError as e:
42-
raise ValueError(
43-
f"Invalid ratio {self.aspect_ratio} or image source {self.image_source}. Choices are: {', '.join(filter(None, obj.aspect_ratios.keys()))}"
44-
) from e
45-
payload = {
46-
**base_payload,
47-
"ratios": {
48-
self.aspect_ratio: {
49-
"sources": {f"image/{self.image_source.lower()}": sizes}
50-
}
51-
},
52-
}
53-
else:
54-
payload = {
55-
**base_payload,
56-
"ratios": {
57-
ratio: {
58-
"sources": {
59-
f"image/{file_type.lower()}": sizes
60-
for file_type, sizes in sources.items()
61-
},
62-
}
63-
for ratio, sources in obj.aspect_ratios.items()
64-
},
65-
}
37+
payload = {
38+
**base_payload,
39+
"ratios": {
40+
ratio: {
41+
"sources": {
42+
f"image/{file_type.lower()}": sizes
43+
for file_type, sizes in sources.items()
44+
if file_type in self.file_types or not self.file_types
45+
},
46+
}
47+
for ratio, sources in obj.aspect_ratios.items()
48+
if ratio in self.aspect_ratios or not self.aspect_ratios
49+
},
50+
}
6651

6752
# if the request has query parameters, filter the payload
6853
try:

tests/contrib/test_rest_framework.py

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
class ProfileSerializer(serializers.ModelSerializer):
1414
image = rest_framework.PictureField(source="picture")
1515
image_mobile = rest_framework.PictureField(
16-
source="picture", aspect_ratio="3/2", image_source="WEBP"
16+
source="picture", aspect_ratios=["3/2"], file_types=["WEBP"]
1717
)
1818

1919
class Meta:
@@ -23,7 +23,7 @@ class Meta:
2323

2424
class ProfileSerializerWithInvalidData(serializers.ModelSerializer):
2525
image_invalid = rest_framework.PictureField(
26-
source="picture", aspect_ratio="21/11", image_source="GIF"
26+
source="picture", aspect_ratios=["21/11"], file_types=["GIF"]
2727
)
2828

2929
class Meta:
@@ -308,20 +308,3 @@ def test_to_representation__with_prefiltered_aspect_ratio_and_source(
308308
}
309309
},
310310
}
311-
312-
@pytest.mark.django_db
313-
def test_to_representation__with_prefiltered_aspect_ratio_and_source__raise_value_error(
314-
self, image_upload_file, settings
315-
):
316-
settings.PICTURES["USE_PLACEHOLDERS"] = False
317-
318-
profile = models.Profile.objects.create(picture=image_upload_file)
319-
320-
serializer = ProfileSerializerWithInvalidData(profile)
321-
with pytest.raises(ValueError) as e:
322-
serializer.data["image_invalid"]
323-
324-
assert (
325-
str(e.value)
326-
== "Invalid ratio 21/11 or image source GIF. Choices are: 1/1, 3/2, 16/9"
327-
)

0 commit comments

Comments
 (0)