Django REST Witchcraft
Django REST Framework integration with SQLAlchemy
django-rest-witchcraft is an extension for Django REST Framework that adds support for SQLAlchemy. It aims to provide a similar development experience to building REST api’s with Django REST Framework with Django ORM, except with SQLAlchemy.
Installation
pip install django-rest-witchcraft
Quick Start
First up, lets define some simple models:
import sqlalchemy as sa
import sqlalchemy.orm # noqa
from sqlalchemy.ext.declarative import declarative_base
engine = sa.create_engine('sqlite:///:memory:', echo=True)
session = sa.orm.scoped_session(sa.orm.sessionmaker(bind=engine))
Base = declarative_base()
Base.query = session.query_property()
class Group(Base):
__tablename__ = 'groups'
id = sa.Column(sa.Integer(), primary_key=True, autoincrement=True)
name = sa.Column(sa.String())
class User(Base):
__tablename__ = 'users'
id = sa.Column(sa.Integer(), primary_key=True, autoincrement=True)
name = sa.Column(sa.String())
fullname = sa.Column(sa.String())
password = sa.Column(sa.String())
_group_id = sa.Column('group_id', sa.Integer(), sa.ForeignKey('groups.id'))
group = sa.orm.relationship(Group, backref='users')
class Address(Base):
__tablename__ = 'addresses'
id = sa.Column(sa.Integer(), primary_key=True, autoincrement=True)
email_address = sa.Column(sa.String(), nullable=False)
_user_id = sa.Column(sa.Integer(), sa.ForeignKey('users.id'))
user = sa.orm.relationship(User, backref='addresses')
Base.metadata.create_all(engine)
Nothing fancy here, we have a User class that can belongs to a Group instance and has many Address instances
This serializer can handle nested create, update or partial update operations.
Lets define a serializer for User with all the fields:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
session = session
fields = '__all__'
This will create the following serializer for us:
>>> serializer = UserSerializer()
>>> serializer
UserSerializer():
id = IntegerField(allow_null=False, help_text=None, label='Id', required=True)
name = CharField(allow_null=True, help_text=None, label='Name', max_length=None, required=False)
fullname = CharField(allow_null=True, help_text=None, label='Fullname', max_length=None, required=False)
password = CharField(allow_null=True, help_text=None, label='Password', max_length=None, required=False)
group = GroupSerializer(allow_null=True, is_nested=True, required=False):
id = IntegerField(allow_null=False, help_text=None, label='Id', required=False)
name = CharField(allow_null=True, help_text=None, label='Name', max_length=None, required=False)
addresses = AddressSerializer(allow_null=True, many=True, required=False):
id = IntegerField(allow_null=False, help_text=None, label='Id', required=False)
email_address = CharField(allow_null=False, help_text=None, label='Email_address', max_length=None, required=True)
url = UriField(read_only=True)
Lets try to create a User instance with our brand new serializer:
serializer = UserSerializer(data={
'name': 'shosca',
'password': 'swordfish',
})
serializer.is_valid()
serializer.save()
user = serializer.instance
This will create the following user for us:
>>> user User(_group_id=None, id=1, name='shosca', fullname=None, password='swordfish')
Lets try to update our user User instance and change its password:
serializer = UserSerializer(user, data={
'name': 'shosca',
'password': 'password',
})
serializer.is_valid()
serializer.save()
user = serializer.instance
Our user now looks like:
>>> user User(_group_id=None, id=1, name='shosca', fullname=None, password='password')
Lets try to update our User instance again, but this time lets change its password only:
serializer = UserSerializer(user, data={
'password': 'swordfish',
}, partial=True)
serializer.is_valid()
serializer.save()
user = serializer.instance
This will update the following user for us:
>>> user User(_group_id=None, id=1, name='shosca', fullname=None, password='swordfish')
Our user does not belong to a Group, lets fix that:
group = Group(name='Admin')
session.add(group)
session.flush()
serializer = UserSerializer(user, data={
'group': {'id': group.id}
})
serializer.is_valid()
serializer.save()
user = serializer.instance
Now, our user looks like:
>>> user User(_group_id=1, id=1, name='shosca', fullname=None, password='swordfish') >>> user.group Group(id=1, name='Admin')
We can also change the name of our user’s group through the user using nested updates:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
session = session
fields = '__all__'
extra_kwargs = {
'group': {'allow_nested_updates': True}
}
serializer = UserSerializer(user, data={
'group': {'name': 'Super User'}
}, partial=True)
serializer.is_valid()
user = serializer.save()
Now, our user looks like:
>>> user User(_group_id=1, id=1, name='shosca', fullname=None, password='swordfish') >>> user.group Group(id=1, name='Super User')
We can use this serializer in a viewset like:
from rest_witchcraft import viewsets
class UserViewSet(viewsets.ModelViewSet):
queryset = User.query
serializer_class = UserSerializer
And we can register this viewset in our urls.py like:
from rest_witchcraft import routers
router = routers.DefaultRouter()
router.register(r'users', UserViewSet)
urlpatterns = [
...
url(r'^', include(router.urls)),
...
]
Metadata
Release files for django-rest-witchcraft 0.12.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| django-rest-witchcraft-0.12.1.tar.gz | 42.0 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| django_rest_witchcraft-0.12.1-py2.py3-none-any.whl | Python 3, Python 2 | none | any | Details |
Total release size: 64.2 kB
Release files / django-rest-witchcraft-0.12.1.tar.gz
| Download URL | django-rest-witchcraft-0.12.1.tar.gz |
|---|---|
| Size | 42.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d6652865f45dfae008d2e93f66d853bccf94eb01511416576ec7e4d972fcb19d
|
|
BLAKE2b-256 checksum How to use checksums |
8b9132173bf57c60b41ad223a1dffd722e51e4001aa73c9cacad9d3bac925aad
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/4.0.2 CPython/3.10.10
|
Release files / django_rest_witchcraft-0.12.1-py2.py3-none-any.whl
| Download URL | django_rest_witchcraft-0.12.1-py2.py3-none-any.whl |
|---|---|
| Size | 22.2 kB |
| Tags | Python 2 Python 3 |
|
SHA-256 checksum How to use checksums |
25c14b99d7d83faf378355bc007ed48ec3dfc40132160e8558fd5761aad465a0
|
|
BLAKE2b-256 checksum How to use checksums |
67ca9fc4c5aedb3445f15885013955272fcbd7b82f03e9e9747b3e7cb3c112eb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/4.0.2 CPython/3.10.10
|
Security for django-rest-witchcraft 0.12.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.