Pynecone full-stack framework CRUD boilerplate
Project description
pynecone-admin
A generic CRUD Model
boilerplate for the python-based full stack
pynecone framework.
- Simple, extendable login state and redirect helpers
add_crud_routes
method adds Create, Update, Read, Delete capabilities to specified models
Example
See ./example/example/example.py.
Usage
- Include
pynecone-admin
in your projectrequirements.txt
. - Call
pynecone_admin.add_crud_routes(app=app, obs=[pynecone_admin.User, Widget], prefix="/crud")
pc init && pc run
- Access models at
/crud
.
API
Authentication
Per-page authentication is provided by pynecone_admin.login_required
. It can be used
as a decorator on a page function.
@pynecone_admin.login_required(State)
def page():
return pc.text("You are logged in as ", State.authenticated_user_id)
A custom login_component
can be passed as a parameter, see
pynecone_admin.auth.default_login_component
as an example for how to customize
the logic. A custom component must call State._login(self, user_id)
to
authenticate a session for the given user_id
.
If no users exist in the database, the default login component will create the first user to login as an admin.
By default, only authenticated_user_id
is provided, if access to the provided User model is needed, implement a small helper in the local app State
(from the example):
class State(pc.State):
@pc.cached_var
def authenticated_user(self) -> User:
if self.authenticated_user_id >= 0:
with pc.session() as session:
if user := session.exec(
User.select.where(User.id == self.authenticated_user_id),
).one_or_none():
return user
return User()
Persistent Token
Using the login_required
function will automatically augment the passed State
class with
additional variables and functionality:
current_token
: a persistent (localStorage
-backed) value that identifies the client browser. This value is updated by thePersistentToken.on_change
event handler defined inside thelogin_required
function.authenticated_user_id
: the user_id associated with a non-expired auth session matching the state'scurrent_token
. If no such session exists,-1
.do_logout
: event handler that disassociates the state'scurrent_token
with any valid auth session_login
: backend-only function that associates the state'scurrent_token
with the givenuser_id
(values less than 0 are ignored). To implement a custom login method, the code must somehow callState._login(self, user_id)
after properly authenticating the user_id.
CRUD - Create Read Update Delete
The primary entry point is pynecone_admin.add_crud_routes
. Two arguments are required:
app
: pass an instance of yourpc.App
objs
: pass a sequence ofpc.Model
classes that should be available for editing
Additional arguments are available to customize the crud pages:
form_component
: function called to render the object create/edit form, defaults topynecone_admin.crud.default_form_component
.field_component
: function called to render a single field in the form, defaults topynecone_admin.crud.default_field_component
.login_component
: function called to render the user login form, defaults to to no login form. If protected access is required, passpynecone_admin.default_login_component
or another custom login component.can_access_resource
: access control function accepting state instance as first parameter, defaults to open access if not presentprefix
: route prefix for admin operations, defaults to/crud
Supported Field Types
See pynecone_admin.crud.default_field_component
.
Simple Types
str
,float
: standardpc.input
int
:pc.number_input
bool
:pc.check_box
Special Types
enum.Enum
:pc.select
drop down boxdatetime.datetime
:pc.input
withtype_="datetime-local"
, which renders a date picker on modern browsers.uuid.UUID
: standardpc.input
with a "random" button that sets the value to"random"
(handled inset_subfield
).
Why are these types special? Because pynecone cannot handle them out of the box,
although they work fine via sqlmodel / sqlalchemy. The solution is to convert
them to serializable types by overriding the dict()
method of the model:
from __future__ import annotations
import datetime
import enum
import uuid
import pynecone as pc
import pynecone_admin
import sqlmodel
class TokenStatus(enum.Enum):
ACTIVE = "active"
DISABLED = "disabled"
class TokenOwner(pc.Model, table=True):
user_id: int
token_uuid: uuid.UUID
created: datetime.datetime = sqlmodel.Field(
sa_column=sqlmodel.Column(
sqlmodel.DateTime(timezone=True),
server_default=sqlmodel.func.now(),
),
)
status: TokenStatus
comment: str | None = None
def dict(self, *args, **kwargs):
d = super().dict(*args, **kwargs)
d["token_uuid"] = str(self.token_uuid) if self.token_uuid else None
d["created"] = (
self.created.replace(microsecond=0).isoformat() if self.created else None
)
d["status"] = self.status.name if self.status else None
return d
class State(pc.State):
pass
app = pc.App(state=State)
pynecone_admin.add_crud_routes(app, [TokenOwner], prefix="/")
app.compile()
The save field handler, set_subfield
, currently handles deserializing these types as
special cases.
Customizing Per-Model Behavior
pynecone-admin
respects specially named hook methods or attributes attached to
Models, to allow behavioral customization:
__pynecone_admin_fields__: Sequence[str]
: names of fields to include in the table and editor form. Allows for rendering a subset of available fields. Default uses all fields defined on the model.__pynecone_admin_load_object_hook__
: method called on each instance after it is loaded from the database for editing.__pynecone_admin_load_row_hook__
: method called on each instance after it is loaded from the database during enumeration (for the table).__pynecone_admin_filter_where_hook__
: classmethod accepting a string,filter_value
, that returns an expression passable to sqlmodelwhere()
selector to filter the table query based on a user-supplied value. Default filter hook casts all columns as string and performs a wildcard match (LIKE %{filter_value}%
) on each.__pynecone_admin_save_object_hook__
: method called on each instance before it is persisted to the database. The includedUser
model, implements this hook to hash password strings that don't look like valid hashes before saving.__pynecone_admin_delete_object_hook__
: method called on each instance before it is deleted from the database.
Changelog
v0.1a0 - 2023-05-31
Alpha Release
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file pynecone-admin-0.1a0.tar.gz
.
File metadata
- Download URL: pynecone-admin-0.1a0.tar.gz
- Upload date:
- Size: 25.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.11.3
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 9ec2e463bcf0dac67e53fb9ae7bc404d910f112ee7170dd950fcd5ab1dff5cec |
|
MD5 | 5b0765ca6055edbe672d0fe534746be9 |
|
BLAKE2b-256 | b6b8634cf00742c14096f8a5b941bc5163aa4b1d9727e04096dd54c1a8706c9d |
File details
Details for the file pynecone_admin-0.1a0-py3-none-any.whl
.
File metadata
- Download URL: pynecone_admin-0.1a0-py3-none-any.whl
- Upload date:
- Size: 19.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.11.3
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2959333750d76f044cc39c870af3d04014ba1b2c5ff7314054e3496baba5aecb |
|
MD5 | dcbe0dcec409860c6dc17aed64d605c0 |
|
BLAKE2b-256 | 306aaf3367c895c45cebf8676f744c8fa914783bd010f2668c19a9aac485487a |