Skip to main content

Logo

ramifice

ORM-pseudo-like API MongoDB for Python language.

Build Status Docs PyPI pyversions PyPI status PyPI version fury.io
Types: Pyrefly Code style: Ruff Format PyPI Downloads GitHub license

Ramifice is built around PyMongo.
For simulate relationship Many-to-One and Many-to-Many,
a simplified alternative (Types of selective fields with dynamic addition of elements) is used.
The project is more concentrated for web development or for applications with a graphic interface.


MongoDB
Supports MongoDB 3.6, 4.0, 4.2, 4.4, 5.0, 6.0, 7.0, and 8.0.
For more information see PyMongo.


Documentation

Requirements

Installation

  1. Install MongoDB (if not installed):
    Fedora Ubuntu Windows

  2. Install system dependencies:

# Fedora:
sudo dnf install gettext
# Ubuntu:
sudo apt install gettext
# MacOS
brew install gettext
brew link gettext --force
# Windows:
https://mlocati.github.io/articles/gettext-iconv-windows.html
  1. Install Ramifice in your project:
uv add ramifice
  1. Add config and public directories in root of your project:
    Download config directory
    Download public directory

  2. Run

# Run Development:
uv run python main.py
# Run Production:
uv run python -OOP main.py

Usage

Examples

import re
import asyncio
from pprint import pprint as pp

from pymongo import AsyncMongoClient

from ramifice import (
    Migration,
    Model,
    NamedTuple,
    Translator,
    fields,
    meta,
    to_human_size,
)

_ = Translator.STUB_TRANSLATOR_FOR_ATTRIBUTES_OF_FIELD


@meta(service_name="Accounts")
class User(Model):
    """User Model."""

    avatar = fields.ImageField(
        label=_("Avatar"),
        default="public/media/default/no-photo.png",
        # Directory for images inside media directory.
        target_dir="users/avatars",
        # Available 4 sizes from lg to xs or None.
        # Hint: Default = None
        thumbnails={"lg": 512, "md": 256, "sm": 128, "xs": 64},
        # The maximum size of the original image in bytes.
        # Hint: Default = 2 MB
        max_size=524288,  # 0.5 MB = 512 KB = 524288 Bytes (in binary)
        warning=[
            _("Maximum size: {}").format(to_human_size(524288)),
        ],
    )
    username = fields.TextField(
        label=_("Username"),
        max_length=150,
        is_require=True,
        is_unique=True,
        warning=[
            _("Allowed characters: {}").format("a-z A-Z 0-9 _"),
            _("Maximum length: {}").format(150),
        ],
    )
    password = fields.PasswordField(
        label=_("Password"),
        warning=[
            _("Maximum length: {}").format(256),  # this is an immutable size
            _("Minimum length: {}").format(8),  # this is an immutable size
        ],
    )
    сonfirm_password = fields.PasswordField(
        label=_("Confirm password"),
        # If true, the value of this field is not saved in the database.
        is_ignore=True,
    )

    # Optional method
    async def add_validation(self) -> NamedTuple:
        """Additional validation of fields."""
        _ = self._CUSTOM_TRANSLATOR.gettext
        err_map = self.get_error_map()

        _id = self.id
        password = self.password
        сonfirm_password = self.сonfirm_password
        username = self.username

        # Check password
        if _id is None and password != сonfirm_password:
            err_map.update("password", _("Passwords do not match!"))

        # Check username
        if username is not None and re.match(r"^[a-zA-Z0-9_]+$", username) is None:
            err_map.update("username", _("Allowed characters: {}").format("a-z A-Z 0-9 _"))

        return err_map


async def main():
    client = AsyncMongoClient()

    await Migration(
        database_name="test_db",
        mongo_client=client,
    ).migrate()

    # Create User
    user = User("ru")
    # user.avatar__core.from_path("public/media/default/no-photo.png")
    # user.avatar__core.from_base64("base64-string")
    user.username = "pythondev"
    user.password = "12345678"
    user.сonfirm_password = "12345678"

    # Save User
    if not await user.save():
        # Convenient to use during development
        user.print_err()

    # Update User
    user.username = "pythondev_123"
    if not await user.save():
        user.print_err()

    print("User details:")
    user_details: dict | None = await User.find_one_to_model_dict(filter={"_id": user.id})
    if user_details is not None:
        pp(user_details)
    else:
        print("No User!")

    # Close connection
    await client.close()


if __name__ == "__main__":
    asyncio.run(main())

Model Parameters

( only service_name is a required parameter )

Parameter Default Description
service_name no Examples: Accounts | Smartphones | Washing machines | etc ...
fixture_name None The name of the fixture in the config/fixtures directory (without extension).
Examples: SiteSettings | AppSettings | etc ...
db_query_docs_limit 100 Limiting the number of request results.
is_create_doc True Can a Model create new documents in a collection?
Set to False if you only need one document in the collection and the Model is using a fixture.
is_update_doc True Can a Model update documents in a collection?
is_delete_doc True Can a Model remove documents from a collection?

