Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions crudadmin/admin_interface/crud_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -803,6 +803,7 @@ def add_view(
update_schema: Type[BaseModel],
update_internal_schema: Optional[Type[BaseModel]] = None,
delete_schema: Optional[Type[BaseModel]] = None,
select_schema: Optional[Type[BaseModel]] = None,
include_in_models: bool = True,
allowed_actions: Optional[set[str]] = None,
password_transformer: Optional[Any] = None,
Expand All @@ -819,6 +820,7 @@ def add_view(
update_schema: Pydantic schema for update operations
update_internal_schema: Internal schema for special update cases
delete_schema: Schema for delete operations
select_schema: Optional schema for read operations (excludes fields from queries)
include_in_models: Show in models list in admin UI
allowed_actions: **Set of allowed operations:**
- **"view"**: Allow viewing records
Expand All @@ -835,6 +837,7 @@ def add_view(
Notes:
- Forms are auto-generated with field types determined from Pydantic schemas
- Actions controlled by allowed_actions parameter
- Use select_schema to exclude problematic fields (e.g., TSVector) from read operations
- Use password_transformer for models with password fields that need hashing

URL Routes:
Expand Down Expand Up @@ -872,6 +875,29 @@ class UserUpdate(BaseModel):
)
```

Excluding problematic fields (e.g., TSVector):
```python
class DocumentCreate(BaseModel):
title: str
content: str
# TSVector field excluded from this schema

class DocumentSelect(BaseModel):
id: int
title: str
content: str
created_at: datetime
# search_vector (TSVector) field excluded

admin.add_view(
model=Document,
create_schema=DocumentCreate,
update_schema=DocumentCreate,
select_schema=DocumentSelect, # TSVector field excluded from reads
allowed_actions={"view", "create", "update"}
)
```

User with password handling:
```python
from crudadmin.admin_interface.model_view import PasswordTransformer
Expand Down Expand Up @@ -1028,6 +1054,7 @@ class Config:
update_schema=update_schema,
update_internal_schema=update_internal_schema,
delete_schema=delete_schema,
select_schema=select_schema,
admin_site=self.admin_site,
allowed_actions=allowed_actions,
event_integration=self.event_integration,
Expand Down
21 changes: 17 additions & 4 deletions crudadmin/admin_interface/model_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -772,7 +772,10 @@ async def bulk_delete_endpoint_inner(
f"{pk_name}__in": valid_ids
}
records_to_delete = await self.crud.get_multi(
db=db, limit=len(valid_ids), **cast(Any, filter_criteria)
db=db,
limit=len(valid_ids),
schema_to_select=self.select_schema,
**cast(Any, filter_criteria),
)

request.state.deleted_records = records_to_delete.get("data", [])
Expand Down Expand Up @@ -804,6 +807,7 @@ async def bulk_delete_endpoint_inner(
db=db,
offset=(adjusted_page - 1) * rows_per_page,
limit=rows_per_page,
schema_to_select=self.select_schema,
)

items: Dict[str, Any] = {
Expand Down Expand Up @@ -947,6 +951,7 @@ async def get_model_admin_page_inner(
limit=rows_per_page,
sort_columns=sort_columns,
sort_orders=sort_orders,
schema_to_select=self.select_schema,
**cast(Any, filter_criteria),
)

Expand Down Expand Up @@ -1053,7 +1058,9 @@ async def get_model_update_page_inner(
db: AsyncSession = Depends(self.session),
) -> Response:
"""Show a form to update an existing record by `id`."""
item = await self.crud.get(db=db, id=id)
item = await self.crud.get(
db=db, id=id, schema_to_select=self.select_schema
)
if not item:
return JSONResponse(
status_code=404, content={"message": f"Item with id {id} not found"}
Expand Down Expand Up @@ -1112,7 +1119,9 @@ async def form_update_endpoint_inner(
status_code=422, content={"message": "No id parameter provided"}
)

item = await self.crud.get(db=db, id=id)
item = await self.crud.get(
db=db, id=id, schema_to_select=self.select_schema
)
if not item:
return JSONResponse(
status_code=404, content={"message": f"Item with id {id} not found"}
Expand Down Expand Up @@ -1283,7 +1292,11 @@ async def table_body_content_inner(
filter_criteria[f"{search_column}__ilike"] = f"%{search_value}%"

items_result = await self.crud.get_multi(
db=db, offset=offset, limit=limit, **cast(Any, filter_criteria)
db=db,
offset=offset,
limit=limit,
schema_to_select=self.select_schema,
**cast(Any, filter_criteria),
)

items: Dict[str, Any] = {
Expand Down
Loading
Loading