plain.models
Model your data and store it in a database.
# app/users/models.py
from plain import models
from plain.passwords.models import PasswordField
class User(models.Model):
email = models.EmailField(unique=True)
password = PasswordField()
is_staff = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.email
Create, update, and delete instances of your models:
from .models import User
# Create a new user
user = User.objects.create(
email="[email protected]",
password="password",
)
# Update a user
user.email = "[email protected]"
user.save()
# Delete a user
user.delete()
# Query for users
staff_users = User.objects.filter(is_staff=True)
Installation
# app/settings.py
INSTALLED_PACKAGES = [
...
"plain.models",
]
To connect to a database, you can provide a DATABASE_URL
environment variable.
DATABASE_URL=postgresql://user:password@localhost:5432/dbname
Or you can manually define the DATABASES
setting.
# app/settings.py
DATABASES = {
"default": {
"ENGINE": "plain.models.backends.postgresql",
"NAME": "dbname",
"USER": "user",
"PASSWORD": "password",
"HOST": "localhost",
"PORT": "5432",
}
}
Multiple backends are supported, including Postgres, MySQL, and SQLite.
Querying
Migrations
Fields
Validation
Indexes and constraints
Managers
Forms
1from functools import partial
2
3from plain.models.utils import make_model_tuple
4from plain.signals.dispatch import Signal
5
6class_prepared = Signal()
7
8
9class ModelSignal(Signal):
10 """
11 Signal subclass that allows the sender to be lazily specified as a string
12 of the `package_label.ModelName` form.
13 """
14
15 def _lazy_method(self, method, packages, receiver, sender, **kwargs):
16 from plain.models.options import Options
17
18 # This partial takes a single optional argument named "sender".
19 partial_method = partial(method, receiver, **kwargs)
20 if isinstance(sender, str):
21 packages = packages or Options.default_packages
22 packages.lazy_model_operation(partial_method, make_model_tuple(sender))
23 else:
24 return partial_method(sender)
25
26 def connect(
27 self, receiver, sender=None, weak=True, dispatch_uid=None, packages=None
28 ):
29 self._lazy_method(
30 super().connect,
31 packages,
32 receiver,
33 sender,
34 weak=weak,
35 dispatch_uid=dispatch_uid,
36 )
37
38 def disconnect(self, receiver=None, sender=None, dispatch_uid=None, packages=None):
39 return self._lazy_method(
40 super().disconnect, packages, receiver, sender, dispatch_uid=dispatch_uid
41 )
42
43
44pre_init = ModelSignal(use_caching=True)
45post_init = ModelSignal(use_caching=True)
46
47pre_save = ModelSignal(use_caching=True)
48post_save = ModelSignal(use_caching=True)
49
50pre_delete = ModelSignal(use_caching=True)
51post_delete = ModelSignal(use_caching=True)
52
53m2m_changed = ModelSignal(use_caching=True)