Prisma Client Python is an auto-generated and fully type-safe database client designed for ease of use
APACHE-2.0 License
Bot releases are visible (Hide)
Published by RobertCraigie over 2 years ago
In order to improve readability, the recommended method to import the client has changed from Client
to Prisma
. However, for backwards compatibility you can still import Client
.
from prisma import Prisma
prisma = Prisma()
By default a warning is raised when you attempt to subclass a model while using pseudo-recursive types, see the documentation for more information.
This warning was raised when using a Prisma model in a FastAPI response model as FastAPI implicitly subclasses the given model. This means that the warning was actually redundant and as such has been removed, the following code snippet will no longer raise a warning:
from fastapi import FastAPI
from prisma.models import User
app = FastAPI()
@app.get('/foo', response_model=User)
async def get_foo() -> User:
...
The internal Prisma binaries that Prisma Python makes use of have been upgraded from v3.8.1 to v3.9.1. For a full changelog see the v3.9.0 release notes and v3.9.1 release notes.
You can now completely remove the internal HTTP timeout
from prisma import Prisma
prisma = Prisma(
http={
'timeout': None,
},
)
This project has been renamed from Prisma Client Python
to Prisma Python
Thanks to @ghandic for the bug report and thanks to @kivo360 for contributing!
Published by RobertCraigie over 2 years ago
update_many
mutation data, updating relational fields from update_many
is not supported yet (https://github.com/prisma/prisma/issues/3143).Python 3.6 reached its end of life on the 23rd of December 2021. You now need Python 3.7 or higher to use Prisma Client Python.
You can now group records by one or more field values and perform aggregations on each group!
It should be noted that the structure of the returned data is different to most other action methods, returning a TypedDict
instead of a BaseModel
.
For example:
results = await Profile.prisma().group_by(
by=['country'],
sum={
'views': True,
},
)
# [
# {"country": "Canada", "_sum": {"views": 23}},
# {"country": "Scotland", "_sum": {"views": 143}},
# ]
For more examples see the documentation: https://prisma-client-py.readthedocs.io/en/stable/reference/operations/#grouping-records
While the syntax is slightly different the official Prisma documentation is also a good reference: https://www.prisma.io/docs/concepts/components/prisma-client/aggregation-grouping-summarizing#group-by
You can now easily (and with full type-safety) define custom options for your own Prisma Generators!
from pydantic import BaseModel
from prisma.generator import GenericGenerator, GenericData, Manifest
# custom options must be defined using a pydantic BaseModel
class Config(BaseModel):
my_option: int
# we don't technically need to define our own Data class
# but it makes typing easier
class Data(GenericData[Config]):
pass
# the GenericGenerator[Data] part is what tells Prisma Client Python to use our
# custom Data class with our custom Config class
class MyGenerator(GenericGenerator[Data]):
def get_manifest(self) -> Manifest:
return Manifest(
name='My Custom Generator Options',
default_output='schema.md',
)
def generate(self, data: Data) -> None:
# generate some assets here
pass
if __name__ == '__main__':
MyGenerator.invoke()
There are two arguments that were deprecated in previous releases that have now been removed:
encoding
argument to Base64.decode()
order
argument to actions.count()
You can now update fields that are marked as @unique
or @id
:
user = await User.prisma().update(
where={
'email': '[email protected]',
},
data={
'email': '[email protected]',
},
)
You can now easily replace the Prisma CLI binary that Prisma Client Python makes use of by overriding the PRISMA_CLI_BINARY
environment variable. This shouldn't be necessary for the vast majority of users however as some platforms are not officially supported yet, binaries must be built manually in these cases.
The internal Prisma binaries that Prisma Client Python makes use of have been upgraded from v3.7.0 to v3.8.1. For a full changelog see the v3.8.0 release notes.
Published by RobertCraigie almost 3 years ago
Subclassing pseudo-recursive models will now raise a warning instead of crashing, static types will still not respect the subclass, for example:
from prisma.models import User
class MyUser(User):
@property
def fullname(self) -> str:
return f'{self.name} {self.surname}'
# static type checkers will think that `user` is an instance of `User` when it is actually `MyUser` at runtime
# you can fix this by following the steps here:
# https://prisma-client-py.readthedocs.io/en/stable/reference/limitations/#removing-limitations
user = MyUser.prisma().create(
data={
'name': 'Robert',
'surname': 'Craigie',
},
)
For more details, see the documentation
The default HTTP timeout used to communicate with the internal Query Engine has been increased from 5 seconds to 30 seconds, this means you should no longer encounter timeout errors when executing very large queries.
You can now customise the HTTPX Client used to communicate with the internal query engine, this could be useful if you need to increase the http timeout, for full reference see the documentation.
client = Client(
http={
'timeout': 100,
},
)
The internal Prisma binaries that Prisma Client Python makes use of have been upgraded from v3.4.0
to v3.7.0
for a full changelog see:
Instead of having to manually update the list of excluded fields when creating partial models whenever a new relation is added you can now just use exclude_relational_fields=True
!
from prisma.models import User
User.create_partial('UserWithoutRelations', exclude_relational_fields=True)
class UserWithoutRelations:
id: str
name: str
email: Optional[str]
Published by RobertCraigie almost 3 years ago
This release is a patch release, fixing a bug introduced in the dev CLI in v0.4.1 (#182)
Published by RobertCraigie almost 3 years ago
You can now easily write your own Prisma generators in Python!
For example:
generator.py
from pathlib import Path
from prisma.generator import BaseGenerator, Manifest, models
class MyGenerator(BaseGenerator):
def get_manifest(self) -> Manifest:
return Manifest(
name='My Prisma Generator',
default_output=Path(__file__).parent / 'generated.md',
)
def generate(self, data: Data) -> None:
lines = [
'# My Prisma Models!\n',
]
for model in data.dmmf.datamodel.models:
lines.append(f'- {model.name}')
output = Path(data.generator.output.value)
output.write_text('\n'.join(lines))
if __name__ == '__main__':
MyGenerator.invoke()
Then you can add the generator to your Prisma Schema file like so:
generator custom {
provider = "python generator.py"
}
Your custom generator will then be invoked whenever you run prisma generate
$ prisma generate
Prisma schema loaded from tests/data/schema.prisma
✔ Generated My Prisma Generator to ./generated.md in 497ms
For more details see the documentation: https://prisma-client-py.readthedocs.io/en/latest/reference/custom-generators/
You can now use the Client
as a context manager to automatically connect and disconnect from the database, for example:
from prisma import Client
async with Client() as client:
await client.user.create(
data={
'name': 'Robert',
},
)
For more information see the documentation: https://prisma-client-py.readthedocs.io/en/stable/reference/client/#context-manager
You can now automatically register the Client when it is created:
from prisma import Client
client = Client(auto_register=True)
Which is equivalent to:
from prisma import Client, register
client = Client()
register(client)
The default timeout used for connecting to the database can now be set at the client level, for example:
from prisma import Client
client = Client(connect_timeout=5)
You can still explicitly specify the timeout when connecting, for example:
from prisma import Client
client = Client(connect_timeout=5)
client.connect() # timeout: 5
client.connect(timeout=10) # timeout: 10
DateTime
microsecond precision is now truncated to 3 places (#129)Published by RobertCraigie almost 3 years ago
The following field names are now restricted and attempting to generate the client with any of them will now raise an error:
startswith
endswith
order_by
not_in
is_not
Bytes
typeYou can now create models that make use of binary data, this is stored in the underlying database as Base64 data, for example:
model User {
id Int @id @default(autoincrement())
name String
binary Bytes
}
from prisma import Base64
from prisma.models import User
user = await User.prisma().create(
data={
'name': 'Robert',
'binary': Base64.encode(b'my binary data'),
},
)
print(f'binary data: {user.binary.decode()}')
You can now query for and update scalar list fields, for example:
model User {
id Int @id @default(autoincrement())
emails String[]
}
user = await client.user.find_first(
where={
'emails': {
'has': '[email protected]',
},
},
)
For more details, visit the documentation: https://prisma-client-py.readthedocs.io/en/latest/reference/operations/#lists-fields
The order
argument to the count()
method has been deprecated, this will be removed in the next release.
All query action methods now have auto-generated docstrings specific for each model, this means that additional documentation will be shown when you hover over the method call in your IDE, for example:
typing-extensions
is now a required dependencyPublished by RobertCraigie almost 3 years ago
The prisma
field name is now reserved, trying to generate a model that has a field called prisma
will raise an error.
You can, however, still create a model that uses the prisma
field name at the database level.
model User {
id String @id @default(cuid())
prisma_field String @map("prisma")
}
You can now run prisma queries directly from model classes, for example:
from prisma.models import User
user = await User.prisma().create(
data={
'name': 'Robert',
},
)
This API is exactly the same as the previous client-based API.
To get starting running queries from model classes, you must first register the prisma client instance that will be used to communicate with the database.
from prisma import Client, register
client = Client()
register(client)
await client.connect()
For more details, visit the documentation.
You can now select which fields are returned by count()
.
This returns a dictionary matching the fields that are passed in the select
argument.
from prisma.models import Post
results = await Post.prisma().count(
select={
'_all': True,
'description': True,
},
)
# {'_all': 3, 'description': 2}
Python 3.10 is now officially supported.
The internal Prisma binaries that Prisma Client Python uses have been upgraded from 3.3.0
to 3.4.0
.
prisma db push
support for MongoDBThe current version of the client will now be displayed post-generation:
Prisma schema loaded from schema.prisma
✔ Generated Prisma Client Python (v0.3.0) to ./.venv/lib/python3.9/site-packages/prisma in 765ms
An explicit and helpful message is now shown when attempting to generate the Python Client using an unexpected version of Prisma.
Environment variables loaded from .env
Prisma schema loaded from tests/data/schema.prisma
Error:
Prisma Client Python expected Prisma version: 1c9fdaa9e2319b814822d6dbfd0a69e1fcc13a85 but got: da6fafb57b24e0b61ca20960c64e2d41f9e8cff1
If this is intentional, set the PRISMA_PY_DEBUG_GENERATOR environment variable to 1 and try again.
Are you sure you are generating the client using the python CLI?
e.g. python3 -m prisma generate (type=value_error)
--type-depth
option to prisma py generate
Published by RobertCraigie almost 3 years ago
This release is a patch release, the v0.2.3 release erroneously contained auto-generated files.
Published by RobertCraigie almost 3 years ago
This release has been yanked from PyPi as it contained auto-generated files, please install using 0.2.4 or greater.
The internal Prisma binaries that Prisma Client Python uses have been upgraded from 3.1.1
to 3.3.0
.
For a full list of changes see https://github.com/prisma/prisma/releases/tag/3.2.0 and https://github.com/prisma/prisma/releases/tag/3.3.0
Published by RobertCraigie about 3 years ago
The python package has been renamed from prisma-client
to prisma
!
You can now install the client like so:
pip install prisma
You can still install using the old package name, however no new releases will be published.
The datasource can be dynamically overriden when the client is instantiated:
from prisma import Client
client = Client(
datasource={
'url': 'file:./dev_qa.db',
},
)
This is especially useful for testing purposes.
Published by RobertCraigie about 3 years ago
This feature is only supported when using PostgreSQL and MongoDB.
user = await client.user.find_first(
where={
'name': {
'contains': 'robert',
'mode': 'insensitive',
},
},
)
The internal Prisma binaries that Prisma Client Python uses have been upgraded from 2.30.0
to 3.1.1
.
This brings with it a lot of new features and improvements:
For a full list of changes see https://github.com/prisma/prisma/releases/tag/3.1.1 and https://github.com/prisma/prisma/releases/tag/3.0.1
Prisma Client Python now comes bundled with a type validator, this makes it much easier to pass untrusted / untyped arguments to queries in a robust and type safe manner:
import prisma
from prisma.types import UserCreateInput
def get_untrusted_input():
return {'points': input('Enter how many points you have: ')}
data = prisma.validate(UserCreateInput, get_untrusted_input())
await client.user.create(data=data)
Any invalid input would then raise an easy to understand error (note: edited for brevity):
Enter how many points you have: a lot
Traceback:
pydantic.error_wrappers.ValidationError: 1 validation error for UserCreateInput
points
value is not a valid integer (type=type_error.integer)
Published by RobertCraigie about 3 years ago
Filtering field types by NOT
and IN
has been renamed to not
and in
.
For example:
post = await client.post.find_first(
where={
'title': {
'NOT': 'Exclude title',
},
},
)
Must now be written as:
post = await client.post.find_first(
where={
'title': {
'not': 'Exclude title',
},
},
)
NOT
(#70)Published by RobertCraigie about 3 years ago
This release does not contain any new features and is simply to mark the start of new version guarantees.
Breaking changes will now be released under a new MINOR version instead of the previous PATCH.
MAJOR
.MINOR
.PATCH
Published by RobertCraigie about 3 years ago
Support for aiohttp
and requests
has been removed in favour of httpx, as httpx supports both asynchronous
and synchronous
clients within the same library there is no reason to use aiohttp
or requests
anymore.
This means that the way you install Prisma Client Python will change. You now no longer need to specify an extra, for example
pip install prisma-client[aiohttp]
turns into
pip install prisma-client
The http
option has been replaced with the interface
option. The new interface
option is used to control whether or not the generated client is asynchronous.
If you used aiohttp
before you should use the following:
generator client {
provider = "prisma-client-py"
interface = "asyncio"
}
If you used requests
before you should use the following:
generator client {
provider = "prisma-client-py"
interface = "sync"
}
You can now make use of Prisma's Json
type.
model User {
id Int @default(autoincrement())
meta Json
}
You can create and search for Json
values like so:
from prisma import Json
user = await client.user.create(
data={
'meta': Json.keys(country='Scotland'),
}
)
from prisma import Json
user = await client.user.find_first(
where={
'meta': Json({'country': 'Scotland'})
# or
'meta': {
'equals': Json.keys(country='Scotland'),
'NOT': Json(['foo']),
}
}
)
BigInt
types.Published by RobertCraigie about 3 years ago
This release fixes broken links in the README
Published by RobertCraigie about 3 years ago
This release fixes an issue with unresolvable dev dependencies.
I added twine
as a dev dependency to publish prisma-client-py to PyPi which ended up causing version conflicts. Twine has been removed as a dependency.
Published by RobertCraigie about 3 years ago
This release is the first public release.
Features can be found in the documentation: https://prisma-client-py.readthedocs.io/