add fixes for fastapi model clones, add functionality to add and remove models to relation, add relation proxy, fix all tests, adding values also to pydantic model __dict__some refactors
This commit is contained in:
@ -22,7 +22,7 @@ class Example(ormar.Model):
|
||||
database = database
|
||||
|
||||
id: ormar.Integer(primary_key=True)
|
||||
name: ormar.String(max_length=200, default='aaa')
|
||||
name: ormar.String(max_length=200, default="aaa")
|
||||
created: ormar.DateTime(default=datetime.datetime.now)
|
||||
created_day: ormar.Date(default=datetime.date.today)
|
||||
created_time: ormar.Time(default=time)
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import gc
|
||||
|
||||
import databases
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
from pydantic import ValidationError
|
||||
|
||||
import ormar
|
||||
from ormar.exceptions import NoMatch, MultipleMatches, RelationshipInstanceError
|
||||
from ormar.fields.foreign_key import ForeignKeyField
|
||||
from tests.settings import DATABASE_URL
|
||||
|
||||
database = databases.Database(DATABASE_URL, force_rollback=True)
|
||||
@ -133,7 +133,9 @@ async def test_model_crud():
|
||||
assert album1.pk == 1
|
||||
assert album1.tracks == []
|
||||
|
||||
await Track.objects.create(album={"id": track.album.pk}, title="The Bird2", position=4)
|
||||
await Track.objects.create(
|
||||
album={"id": track.album.pk}, title="The Bird2", position=4
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@ -164,6 +166,47 @@ async def test_select_related():
|
||||
assert len(tracks) == 6
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_removal_from_relations():
|
||||
async with database:
|
||||
album = Album(name="Chichi")
|
||||
await album.save()
|
||||
track1 = Track(album=album, title="The Birdman", position=1)
|
||||
track2 = Track(album=album, title="Superman", position=2)
|
||||
track3 = Track(album=album, title="Wonder Woman", position=3)
|
||||
await track1.save()
|
||||
await track2.save()
|
||||
await track3.save()
|
||||
|
||||
assert len(album.tracks) == 3
|
||||
album.tracks.remove(track1)
|
||||
assert len(album.tracks) == 2
|
||||
assert track1.album is None
|
||||
|
||||
await track1.update()
|
||||
track1 = await Track.objects.get(title="The Birdman")
|
||||
assert track1.album is None
|
||||
|
||||
album.tracks.add(track1)
|
||||
assert len(album.tracks) == 3
|
||||
assert track1.album == album
|
||||
|
||||
await track1.update()
|
||||
track1 = await Track.objects.select_related("album__tracks").get(
|
||||
title="The Birdman"
|
||||
)
|
||||
album = await Album.objects.select_related("tracks").get(name="Chichi")
|
||||
assert track1.album == album
|
||||
|
||||
track1.remove(album)
|
||||
assert track1.album is None
|
||||
assert len(album.tracks) == 2
|
||||
|
||||
track2.remove(album)
|
||||
assert track2.album is None
|
||||
assert len(album.tracks) == 1
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_fk_filter():
|
||||
async with database:
|
||||
@ -182,8 +225,8 @@ async def test_fk_filter():
|
||||
|
||||
tracks = (
|
||||
await Track.objects.select_related("album")
|
||||
.filter(album__name="Fantasies")
|
||||
.all()
|
||||
.filter(album__name="Fantasies")
|
||||
.all()
|
||||
)
|
||||
assert len(tracks) == 3
|
||||
for track in tracks:
|
||||
@ -191,8 +234,8 @@ async def test_fk_filter():
|
||||
|
||||
tracks = (
|
||||
await Track.objects.select_related("album")
|
||||
.filter(album__name__icontains="fan")
|
||||
.all()
|
||||
.filter(album__name__icontains="fan")
|
||||
.all()
|
||||
)
|
||||
assert len(tracks) == 3
|
||||
for track in tracks:
|
||||
@ -234,8 +277,8 @@ async def test_multiple_fk():
|
||||
|
||||
members = (
|
||||
await Member.objects.select_related("team__org")
|
||||
.filter(team__org__ident="ACME Ltd")
|
||||
.all()
|
||||
.filter(team__org__ident="ACME Ltd")
|
||||
.all()
|
||||
)
|
||||
assert len(members) == 4
|
||||
for member in members:
|
||||
@ -254,8 +297,8 @@ async def test_pk_filter():
|
||||
|
||||
tracks = (
|
||||
await Track.objects.select_related("album")
|
||||
.filter(position=2, album__name="Test")
|
||||
.all()
|
||||
.filter(position=2, album__name="Test")
|
||||
.all()
|
||||
)
|
||||
assert len(tracks) == 1
|
||||
|
||||
|
||||
@ -54,7 +54,9 @@ class ExampleModel2(Model):
|
||||
|
||||
@pytest.fixture()
|
||||
def example():
|
||||
return ExampleModel(pk=1, test_string="test", test_bool=True, test_decimal=decimal.Decimal(3.5))
|
||||
return ExampleModel(
|
||||
pk=1, test_string="test", test_bool=True, test_decimal=decimal.Decimal(3.5)
|
||||
)
|
||||
|
||||
|
||||
def test_not_nullable_field_is_required():
|
||||
@ -110,6 +112,7 @@ def test_sqlalchemy_table_is_created(example):
|
||||
|
||||
def test_no_pk_in_model_definition():
|
||||
with pytest.raises(ModelDefinitionError):
|
||||
|
||||
class ExampleModel2(Model):
|
||||
class Meta:
|
||||
tablename = "example3"
|
||||
@ -120,6 +123,7 @@ def test_no_pk_in_model_definition():
|
||||
|
||||
def test_two_pks_in_model_definition():
|
||||
with pytest.raises(ModelDefinitionError):
|
||||
|
||||
class ExampleModel2(Model):
|
||||
class Meta:
|
||||
tablename = "example3"
|
||||
@ -131,6 +135,7 @@ def test_two_pks_in_model_definition():
|
||||
|
||||
def test_setting_pk_column_as_pydantic_only_in_model_definition():
|
||||
with pytest.raises(ModelDefinitionError):
|
||||
|
||||
class ExampleModel2(Model):
|
||||
class Meta:
|
||||
tablename = "example4"
|
||||
@ -141,6 +146,7 @@ def test_setting_pk_column_as_pydantic_only_in_model_definition():
|
||||
|
||||
def test_decimal_error_in_model_definition():
|
||||
with pytest.raises(ModelDefinitionError):
|
||||
|
||||
class ExampleModel2(Model):
|
||||
class Meta:
|
||||
tablename = "example5"
|
||||
@ -151,6 +157,7 @@ def test_decimal_error_in_model_definition():
|
||||
|
||||
def test_string_error_in_model_definition():
|
||||
with pytest.raises(ModelDefinitionError):
|
||||
|
||||
class ExampleModel2(Model):
|
||||
class Meta:
|
||||
tablename = "example6"
|
||||
|
||||
@ -28,7 +28,7 @@ class User(ormar.Model):
|
||||
database = database
|
||||
|
||||
id: ormar.Integer(primary_key=True)
|
||||
name: ormar.String(max_length=100, default='')
|
||||
name: ormar.String(max_length=100, default="")
|
||||
|
||||
|
||||
class Product(ormar.Model):
|
||||
|
||||
@ -79,7 +79,7 @@ async def create_category(category: Category):
|
||||
@app.put("/items/{item_id}")
|
||||
async def get_item(item_id: int, item: Item):
|
||||
item_db = await Item.objects.get(pk=item_id)
|
||||
return {"updated_rows": await item_db.update(**item.dict())}
|
||||
return await item_db.update(**item.dict())
|
||||
|
||||
|
||||
@app.delete("/items/{item_id}")
|
||||
@ -105,7 +105,7 @@ def test_all_endpoints():
|
||||
|
||||
item.name = "New name"
|
||||
response = client.put(f"/items/{item.pk}", json=item.dict())
|
||||
assert response.json().get("updated_rows") == 1
|
||||
assert response.json() == item.dict()
|
||||
|
||||
response = client.get("/items/")
|
||||
items = [Item(**item) for item in response.json()]
|
||||
|
||||
@ -101,10 +101,10 @@ async def test_model_multiple_instances_of_same_table_in_schema():
|
||||
assert classes[0].name == "Math"
|
||||
assert classes[0].students[0].name == "Jane"
|
||||
assert len(classes[0].dict().get("students")) == 2
|
||||
assert classes[0].teachers[0].category.department.name == 'Law Department'
|
||||
assert classes[0].teachers[0].category.department.name == "Law Department"
|
||||
|
||||
assert classes[0].students[0].category.pk is not None
|
||||
assert classes[0].students[0].category.name is None
|
||||
await classes[0].students[0].category.load()
|
||||
await classes[0].students[0].category.department.load()
|
||||
assert classes[0].students[0].category.department.name == 'Math Department'
|
||||
assert classes[0].students[0].category.department.name == "Math Department"
|
||||
|
||||
Reference in New Issue
Block a user