Example:

from ramifice import (
    Model,
    fields,
    meta,
)

@meta(
    service_name="ServiceName",
    fixture_name="FixtureName",
    db_query_docs_limit=100,
    is_create_doc = True,
    is_update_doc = True,
    is_delete_doc = True,
)
class User(Model):
  username = fields.TextField(
      label="Username",
      is_require=True,
      is_unique=True,
  )

Changelog

MIT

APACHE-2.0

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ramifice-2.0.2-py3-none-any.whl (130.8 kB view details)

Uploaded Python 3

File details

Details for the file ramifice-2.0.2-py3-none-any.whl.

File metadata

  • Download URL: ramifice-2.0.2-py3-none-any.whl
  • Upload date:
  • Size: 130.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Fedora Linux","version":"44","id":"","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for ramifice-2.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 e2563ce56c5a529ed4063eb3fefb21cf7c7dfc81dfe0372f30ae4bd306b3c7e6
MD5 6883e715e5f1726de02823d0dcf783f6
BLAKE2b-256 7ca8d3eaa83174b8e4465d7010a46645542b531a25c226e8209bad5c9b4fc048

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

2.0.2 This release

1 file

2.0.1

1 file

2.0.0

1 file

1.0.1

1 file

1.0.0

1 file

0.10.0

1 file

0.9.19

1 file

0.9.18

1 file

0.9.17

1 file

0.9.16

1 file

0.9.15

1 file

0.9.14

1 file

0.9.13

1 file

0.9.12

1 file

0.9.11

1 file

0.9.10

1 file

0.9.9

1 file

0.9.8

1 file

0.9.7

1 file

0.9.6

1 file

0.9.5

1 file

0.9.3

1 file

0.9.2

1 file

0.9.1

1 file

0.9.0

1 file

0.8.48

1 file

0.8.47

1 file

0.8.46

1 file

0.8.45

1 file

0.8.44

1 file

0.8.43

1 file

0.8.42

1 file

0.8.41

1 file

0.8.40

1 file

0.8.39

1 file

0.8.38

1 file

0.8.37

1 file

0.8.35

1 file

0.8.34

1 file

0.8.33

1 file

0.8.32

1 file

0.8.31

1 file

0.8.30

1 file

0.8.29

1 file

0.8.28

1 file

0.8.27

1 file

0.8.26

1 file

0.8.25

1 file

0.8.22

1 file

0.8.21

1 file

0.8.20

1 file

0.8.19

1 file

0.8.18

1 file

0.8.17

1 file

0.8.16

1 file

0.8.15

1 file

0.8.14

1 file

0.8.13

1 file

0.8.12

1 file

0.8.11

1 file

0.8.10

1 file

0.8.9

1 file

0.8.8

1 file

0.8.7

1 file

0.8.6

1 file

0.8.5

1 file

0.8.4

1 file

0.8.3

1 file

0.8.2

1 file

0.8.1

1 file

0.8.0

1 file

0.7.0

1 file

0.6.1

1 file

0.6.0

1 file

0.5.12

1 file

0.5.11

1 file

0.5.10

1 file

0.5.9

1 file

0.5.8

1 file

0.5.7

1 file

0.5.6

1 file

0.5.5

1 file

0.5.4

1 file

0.5.3

1 file

0.5.2

1 file

0.5.1

1 file

0.5.0

1 file

0.4.12

1 file

0.4.11

1 file

0.4.10

1 file

0.4.9

1 file

0.4.8

1 file

0.4.7

1 file

0.4.6

1 file

0.4.5

1 file

0.4.4

1 file

0.4.3

1 file

0.4.2

1 file

0.4.1

1 file

0.4.0

1 file

0.3.34

1 file

0.3.32

1 file

0.3.30

1 file

0.3.29

1 file

0.3.28

1 file

0.3.27

1 file

0.3.26

1 file

0.3.25

1 file

0.3.24

1 file

0.3.23

1 file

0.3.22

1 file

0.3.21

1 file

0.3.20

1 file

0.3.19

1 file

0.3.18

1 file

0.3.17

1 file

0.3.16

1 file

0.3.15

1 file

0.3.14

1 file

0.3.13

1 file

0.3.12

1 file

0.3.11

1 file

0.3.10

1 file

0.3.9

1 file

0.3.8

1 file

0.3.7

2 files

0.3.6

2 files

0.3.5

2 files

0.3.4

2 files

0.3.3

2 files

0.3.2

2 files

0.3.1

2 files

0.3.0

2 files

0.2.19

2 files

0.2.18

2 files

0.2.17

2 files

0.2.16

2 files

0.2.15

2 files

0.2.14

2 files

0.2.13

2 files

0.2.12

2 files

0.2.11

2 files

0.2.10

2 files

0.2.9

2 files

0.2.8

2 files

0.2.7

2 files

0.2.6

2 files

0.2.5

2 files

0.2.4

2 files

0.2.3

2 files

0.2.2

2 files

0.2.1

2 files

0.2.0

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page