Skip to content

Commit 7a087fc

Browse files
kafai-lamlmignon
authored andcommitted
[17.0][FIX] fs_attachment: allow serving field attachment with fs stream
1 parent 1c26302 commit 7a087fc

File tree

2 files changed

+47
-9
lines changed

2 files changed

+47
-9
lines changed

fs_attachment/models/ir_binary.py

+18-9
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,14 @@ class IrBinary(models.AbstractModel):
1717

1818
_inherit = "ir.binary"
1919

20-
def _record_to_stream(self, record, field_name):
21-
# Extend base implementation to support attachment stored into a
22-
# filesystem storage
23-
fs_attachment = None
20+
def _get_fs_attachment_for_field(self, record, field_name):
2421
if record._name == "ir.attachment" and record.fs_filename:
25-
fs_attachment = record
22+
return record
23+
2624
record.check_field_access_rights("read", [field_name])
2725
field_def = record._fields[field_name]
28-
if field_def.attachment and not field_def.compute and not field_def.related:
29-
field_attachment = (
26+
if field_def.attachment and field_def.store:
27+
fs_attachment = (
3028
self.env["ir.attachment"]
3129
.sudo()
3230
.search(
@@ -38,8 +36,14 @@ def _record_to_stream(self, record, field_name):
3836
limit=1,
3937
)
4038
)
41-
if field_attachment.fs_filename:
42-
fs_attachment = field_attachment
39+
if fs_attachment and fs_attachment.fs_filename:
40+
return fs_attachment
41+
return None
42+
43+
def _record_to_stream(self, record, field_name):
44+
# Extend base implementation to support attachment stored into a
45+
# filesystem storage
46+
fs_attachment = self._get_fs_attachment_for_field(record, field_name)
4347
if fs_attachment:
4448
return FsStream.from_fs_attachment(fs_attachment)
4549
return super()._record_to_stream(record, field_name)
@@ -101,6 +105,11 @@ def _get_image_stream_from(
101105
if value:
102106
record = value.attachment
103107
field_name = "raw"
108+
elif field_def.type in ("binary"):
109+
fs_attachment = self._get_fs_attachment_for_field(record, field_name)
110+
if fs_attachment:
111+
record = fs_attachment
112+
field_name = "raw"
104113
stream = super()._get_image_stream_from(
105114
record,
106115
field_name=field_name,

fs_attachment/tests/test_stream.py

+29
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Copyright 2023 ACSONE SA/NV (http://acsone.eu).
22
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
3+
import base64
34
import io
45
import os
56
import shutil
@@ -160,3 +161,31 @@ def test_response_csp_header(self):
160161
"Content-Security-Policy": "default-src 'none'",
161162
},
162163
)
164+
165+
def test_serving_field_image(self):
166+
self.authenticate("admin", "admin")
167+
demo_partner = self.env.ref("base.partner_demo")
168+
demo_partner.with_context(
169+
storage_location=self.temp_backend.code,
170+
).write({"image_128": base64.encodebytes(self._create_image(128, 128))})
171+
url = f"/web/image/{demo_partner._name}/{demo_partner.id}/image_128"
172+
res = self.assertDownload(
173+
url,
174+
headers={},
175+
assert_status_code=200,
176+
assert_headers={
177+
"Content-Type": "image/png",
178+
},
179+
)
180+
self.assertEqual(Image.open(io.BytesIO(res.content)).size, (128, 128))
181+
182+
url = f"/web/image/{demo_partner._name}/{demo_partner.id}/avatar_128"
183+
avatar_res = self.assertDownload(
184+
url,
185+
headers={},
186+
assert_status_code=200,
187+
assert_headers={
188+
"Content-Type": "image/png",
189+
},
190+
)
191+
self.assertEqual(Image.open(io.BytesIO(avatar_res.content)).size, (128, 128))

0 commit comments

Comments
 (0)