This release is a pre-release and may not be stable for production use.
pynecone-admin
A generic CRUD Model boilerplate for the python-based full stack
pynecone framework.
- Simple, extendable login state and redirect helpers
add_crud_routesmethod adds Create, Update, Read, Delete capabilities to specified models
Example
See ./example/example/example.py.
Usage
- Include
pynecone-adminin 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_changeevent handler defined inside thelogin_requiredfunction.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_tokenwith any valid auth session_login: backend-only function that associates the state'scurrent_tokenwith 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.Appobjs: pass a sequence ofpc.Modelclasses 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_componentor 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.inputint:pc.number_inputbool:pc.check_box
Special Types
enum.Enum:pc.selectdrop down boxdatetime.datetime:pc.inputwithtype_="datetime-local", which renders a date picker on modern browsers.uuid.UUID: standardpc.inputwith 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 includedUsermodel, 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
Release files for pynecone-admin 0.1a0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pynecone-admin-0.1a0.tar.gz | 25.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pynecone_admin-0.1a0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 45.2 kB
Release files / pynecone-admin-0.1a0.tar.gz
| Download URL | pynecone-admin-0.1a0.tar.gz |
|---|---|
| Size | 25.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9ec2e463bcf0dac67e53fb9ae7bc404d910f112ee7170dd950fcd5ab1dff5cec
|
|
BLAKE2b-256 checksum How to use checksums |
b6b8634cf00742c14096f8a5b941bc5163aa4b1d9727e04096dd54c1a8706c9d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/4.0.2 CPython/3.11.3
|
Release files / pynecone_admin-0.1a0-py3-none-any.whl
| Download URL | pynecone_admin-0.1a0-py3-none-any.whl |
|---|---|
| Size | 19.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2959333750d76f044cc39c870af3d04014ba1b2c5ff7314054e3496baba5aecb
|
|
BLAKE2b-256 checksum How to use checksums |
306aaf3367c895c45cebf8676f744c8fa914783bd010f2668c19a9aac485487a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/4.0.2 CPython/3.11.3
|