{"id":18098738,"url":"https://github.com/shosca/django-rest-witchcraft","last_synced_at":"2025-04-13T12:52:22.611Z","repository":{"id":21526999,"uuid":"93176001","full_name":"shosca/django-rest-witchcraft","owner":"shosca","description":"Django REST Framework integration with SQLAlchemy","archived":false,"fork":false,"pushed_at":"2022-12-21T12:55:54.000Z","size":333,"stargazers_count":47,"open_issues_count":6,"forks_count":11,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-13T12:52:17.238Z","etag":null,"topics":["django","django-rest-framework","django-sqlalchemy","rest","sqlalchemy"],"latest_commit_sha":null,"homepage":"https://django-rest-witchcraft.readthedocs.io","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shosca.png","metadata":{"files":{"readme":"README.rst","changelog":"HISTORY.rst","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-06-02T14:52:17.000Z","updated_at":"2024-09-16T15:01:26.000Z","dependencies_parsed_at":"2023-01-13T21:32:26.895Z","dependency_job_id":null,"html_url":"https://github.com/shosca/django-rest-witchcraft","commit_stats":null,"previous_names":[],"tags_count":61,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shosca%2Fdjango-rest-witchcraft","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shosca%2Fdjango-rest-witchcraft/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shosca%2Fdjango-rest-witchcraft/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shosca%2Fdjango-rest-witchcraft/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shosca","download_url":"https://codeload.github.com/shosca/django-rest-witchcraft/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248717259,"owners_count":21150388,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["django","django-rest-framework","django-sqlalchemy","rest","sqlalchemy"],"created_at":"2024-10-31T20:12:46.063Z","updated_at":"2025-04-13T12:52:22.590Z","avatar_url":"https://github.com/shosca.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"Django REST Witchcraft\n======================\n\n|Build Status| |Read The Docs| |PyPI version| |Coveralls Status| |Black|\n\n**Django REST Framework integration with SQLAlchemy**\n\ndjango-rest-witchcraft is an extension for Django REST Framework that adds support for SQLAlchemy. It aims to provide\na similar development experience to building REST api's with Django REST Framework with Django ORM, except with\nSQLAlchemy.\n\nInstallation\n============\n\n::\n\n    pip install django-rest-witchcraft\n\nQuick Start\n===========\n\nFirst up, lets define some simple models:\n\n.. code:: python\n\n    import sqlalchemy as sa\n    import sqlalchemy.orm  # noqa\n    from sqlalchemy.ext.declarative import declarative_base\n\n    engine = sa.create_engine('sqlite:///:memory:', echo=True)\n    session = sa.orm.scoped_session(sa.orm.sessionmaker(bind=engine))\n\n    Base = declarative_base()\n    Base.query = session.query_property()\n\n\n    class Group(Base):\n        __tablename__ = 'groups'\n\n        id = sa.Column(sa.Integer(), primary_key=True, autoincrement=True)\n        name = sa.Column(sa.String())\n\n\n    class User(Base):\n        __tablename__ = 'users'\n\n        id = sa.Column(sa.Integer(), primary_key=True, autoincrement=True)\n        name = sa.Column(sa.String())\n        fullname = sa.Column(sa.String())\n        password = sa.Column(sa.String())\n\n        _group_id = sa.Column('group_id', sa.Integer(), sa.ForeignKey('groups.id'))\n        group = sa.orm.relationship(Group, backref='users')\n\n\n    class Address(Base):\n        __tablename__ = 'addresses'\n\n        id = sa.Column(sa.Integer(), primary_key=True, autoincrement=True)\n        email_address = sa.Column(sa.String(), nullable=False)\n\n        _user_id = sa.Column(sa.Integer(), sa.ForeignKey('users.id'))\n        user = sa.orm.relationship(User, backref='addresses')\n\n    Base.metadata.create_all(engine)\n\n\nNothing fancy here, we have a ``User`` class that can belongs to a ``Group`` instance and has many ``Address``\ninstances\n\nThis serializer can handle nested create, update or partial update operations.\n\nLets define a serializer for ``User`` with all the fields:\n\n.. code:: python\n\n    class UserSerializer(serializers.ModelSerializer):\n\n        class Meta:\n            model = User\n            session = session\n            fields = '__all__'\n\nThis will create the following serializer for us:\n\n::\n\n    \u003e\u003e\u003e serializer = UserSerializer()\n\n    \u003e\u003e\u003e serializer\n    UserSerializer():\n        id = IntegerField(allow_null=False, help_text=None, label='Id', required=True)\n        name = CharField(allow_null=True, help_text=None, label='Name', max_length=None, required=False)\n        fullname = CharField(allow_null=True, help_text=None, label='Fullname', max_length=None, required=False)\n        password = CharField(allow_null=True, help_text=None, label='Password', max_length=None, required=False)\n        group = GroupSerializer(allow_null=True, is_nested=True, required=False):\n            id = IntegerField(allow_null=False, help_text=None, label='Id', required=False)\n            name = CharField(allow_null=True, help_text=None, label='Name', max_length=None, required=False)\n        addresses = AddressSerializer(allow_null=True, many=True, required=False):\n            id = IntegerField(allow_null=False, help_text=None, label='Id', required=False)\n            email_address = CharField(allow_null=False, help_text=None, label='Email_address', max_length=None, required=True)\n        url = UriField(read_only=True)\n\nLets try to create a ``User`` instance with our brand new serializer:\n\n.. code:: python\n\n    serializer = UserSerializer(data={\n        'name': 'shosca',\n        'password': 'swordfish',\n    })\n    serializer.is_valid()\n    serializer.save()\n\n    user = serializer.instance\n\nThis will create the following user for us:\n\n::\n\n    \u003e\u003e\u003e user\n    User(_group_id=None, id=1, name='shosca', fullname=None, password='swordfish')\n\nLets try to update our user ``User`` instance and change its password:\n\n.. code:: python\n\n    serializer = UserSerializer(user, data={\n        'name': 'shosca',\n        'password': 'password',\n    })\n    serializer.is_valid()\n    serializer.save()\n\n    user = serializer.instance\n\nOur user now looks like:\n\n::\n\n    \u003e\u003e\u003e user\n    User(_group_id=None, id=1, name='shosca', fullname=None, password='password')\n\nLets try to update our ``User`` instance again, but this time lets change its password only:\n\n.. code:: python\n\n    serializer = UserSerializer(user, data={\n        'password': 'swordfish',\n    }, partial=True)\n    serializer.is_valid()\n    serializer.save()\n\n    user = serializer.instance\n\nThis will update the following user for us:\n\n::\n\n    \u003e\u003e\u003e user\n    User(_group_id=None, id=1, name='shosca', fullname=None, password='swordfish')\n\nOur user does not belong to a ``Group``, lets fix that:\n\n.. code:: python\n\n    group = Group(name='Admin')\n    session.add(group)\n    session.flush()\n\n    serializer = UserSerializer(user, data={\n        'group': {'id': group.id}\n    })\n    serializer.is_valid()\n    serializer.save()\n\n    user = serializer.instance\n\nNow, our user looks like:\n\n::\n\n    \u003e\u003e\u003e user\n    User(_group_id=1, id=1, name='shosca', fullname=None, password='swordfish')\n\n    \u003e\u003e\u003e user.group\n    Group(id=1, name='Admin')\n\nWe can also change the name of our user's group through the user using nested updates:\n\n.. code:: python\n\n    class UserSerializer(serializers.ModelSerializer):\n\n        class Meta:\n            model = User\n            session = session\n            fields = '__all__'\n            extra_kwargs = {\n                'group': {'allow_nested_updates': True}\n            }\n\n    serializer = UserSerializer(user, data={\n        'group': {'name': 'Super User'}\n    }, partial=True)\n    serializer.is_valid()\n\n    user = serializer.save()\n\nNow, our user looks like:\n\n::\n\n    \u003e\u003e\u003e user\n    User(_group_id=1, id=1, name='shosca', fullname=None, password='swordfish')\n\n    \u003e\u003e\u003e user.group\n    Group(id=1, name='Super User')\n\nWe can use this serializer in a viewset like:\n\n.. code:: python\n\n    from rest_witchcraft import viewsets\n\n    class UserViewSet(viewsets.ModelViewSet):\n        queryset = User.query\n        serializer_class = UserSerializer\n\nAnd we can register this viewset in our ``urls.py`` like:\n\n.. code:: python\n\n    from rest_witchcraft import routers\n\n    router = routers.DefaultRouter()\n    router.register(r'users', UserViewSet)\n\n    urlpatterns = [\n        ...\n        url(r'^', include(router.urls)),\n        ...\n    ]\n\n\n.. |Build Status| image:: https://github.com/shosca/django-rest-witchcraft/workflows/Build/badge.svg?branch=master\n   :target: https://github.com/shosca/django-rest-witchcraft/actions?query=workflow%3ABuild+branch%3Amaster\n.. |Read The Docs| image:: https://readthedocs.org/projects/django-rest-witchcraft/badge/?version=latest\n   :target: http://django-rest-witchcraft.readthedocs.io/en/latest/?badge=latest\n.. |PyPI version| image:: https://badge.fury.io/py/django-rest-witchcraft.svg\n   :target: https://badge.fury.io/py/django-rest-witchcraft\n.. |Coveralls Status| image:: https://coveralls.io/repos/github/shosca/django-rest-witchcraft/badge.svg?branch=master\n   :target: https://coveralls.io/github/shosca/django-rest-witchcraft?branch=master\n.. |Black| image:: https://img.shields.io/badge/code%20style-black-000000.svg\n   :target: https://github.com/ambv/black\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshosca%2Fdjango-rest-witchcraft","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshosca%2Fdjango-rest-witchcraft","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshosca%2Fdjango-rest-witchcraft/lists"}