Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Actions: custom PK (except id) is not passed to ModelAction.handle() #165

Open
prostospirit opened this issue Mar 17, 2024 · 6 comments
Open

Comments

@prostospirit
Copy link

prostospirit commented Mar 17, 2024

For example, I have the following model:

class Promoaction(SQLModel, table=True):
    __tablename__ = "promoaction"

    promoaction_id: int
    name: str

I have the next admin:

class ActionAdmin(admin.ModelAdmin):
    page_schema = 'Promoaction Management'
    model = Promoaction
    pk_name = 'promoaction_id'     # set custom pk

    admin_action_maker = [
        lambda self: LoadMailsByAction(self, name="load_mails_action", label="Load Mails", flags=["item", "load_mails"]),
    ]

and i have the next action:

class LoadMailsByAction(admin.ModelAction):
    action = ActionType.Dialog(tooltip="Upload mails by promoaction", icon="fa fa-paper-plane", level=LevelEnum.warning,
                               dialog=Dialog())

    class schema(BaseModel):
        promoaction_ids: list[int] = Field(None, title="Enter promoaction IDs")

    async def handle(self, request: Request, item_id: List[str], data: Optional[SchemaUpdateT], **kwargs) -> BaseApiOut[Any]:
        items: list[Action] = await self.admin.fetch_items(*item_id)
        responses: dict[int, str] = {}
        for promoaction_id in data.promoaction_ids:
            result = update_mails_without_filesystem(action_id=promoaction_id)
            responses.update({promoaction_id: result})
        return BaseApiOut(data=responses)

I expected that item_id would be passed to the handle function in the item_id parameter, but it does not arrive.

Same time in the browser console I see the following request:

http://...:8000/admin/my_app/PromoactionAdmin/LoadMailsByAction/api?item_id= (item_id is empty)

What needs to be done for this to work correctly? I tried to find this configuration settings but failed. Thanks in advance for your answer and for the project!

@mmmcorpsvit
Copy link

i think, Request must contain all fields and request data

@prostospirit
Copy link
Author

prostospirit commented Mar 25, 2024

I experimented a bit and realized that it is possible to override ModelAction.get_action

It will looks like a

   async def get_action(self, request: Request, **kwargs) -> Action:
        action = await super().get_action(request, **kwargs)
        node: AmisNode = getattr(action, action.actionType, None)
        if node:
            node.body = Service(
                schemaApi=AmisAPI(
                    method="post",
        >>>>>       url=self.router_path + self.page_path + "?item_id=${IF(promoaction_ids, promoaction_ids, promoaction_id)}",  # override default PK name
                    responseData={
                        "&": "${body}",
                        "api.url": "${body.api.url}?item_id=${api.query.item_id}",
                        "initApi.url": "${body.initApi.url}?item_id=${api.query.item_id}" if self.form_init else None,
                        "submitText": "",
                    },
                )
            )
        return action

and it will works correctly, but I think this should be provided by the functionality or there should be a more friendly interface for this

@mmmcorpsvit
Copy link

mmmcorpsvit commented Mar 25, 2024

you can set

class CarCategoryAdmin(admin.ModelAdmin):
    page_schema = PageSchema(label="Car Category", icon="fa fa-truck")
    model = CarCategory

    pk_name: str = "id" # no ?

@prostospirit
Copy link
Author

prostospirit commented Mar 25, 2024

@mmmcorpsvit no, it doesn't work correctly for me to perform actions on records. If I set only pk_name, then item_id is empty when I make request for action from admin to backend.

the meaning is that I want to use the first key's name other than id

@amisadmin
Copy link
Owner

I'm not sure if this will work, but you can try the idea of defining a virtual id foreign key.

from sqlmodelx import SQLModel
from sqlmodel import Field
from sqlalchemy import column_property
from fastapi_amis_admin import admin

class Promoaction(SQLModel, table=True):
    __tablename__ = "promoaction"

    promoaction_id: int
    name: str

class Promoaction2(Promoaction, table=True):
    id: int = Field(
        None,
        title="Read-only primary key",
        sa_column=column_property(Promoaction.promoaction_id),
    )
    
class ActionAdmin(admin.ModelAdmin):
    page_schema = 'Promoaction Management'
    model = Promoaction2

@prostospirit
Copy link
Author

@amisadmin

can try the idea of defining a virtual id foreign key.

I checked but it didn't work.

Traceback:

Traceback (most recent call last):
  File "/home/sergei/.pycharm_helpers/pydev/pydevd.py", line 1534, in _exec
    pydev_imports.execfile(file, globals, locals)  # execute the script
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sergei/.pycharm_helpers/pydev/_pydev_imps/_pydev_execfile.py", line 18, in execfile
    exec(compile(contents+"\n", file, 'exec'), glob, loc)
  File "..../admin_backend/main.py", line 19, in <module>
    site.mount_app(app)
  File "..../python3.12/site-packages/fastapi_amis_admin/admin/admin.py", line 1536, in mount_app
    self.register_router()
  File "..../python3.12/site-packages/fastapi_amis_admin/admin/admin.py", line 1402, in register_router
    self._register_admin_router_all()
  File "..../python3.12/site-packages/fastapi_amis_admin/admin/admin.py", line 1394, in _register_admin_router_all
    admin.register_router()
  File "..../python3.12/site-packages/fastapi_amis_admin/admin/admin.py", line 1400, in register_router
    self._create_admin_instance_all()
  File "..../python3.12/site-packages/fastapi_amis_admin/admin/admin.py", line 1386, in _create_admin_instance_all
    [self.get_admin_or_create(admin_cls) for admin_cls in self._registered.keys()]
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "..../python3.12/site-packages/fastapi_amis_admin/admin/admin.py", line 1361, in get_admin_or_create
    admin = admin_cls(self)
            ^^^^^^^^^^^^^^^
  File "..../python3.12/site-packages/fastapi_amis_admin/admin/admin.py", line 646, in __init__
    SqlalchemyCrud.__init__(self, self.model, self.engine)
  File "..../python3.12/site-packages/fastapi_amis_admin/crud/_sqlalchemy.py", line 265, in __init__
    SqlalchemySelector.__init__(self, model, fields)
  File "..../python3.12/site-packages/fastapi_amis_admin/crud/_sqlalchemy.py", line 124, in __init__
    assert self.fields, "fields is None"
AssertionError: fields is None

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants