ohmyapi 0.1.0__py3-none-any.whl → 0.1.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,23 +1,30 @@
1
1
  from typing import Optional, List
2
2
  from ohmyapi.db import Model, field
3
3
  from passlib.context import CryptContext
4
+ from tortoise.contrib.pydantic import pydantic_queryset_creator
4
5
 
5
6
  pwd_context = CryptContext(schemes=["argon2"], deprecated="auto")
6
7
 
7
8
 
8
9
  class Group(Model):
9
10
  id = field.IntField(pk=True)
10
- name = field.CharField(max_length=42)
11
+ name = field.CharField(max_length=42, index=True)
11
12
 
12
13
 
13
14
  class User(Model):
14
15
  id = field.IntField(pk=True)
16
+ email = CharField(unique=True, index=True)
15
17
  username = field.CharField(max_length=150, unique=True)
16
18
  password_hash = field.CharField(max_length=128)
17
19
  is_admin = field.BooleanField(default=False)
18
20
  is_staff = field.BooleanField(default=False)
19
21
  groups: Optional[List[Group]] = field.ManyToManyField("ohmyapi_auth.Group", related_name="users")
20
22
 
23
+
24
+ class Schema:
25
+ exclude = 'password_hash',
26
+
27
+
21
28
  def set_password(self, raw_password: str) -> None:
22
29
  """Hash and store the password."""
23
30
  self.password_hash = pwd_context.hash(raw_password)
ohmyapi/db/model/model.py CHANGED
@@ -3,78 +3,44 @@ from tortoise.models import Model as TortoiseModel
3
3
  from tortoise.contrib.pydantic import pydantic_model_creator, pydantic_queryset_creator
4
4
 
5
5
 
6
- class Model(TortoiseModel):
7
- """
8
- Base Tortoise model with attached Pydantic schema generators via .Schema
9
- """
10
-
6
+ class ModelMeta(type(TortoiseModel)):
7
+ def __new__(cls, name, bases, attrs):
8
+ new_cls = super().__new__(cls, name, bases, attrs)
9
+
10
+ schema_opts = getattr(new_cls, "Schema", None)
11
+
12
+ class BoundSchema:
13
+ @property
14
+ def one(self):
15
+ """Return a Pydantic model class for 'one' results."""
16
+ include = getattr(schema_opts, "include", None)
17
+ exclude = getattr(schema_opts, "exclude", None)
18
+ return pydantic_model_creator(
19
+ new_cls,
20
+ name=f"{new_cls.__name__}SchemaOne",
21
+ include=include,
22
+ exclude=exclude,
23
+ exclude_readonly=True,
24
+ )
25
+
26
+ @property
27
+ def many(self):
28
+ """Return a Pydantic queryset class for 'many' results."""
29
+ include = getattr(schema_opts, "include", None)
30
+ exclude = getattr(schema_opts, "exclude", None)
31
+ return pydantic_queryset_creator(
32
+ new_cls,
33
+ name=f"{new_cls.__name__}SchemaMany",
34
+ include=include,
35
+ exclude=exclude,
36
+ )
37
+
38
+ new_cls.Schema = BoundSchema()
39
+ return new_cls
40
+
41
+
42
+ class Model(TortoiseModel, metaclass=ModelMeta):
11
43
  class Schema:
12
- """
13
- Provides convenient access to auto-generated Pydantic schemas.
14
- """
15
-
16
- def __init__(self, model_cls):
17
- self.model_cls = model_cls
18
-
19
- @property
20
- def id(self):
21
- # Minimal schema with just the primary key field
22
- pk_field = self.model_cls._meta.pk_attr
23
- return pydantic_model_creator(
24
- self.model_cls, name=f"{self.model_cls.__name__}SchemaId", include=(pk_field,)
25
- )
26
-
27
- @property
28
- def get(self):
29
- # Full schema for reading
30
- return pydantic_model_creator(
31
- self.model_cls, name=f"{self.model_cls.__name__}SchemaGet"
32
- )
33
-
34
- @property
35
- def post(self):
36
- # Input schema for creation (no readonly fields like ID/PK)
37
- return pydantic_model_creator(
38
- self.model_cls,
39
- name=f"{self.model_cls.__name__}SchemaPost",
40
- exclude_readonly=True,
41
- )
42
-
43
- @property
44
- def put(self):
45
- # Input schema for updating
46
- return pydantic_model_creator(
47
- self.model_cls,
48
- name=f"{self.model_cls.__name__}SchemaPut",
49
- exclude_readonly=True,
50
- )
51
-
52
- @property
53
- def delete(self):
54
- # Schema for delete operations (just PK)
55
- pk_field = self.model_cls._meta.pk_attr
56
- return pydantic_model_creator(
57
- self.model_cls, name=f"{self.model_cls.__name__}SchemaDelete", include=(pk_field,)
58
- )
59
-
60
- @property
61
- def list(self):
62
- # Schema for list endpoints
63
- return pydantic_queryset_creator(self.model_cls)
64
-
65
- def from_fields(self, *fields: str):
66
- # Generate schema restricted to given fields
67
- valid = [f for f in fields if f in self.model_cls._meta.fields_map]
68
- return pydantic_model_creator(
69
- self.model_cls,
70
- name=f"{self.model_cls.__name__}SchemaFields",
71
- include=valid,
72
- )
73
-
74
- def __init_subclass__(cls, **kwargs):
75
- """
76
- Automatically attach .Schema to all subclasses
77
- """
78
- super().__init_subclass__(**kwargs)
79
- cls.Schema = cls.Schema(cls)
44
+ include = None
45
+ exclude = None
80
46
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ohmyapi
3
- Version: 0.1.0
3
+ Version: 0.1.1
4
4
  Summary: A Django-like but async web-framework based on FastAPI and TortoiseORM.
5
5
  License-Expression: MIT
6
6
  Keywords: fastapi,tortoise,orm,async,web-framework
@@ -142,7 +142,21 @@ Similar to Django, first run:
142
142
  ohmyapi makemigrations [ <app> ] # no app means all INSTALLED_APPS
143
143
  ```
144
144
 
145
- And the apply your migrations via:
145
+ This will create a `migrations/` folder in you project root.
146
+
147
+ ```
148
+ myproject/
149
+ - myapp/
150
+ - __init__.py
151
+ - models.py
152
+ - routes.py
153
+ - migrations/
154
+ - myapp/
155
+ - pyproject.toml
156
+ - settings.py
157
+ ```
158
+
159
+ Apply your migrations via:
146
160
 
147
161
  ```
148
162
  ohmyapi migrate [ <app> ] # no app means all INSTALLED_APPS
@@ -165,6 +179,7 @@ ohmyapi shell
165
179
  ## Authentication
166
180
 
167
181
  A builtin auth app is available.
182
+
168
183
  Simply add `ohmyapi_auth` to your INSTALLED_APPS and define a JWT_SECRET in your `settings.py`.
169
184
  Remember to `makemigrations` and `migrate` for the auth tables to be created in the database.
170
185
 
@@ -1,6 +1,6 @@
1
1
  ohmyapi/__init__.py,sha256=UmLNQImTbKvHEgwQB2Wsyl6fq88X92imL9QZYJpQX4I,18
2
2
  ohmyapi/builtin/auth/__init__.py,sha256=TY1RKgwWmJ6FKz_v4J3m0Ang69qSmtVDLe4rqjLk4-E,69
3
- ohmyapi/builtin/auth/models.py,sha256=9GNaMc0Qp25HaVVZouTt_DmYazNj3tO_FM0Jbhc6kuM,1311
3
+ ohmyapi/builtin/auth/models.py,sha256=PWDUFDzfu6Sl6G6ZujVN7KGBzk6RNUk-moS-g-vEPOM,1490
4
4
  ohmyapi/builtin/auth/permissions.py,sha256=gPBf01UNgXjU3v3DwMSYpKjayZSnwksp-ji4C99oX_I,111
5
5
  ohmyapi/builtin/auth/routes.py,sha256=5jLq92z4TJw4eyiIJ5t7MwRNtYlpN7suDwW28JeEQYA,4902
6
6
  ohmyapi/cli.py,sha256=DaSf1uYxv1bD1XBwVN_rn4F7hq9AlvXwtWzbVw7WPBw,3472
@@ -15,9 +15,9 @@ ohmyapi/core/templates/project/settings.py.j2,sha256=c8hHo5DHxNLtam_8Sk8bLYxrjhg
15
15
  ohmyapi/db/__init__.py,sha256=p5oXqYUKT6eAoE-9JD-p6zKo9s-H84rJbrKxFna8Kvc,63
16
16
  ohmyapi/db/migration_manager.py,sha256=dTabeDyd6ZIa0lORlKRuiLnBTcsVAgUjgrO9_bew6pQ,3621
17
17
  ohmyapi/db/model/__init__.py,sha256=owKYpx5a2ZFTBgBqyEKN09AvY1cSP0dy1O7d3_sUVgM,33
18
- ohmyapi/db/model/model.py,sha256=fcLtTh-tD-jkoEYI18HX8PQRk2P7sLM2LWgEkKHa1Nw,2595
18
+ ohmyapi/db/model/model.py,sha256=PSzK_d8IZQExSRuTrEyPnqfa4GENQhbBZsVxxLWTR4g,1570
19
19
  ohmyapi/router.py,sha256=RzDXrtJJrk4eWdt9qoKBfz6g0S5WZq2hDQoFy5whR6A,40
20
- ohmyapi-0.1.0.dist-info/METADATA,sha256=eepZKZNCVi-WgcB79fnk2mHA7IQbADYLmMJOviQISjg,3969
21
- ohmyapi-0.1.0.dist-info/WHEEL,sha256=M5asmiAlL6HEcOq52Yi5mmk9KmTVjY2RDPtO4p9DMrc,88
22
- ohmyapi-0.1.0.dist-info/entry_points.txt,sha256=ZCZJLw_ojguyr1WOmb8UwHrr42hiLj6-Kzh4mMa_7Ns,44
23
- ohmyapi-0.1.0.dist-info/RECORD,,
20
+ ohmyapi-0.1.1.dist-info/METADATA,sha256=4U7499jLyiwuU0PfDvqJq9y1jH-LHpw3aZQ0VFydQDA,4169
21
+ ohmyapi-0.1.1.dist-info/WHEEL,sha256=M5asmiAlL6HEcOq52Yi5mmk9KmTVjY2RDPtO4p9DMrc,88
22
+ ohmyapi-0.1.1.dist-info/entry_points.txt,sha256=ZCZJLw_ojguyr1WOmb8UwHrr42hiLj6-Kzh4mMa_7Ns,44
23
+ ohmyapi-0.1.1.dist-info/RECORD,,