@@ -33,8 +33,7 @@ async def test_delete_model_by_id_not_found(db: AsyncSession, crud_ins: CRUDPlus
3333async def test_delete_model_with_flush (db : AsyncSession , sample_ins : list [Ins ], crud_ins : CRUDPlus [Ins ]):
3434 item = sample_ins [1 ]
3535
36- async with db .begin ():
37- count = await crud_ins .delete_model (db , item .id , flush = True )
36+ count = await crud_ins .delete_model (db , item .id , flush = True )
3837
3938 assert count == 1
4039
@@ -52,10 +51,15 @@ async def test_delete_model_with_commit(db: AsyncSession, sample_ins: list[Ins],
5251async def test_delete_model_by_column_basic (db : AsyncSession , sample_ins : list [Ins ], crud_ins : CRUDPlus [Ins ]):
5352 item = sample_ins [3 ]
5453
55- async with db . begin ():
56- count = await crud_ins . delete_model_by_column ( db , allow_multiple = True , name = item . name )
54+ before_exists = await crud_ins . exists ( db , name = item . name )
55+ assert before_exists is True
5756
58- assert count >= 0
57+ count = await crud_ins .delete_model_by_column (db , allow_multiple = True , commit = True , name = item .name )
58+
59+ assert count > 0
60+
61+ after_exists = await crud_ins .exists (db , name = item .name )
62+ assert after_exists is False
5963
6064
6165@pytest .mark .asyncio
@@ -68,29 +72,45 @@ async def test_delete_model_by_column_not_found(db: AsyncSession, crud_ins: CRUD
6872
6973@pytest .mark .asyncio
7074async def test_delete_model_by_column_allow_multiple (db : AsyncSession , sample_ins : list [Ins ], crud_ins : CRUDPlus [Ins ]):
71- async with db . begin ():
72- count = await crud_ins . delete_model_by_column ( db , allow_multiple = True , is_deleted = False )
75+ before_count = await crud_ins . count ( db , is_deleted = False )
76+ assert before_count > 0
7377
74- assert count >= 0
78+ count = await crud_ins .delete_model_by_column (db , allow_multiple = True , commit = True , is_deleted = False )
79+
80+ assert count == before_count
81+
82+ after_count = await crud_ins .count (db , is_deleted = False )
83+ assert after_count == 0
7584
7685
7786@pytest .mark .asyncio
7887async def test_delete_model_by_column_with_flush (db : AsyncSession , sample_ins : list [Ins ], crud_ins : CRUDPlus [Ins ]):
7988 item = sample_ins [4 ]
8089
81- async with db . begin ():
82- count = await crud_ins . delete_model_by_column ( db , allow_multiple = True , flush = True , name = item . name )
90+ before_exists = await crud_ins . exists ( db , name = item . name )
91+ assert before_exists is True
8392
84- assert count >= 0
93+ count = await crud_ins .delete_model_by_column (db , allow_multiple = True , commit = True , name = item .name )
94+
95+ assert count > 0
96+
97+ after_exists = await crud_ins .exists (db , name = item .name )
98+ assert after_exists is False
8599
86100
87101@pytest .mark .asyncio
88102async def test_delete_model_by_column_with_commit (db : AsyncSession , sample_ins : list [Ins ], crud_ins : CRUDPlus [Ins ]):
89103 item = sample_ins [5 ]
90104
105+ before_exists = await crud_ins .exists (db , name = item .name )
106+ assert before_exists is True
107+
91108 count = await crud_ins .delete_model_by_column (db , allow_multiple = True , commit = True , name = item .name )
92109
93- assert count >= 0
110+ assert count > 0
111+
112+ after_exists = await crud_ins .exists (db , name = item .name )
113+ assert after_exists is False
94114
95115
96116@pytest .mark .asyncio
@@ -104,7 +124,9 @@ async def test_delete_model_by_column_no_filters_error(db: AsyncSession, crud_in
104124async def test_delete_model_by_column_multiple_results_error (
105125 db : AsyncSession , sample_ins : list [Ins ], crud_ins : CRUDPlus [Ins ]
106126):
107- with pytest .raises (Exception ):
127+ from sqlalchemy_crud_plus .errors import MultipleResultsError
128+
129+ with pytest .raises (MultipleResultsError ):
108130 async with db .begin ():
109131 await crud_ins .delete_model_by_column (db , is_deleted = False )
110132
@@ -130,20 +152,22 @@ async def test_logical_delete_single_record(db: AsyncSession, sample_ins: list[I
130152
131153@pytest .mark .asyncio
132154async def test_logical_delete_multiple_records (db : AsyncSession , sample_ins : list [Ins ], crud_ins : CRUDPlus [Ins ]):
133- async with db .begin ():
134- count = await crud_ins .delete_model_by_column (
135- db ,
136- logical_deletion = True ,
137- deleted_flag_column = 'is_deleted' ,
138- allow_multiple = True ,
139- is_deleted = False ,
140- )
155+ before_count = await crud_ins .count (db , is_deleted = False )
156+ assert before_count > 0
141157
142- assert count >= 0
158+ count = await crud_ins .delete_model_by_column (
159+ db ,
160+ logical_deletion = True ,
161+ deleted_flag_column = 'is_deleted' ,
162+ allow_multiple = True ,
163+ commit = True ,
164+ is_deleted = False ,
165+ )
143166
144- async with db .begin ():
145- remaining_false = await crud_ins .select_models (db , is_deleted = False )
146- assert len (remaining_false ) >= 0
167+ assert count == before_count
168+
169+ remaining_false = await crud_ins .select_models (db , is_deleted = False )
170+ assert len (remaining_false ) == 0
147171
148172
149173@pytest .mark .asyncio
@@ -164,37 +188,36 @@ async def test_logical_delete_with_custom_column(db: AsyncSession, sample_ins: l
164188
165189@pytest .mark .asyncio
166190async def test_logical_delete_with_filters (db : AsyncSession , sample_ins : list [Ins ], crud_ins : CRUDPlus [Ins ]):
167- async with db .begin ():
168- count = await crud_ins .delete_model_by_column (
169- db ,
170- logical_deletion = True ,
171- deleted_flag_column = 'is_deleted' ,
172- allow_multiple = True ,
173- name__like = 'item_%' ,
174- id__gt = 3 ,
175- )
191+ await crud_ins .count (db , name__like = 'item_%' , id__gt = 3 , is_deleted = False )
176192
177- assert count >= 0
193+ count = await crud_ins .delete_model_by_column (
194+ db ,
195+ logical_deletion = True ,
196+ deleted_flag_column = 'is_deleted' ,
197+ allow_multiple = True ,
198+ commit = True ,
199+ name__like = 'item_%' ,
200+ id__gt = 3 ,
201+ )
178202
179- async with db .begin ():
180- deleted_items = await crud_ins .select_models (db , name__like = 'item_%' , id__gt = 3 , is_deleted = True )
203+ assert count >= 0
181204
182- assert len (deleted_items ) >= 0
205+ deleted_items = await crud_ins .select_models (db , name__like = 'item_%' , id__gt = 3 , is_deleted = True )
206+ assert len (deleted_items ) >= count
183207
184208
185209@pytest .mark .asyncio
186210async def test_logical_delete_with_flush (db : AsyncSession , sample_ins : list [Ins ], crud_ins : CRUDPlus [Ins ]):
187211 item = sample_ins [2 ]
188212
189- async with db .begin ():
190- count = await crud_ins .delete_model_by_column (
191- db ,
192- logical_deletion = True ,
193- deleted_flag_column = 'is_deleted' ,
194- allow_multiple = False ,
195- flush = True ,
196- id = item .id ,
197- )
213+ count = await crud_ins .delete_model_by_column (
214+ db ,
215+ logical_deletion = True ,
216+ deleted_flag_column = 'is_deleted' ,
217+ allow_multiple = False ,
218+ flush = True ,
219+ id = item .id ,
220+ )
198221
199222 assert count == 1
200223
@@ -234,20 +257,23 @@ async def test_logical_delete_no_matching_records(db: AsyncSession, crud_ins: CR
234257
235258@pytest .mark .asyncio
236259async def test_logical_delete_already_deleted_records (db : AsyncSession , sample_ins : list [Ins ], crud_ins : CRUDPlus [Ins ]):
237- async with db . begin ():
238- await crud_ins . delete_model_by_column (
239- db , logical_deletion = True , deleted_flag_column = 'is_deleted' , allow_multiple = True , id__le = 3
240- )
260+ first_count = await crud_ins . delete_model_by_column (
261+ db , logical_deletion = True , deleted_flag_column = 'is_deleted' , allow_multiple = True , commit = True , id__le = 3
262+ )
263+ assert first_count >= 0
241264
242- async with db .begin ():
243- count = await crud_ins .delete_model_by_column (
244- db ,
245- logical_deletion = True ,
246- deleted_flag_column = 'is_deleted' ,
247- allow_multiple = True ,
248- id__le = 3 ,
249- is_deleted = True ,
250- )
265+ already_deleted_count = await crud_ins .count (db , id__le = 3 , is_deleted = True )
266+ assert already_deleted_count >= first_count
267+
268+ count = await crud_ins .delete_model_by_column (
269+ db ,
270+ logical_deletion = True ,
271+ deleted_flag_column = 'is_deleted' ,
272+ allow_multiple = True ,
273+ commit = True ,
274+ id__le = 3 ,
275+ is_deleted = True ,
276+ )
251277
252278 assert count >= 0
253279
@@ -295,23 +321,22 @@ async def test_logical_delete_single_but_multiple_found(
295321async def test_logical_delete_affects_count (db : AsyncSession , sample_ins : list [Ins ], crud_ins : CRUDPlus [Ins ]):
296322 initial_count = await crud_ins .count (db , is_deleted = False )
297323
324+ to_delete_count = await crud_ins .count (db , id__le = 2 , is_deleted = False )
325+
298326 deleted_count = await crud_ins .delete_model_by_column (
299327 db ,
300328 logical_deletion = True ,
301329 deleted_flag_column = 'is_deleted' ,
302330 allow_multiple = True ,
303331 commit = True ,
304332 id__le = 2 ,
333+ is_deleted = False ,
305334 )
306335
307336 final_count = await crud_ins .count (db , is_deleted = False )
308337
309- # 检查是否至少删除了一条记录
310- assert deleted_count >= 0
311-
312- # 如果删除了记录,则最终计数应该小于或等于初始计数
313- if deleted_count > 0 :
314- assert final_count <= initial_count
338+ assert deleted_count == to_delete_count
339+ assert final_count == initial_count - deleted_count
315340
316341
317342@pytest .mark .asyncio
@@ -359,7 +384,6 @@ async def test_logical_delete_with_select_models(db: AsyncSession, sample_ins: l
359384
360385@pytest .mark .asyncio
361386async def test_delete_model_by_column_with_deleted_at (db : AsyncSession , sample_ins : list [Ins ], crud_ins : CRUDPlus [Ins ]):
362- # 使用数据库中存在的项目
363387 item = sample_ins [6 ]
364388
365389 async with db .begin ():
@@ -378,7 +402,6 @@ async def test_delete_model_by_column_with_deleted_at(db: AsyncSession, sample_i
378402async def test_delete_model_by_column_without_deleted_at_column (
379403 db : AsyncSession , sample_ins : list [Ins ], crud_ins : CRUDPlus [Ins ]
380404):
381- # 使用数据库中存在的项目
382405 item = sample_ins [7 ]
383406
384407 async with db .begin ():
@@ -390,3 +413,30 @@ async def test_delete_model_by_column_without_deleted_at_column(
390413 updated_item = await crud_ins .select_model (db , item .id )
391414 assert updated_item is not None
392415 assert updated_item .is_deleted is True
416+
417+
418+ @pytest .mark .asyncio
419+ async def test_delete_model_by_column_with_custom_deleted_at_column (
420+ db : AsyncSession , sample_ins : list [Ins ], crud_ins : CRUDPlus [Ins ]
421+ ):
422+ from datetime import datetime , timezone
423+
424+ item = sample_ins [8 ]
425+
426+ async with db .begin ():
427+ count = await crud_ins .delete_model_by_column (
428+ db ,
429+ logical_deletion = True ,
430+ deleted_flag_column = 'is_deleted' ,
431+ deleted_at_column = 'updated_time' ,
432+ deleted_at_factory = datetime .now (timezone .utc ),
433+ id = item .id ,
434+ )
435+
436+ assert count == 1
437+
438+ async with db .begin ():
439+ updated_item = await crud_ins .select_model (db , item .id )
440+ assert updated_item is not None
441+ assert updated_item .is_deleted is True
442+ assert updated_item .updated_time is not None
0 commit comments