Skip to content

Releases: piccolo-orm/piccolo

1.25.0

26 Apr 22:14

Choose a tag to compare

Improvements to Piccolo app creation. When running the following:

piccolo app new my_app

It now validates that the app name (my_app in this case) is valid as a Python package.

Also, there is now a --register flag, which automatically adds the new app to the APP_REGISTRY in piccolo_conf.py.

piccolo app new my_app --register

Other changes:

  • table_finder can now use relative modules.
  • Updated the Esmerald ASGI template (thanks to @sinisaos for this).
  • When using the remove method to delete a row from the database (e.g. await some_band.remove()), then some_band._exists_in_db is now set to False. Thanks to @sinisaos for this fix.

1.24.2

03 Apr 22:05

Choose a tag to compare

Fixed a bug with delete queries which have joins in the where clause. For example:

>>> await Band.delete().where(Band.manager.name == 'Guido')

Thanks to @HakierGrzonzo for reporting the issue, and @sinisaos for the fix.

1.24.1

21 Mar 22:44

Choose a tag to compare

Fixed a bug with default values in Timestamp and Timestamptz columns. Thanks to @splch for this.

1.24.0

14 Mar 22:58

Choose a tag to compare

  • Fixed a bug with get_or_create when a table has a column with both null=False and default=None - thanks to @bymoye for reporting this issue.
  • If a PostgresEngine uses the dsn argument for asyncpg, this is now used by piccolo sql_shell run. Thanks to @abhishek-compro for suggesting this.
  • Fixed the type annotation for the length argument of Varchar - it is allowed to be None. Thanks to @Compro-Prasad for this.

1.23.0

12 Feb 23:54

Choose a tag to compare

  • Added Quart, Sanic, and Falcon as supported ASGI frameworks (thanks to @sinisaos for this).
  • Fixed a bug with very large integers in SQLite.
  • Fixed type annotation for Timestamptz default values (thanks to @Skelmis for this).

1.22.0

23 Oct 21:43

Choose a tag to compare

Python 3.13 is now officially supported.

JSON / JSONB querying has been significantly improved. For example, if we have this table:

class RecordingStudio(Table):
    facilities = JSONB()

And the facilities column contains the following JSON data:

{
    "technicians": [
        {"name": "Alice Jones"},
        {"name": "Bob Williams"},
    ]
}

We can get the first technician name as follows:

>>> await RecordingStudio.select(
...     RecordingStudio.facilities["technicians"][0]["name"].as_alias("name")
... ).output(load_json=True)
[{'name': 'Alice Jones'}, ...]

TableStorage (used for dynamically creating Piccolo Table classes from an existing database) was improved, to support a Dockerised version of Piccolo Admin, which is coming soon.

1.21.0

18 Oct 12:51

Choose a tag to compare

Postgres 17 is now officially supported.

Fixed a bug with joins, when a ForeignKey column had db_column_name specified. Thanks to @jessemcl-flwls for reporting this issue.

1.20.0

04 Oct 23:09

Choose a tag to compare

get_related now works multiple layers deep:

concert = await Concert.objects().first()
manager = await concert.get_related(Concert.band_1._.manager)

1.19.1

01 Oct 08:52

Choose a tag to compare

Fixed a bug with the get_m2m method, which would raise a ValueError when no objects were found. It now handles this gracefully and returns an empty list instead. Thanks to @nVitius for this fix.

Improved the ASGI templates (including a fix for the latest Litestar version). Thanks to @sinisaos for this.

1.19.0

24 Sep 00:27

Choose a tag to compare

Added support for row locking (i.e. SELECT ... FOR UPDATE).

For example, if we have this table:

class Concert(Table):
    name = Varchar()
    tickets_available = Integer()

And we want to make sure that tickets_available never goes below 0, we can do the following:

async def book_tickets(ticket_count: int):
    async with Concert._meta.db.transaction():
        concert = await Concert.objects().where(
            Concert.name == "Awesome Concert"
        ).first().lock_rows()

        if concert.tickets_available >= ticket_count:
            await concert.update_self({
                Concert.tickets_available: Concert.tickets_available - ticket_count
            })
        else:
            raise ValueError("Not enough tickets are available!")

This means that when multiple transactions are running at the same time, it isn't possible to book more tickets than are available.

Thanks to @dkopitsa for adding this feature.