master
.If you try to edit any fields of the form or submit the form unchanged, the image file that was uploaded earlier will be corrupted.
Here is my code:
from fastapi_storages import FileSystemStorage
storage = FileSystemStorage(path="static/images/")
class Subcategory(IntIdPkMixin, Base, Creatable, Updatable, SoftDeletable):
name_en: Mapped[str] = mapped_column(String(50), nullable=False)
name_ru: Mapped[Optional[str]] = mapped_column(String(50), nullable=True)
tag_en: Mapped[Optional[str]] = mapped_column(String(50), nullable=True)
tag_ru: Mapped[Optional[str]] = mapped_column(String(50), nullable=True)
image_url: Mapped[Optional[str]] = mapped_column(
FileType(storage=storage), nullable=True
)
is_main: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
slug: Mapped[Optional[str]] = mapped_column(String(100), nullable=True, unique=True)
category_id: Mapped[int] = mapped_column(ForeignKey("categorys.id"))
category: Mapped["Category"] = relationship(
"Category", back_populates="subcategories"
)
products: Mapped[List["Product"]] = relationship(
"Product", back_populates="subcategory"
)
def __str__(self):
return self.name_ru
class SubcategoryAdmin(ModelView, model=Subcategory):
name = "Подкатегории"
name_plural = "Подкатегории"
icon = "fa-solid fa-tags"
category = "Товары"
edit_template = "sqladmin/edit.html"
column_list = [
Subcategory.id,
Subcategory.slug,
Subcategory.name_en,
Subcategory.name_ru,
Subcategory.tag_en,
Subcategory.tag_ru,
Subcategory.is_main,
"category.name_en",
"category.name_ru",
]
column_searchable_list = [Subcategory.name_en, Subcategory.name_ru]
column_sortable_list = [
Subcategory.id,
Subcategory.slug,
Subcategory.name_en,
Subcategory.name_ru,
Subcategory.tag_en,
Subcategory.tag_ru,
Subcategory.is_main,
"category.name_en",
"category.name_ru",
]
can_create = True
can_edit = True
can_delete = True
can_view_details = True
form_columns = [
"category",
"name_en",
"name_ru",
"tag_en",
"tag_ru",
"image_url",
"is_main",
]
column_formatters = {
"category.name_en": lambda m, a: m.category.name_en if m.category else "N/A",
"category.name_ru": lambda m, a: m.category.name_ru if m.category else "N/A",
}
column_labels = {
"id": "ID",
"name_en": "Название подкатегории (англ.)",
"name_ru": "Название подкатегории (рус.)",
"tag_en": "Тег (англ.)",
"tag_ru": "Тег (рус.)",
"image_url": "URL изображения",
"is_main": "Главная",
"slug": "Слаг",
"category_id": "ID Категории",
"created_at": "Дата создания",
"updated_at": "Дата обновления",
"category.name_en": "Подкатегория (англ.)",
"category.name_ru": "Подкатегория (рус.)",
"products": "Продукты",
"category": "Категория",
}
async def on_model_change(self, data, model, is_created, request):
form = await request.form()
for key, value in form.items():
app_logger.info(
f"Field name: {key}, Field type: {type(value)}, Field value: {value}"
)
if "image_url" in form:
image = form["image_url"]
if image.filename == "":
data.pop("image_url", None)
app_logger.info("Image field drop")
model.slug = generate_slug(model.name_en)
app_logger.info(data)
async with Session(expire_on_commit=False) as session:
subcategory_service = SubcategoryService(session)
await subcategory_service.set_main_subcategory(model.id)
1.Go to the edit page
2. Save the edits without uploading a new image.
4. If you check the image that was there earlier, it will be damaged.
it is expected to receive modified data in other fields, without damaging the image
No response
I did a little research. I found that when submitting the form, if you do not embed a new image, there is file data in the form, but they are empty.
web_1 | INFO 2024-08-12 07:05:52.875 request id: None - core.admin:on_model_change - Field name: image_url, Field type: <class 'starlette.datastructures.UploadFile'>, Field value: UploadFile(filename='', size=0, headers=Headers({'content-disposition': 'form-data; name="image_url"; filename=""', 'content-type': 'application/octet-stream'}))
By adding a simple check and removing this field from the data, I avoid the problem of file corruption:
` async def on_model_change(self, data, model, is_created, request):
form = await request.form()
for key, value in form.items():
app_logger.info(
f"Field name: {key}, Field type: {type(value)}, Field value: {value}"
)
if "image_url" in form:
image = form["image_url"]
if image.filename == "":
data.pop("image_url", None)
app_logger.info("Image field drop")`
ubuntu 23.04, python 3.10, sqladmin[full] latest, fastapi 0.111, sqlalchemy[asyncio]~=2.0.30
No response
Pay now to fund the work behind this issue.
Get updates on progress being made.
Maintainer is rewarded once the issue is completed.
You're funding impactful open source efforts
You want to contribute to this effort
You want to get funding like this too