Skip to content

pyvelm v0.17.0

Release date: 2026-05-27

A bundled file library + file picker for ir.attachment, plus a generic image=<field> slot on kanban cards so any model can get a thumbnail view for free.


Highlights

file_manager module

A small bundled app that turns the existing ir.attachment table into a browsable library:

Where What
Files → Library Thumbnail kanban — image MIMEs render their bytes; everything else gets a MIME-icon tile
Files → All files Sortable list (name, MIME, size, owning record, public, uploaded-at). + New jumps to the upload page
GET/POST /web/files/upload Multipart upload page — pick one or many, optional Public flag, redirects back to the library
GET /web/files/picker?accept=&q=&multi=0\|1 Picker dialog body (live search, MIME filter, inline upload)
POST /web/files/picker/upload Upload-from-dialog (returns the new row JSON so the picker selects it)

Install hook grants:

  • Admin — full CRUD on ir.attachment.
  • User — read on ir.attachment (so non-admins can pick files via the widgets even when they can't reach the management UI).

File-picker widgets

Two new widgets sit on the existing Many2one / Many2many machinery:

class Brochure(BaseModel):
    _name = "marketing.brochure"

    title = Char(required=True)
    cover_id = Many2one("ir.attachment")
    asset_ids = Many2many("ir.attachment")
field("cover_id", widget="file", accept="image/*")
field("asset_ids", widget="files", accept="application/pdf,image/*")
  • Edit mode: chip list of selections + Pick a file button. The button opens PvDialog against /web/files/picker; the dialog shows the library as a thumbnail grid, with a live name search and an inline upload that auto-selects the newly created row.
  • Display mode: image MIMEs render as a clickable thumbnail; other MIMEs render as a small file pill with a download link.
  • The accept= token flows into both the library query (mimetype ilike) and the upload input's accept attribute, so operators only see files they can pick.

Single-mode picks close the dialog on tile click. Multi-mode picks collect a selection and emit it via the Use selected footer button. The dialog's onResult patches the field's hidden input — Many2one stores one id; Many2many stores comma-separated ids (the existing parent-form parser already accepts both shapes).

Generic image slot on kanban cards

card(...) gained an image=<field> keyword. The renderer pulls the field's string value (a URL) into card["image_url"]; the card template renders a 4:3 thumbnail above the title when non-empty.

kanban_view(
    "file_manager.file.kanban", "ir.attachment",
    card=card("name", image="thumbnail_url", subtitle="mimetype"),
)

file_manager extends ir.attachment with a computed thumbnail_url Char that returns /api/attachment/{id}/download for image MIMEs, the external url for URL-typed image attachments, and "" otherwise. Reuse the slot in your own kanbans by exposing any Char field that resolves to a URL.


Upgrade

pip install -U pyvelm==0.17.0
  1. Apps → Install file_manager — depends on base + admin; no base schema bumps.
  2. Hard-refresh the browser so the updated kanban card template loads and the new widget JS runs.
  3. To use the picker on existing models, declare Many2one("ir.attachment") / Many2many("ir.attachment") fields and reference them as field(..., widget="file"|"files", accept="...") in your view arch.

Also in this release

  • card(...) builder docstring + ArchKanbanCard TypedDict gain the image key.
  • _kanban_cards_for_records() accepts an image_attr= kwarg; the card template renders the thumbnail block conditionally on card.image_url.
  • New tests in pyvelm/tests/test_file_manager.py cover the kanban image slot, picker dialog rendering (with / without upload, empty state), and the field-side template's seeded chips.

Docs