All Projects → imbokov → drf_dynamics

imbokov / drf_dynamics

Licence: MIT license
Dynamic queryset and serializer setup for Django REST Framework

Programming Languages

python
139335 projects - #7 most used programming language

Projects that are alternatives of or similar to drf dynamics

django-on-k8s
An end to end tutorial to run a Django Web Application having a PostgreSQL database in Kubernetes
Stars: ✭ 37 (+42.31%)
Mutual labels:  django-rest-framework
Django-Ionic-Integration
Section 3 of the Django + Angular + Ionic Course
Stars: ✭ 21 (-19.23%)
Mutual labels:  django-rest-framework
django-rest-framework-condition
Decorators @​condition, @​last_modified and @​etag for Django Rest Framework
Stars: ✭ 26 (+0%)
Mutual labels:  django-rest-framework
web-ui
python+selenium+pytest+allure UI 自动化框架
Stars: ✭ 199 (+665.38%)
Mutual labels:  django-rest-framework
linkedevents
Linked Events event database and API
Stars: ✭ 20 (-23.08%)
Mutual labels:  django-rest-framework
django-rest-framework-react-tutorial
Source code for Django Rest Framework + React tutorial.
Stars: ✭ 69 (+165.38%)
Mutual labels:  django-rest-framework
Django Practice Book
《Django企业开发实战》已出版
Stars: ✭ 251 (+865.38%)
Mutual labels:  django-rest-framework
chembience
A Docker-based, cloudable platform for the development of chemoinformatics-centric web applications and microservices.
Stars: ✭ 41 (+57.69%)
Mutual labels:  django-rest-framework
cryptopay-web
A payment gateway like Stripe for cryptocurrencies
Stars: ✭ 7 (-73.08%)
Mutual labels:  django-rest-framework
batamlawancorona api
Unofficial API of Batam Lawan Corona. Documentation and sample of use can be found at http://batamlawancoronaapi.herokuapp.com/docs/
Stars: ✭ 22 (-15.38%)
Mutual labels:  django-rest-framework
drf-starter-template
DRF Starter Template with drf-yasg, heroku deployment ready config, CORS config
Stars: ✭ 25 (-3.85%)
Mutual labels:  django-rest-framework
QuestionTime
📚 Quora-like Single Page Application built with Django, Django REST Framework and Vue JS
Stars: ✭ 76 (+192.31%)
Mutual labels:  django-rest-framework
ChRIS ultron backEnd
Backend for ChRIS
Stars: ✭ 28 (+7.69%)
Mutual labels:  django-rest-framework
django-jsonapi-training
Columbia University IT developer training on using Django, REST and {json:api}
Stars: ✭ 25 (-3.85%)
Mutual labels:  django-rest-framework
Dailyfresh-B2C
这是一个 ☛全栈/全端/全平台☚ 的B2C模式的电商项目, web后台基于Django2.0 + Python3.6, 前后端分离,前端使用Vue框架开发。移动端基于Flutter开发,一套代码支持Android&IOS平台。微信小程序基于mpvue框架开发。
Stars: ✭ 74 (+184.62%)
Mutual labels:  django-rest-framework
penn-clubs
Official React-based website for Penn Labs' club directory and events listings.
Stars: ✭ 41 (+57.69%)
Mutual labels:  django-rest-framework
DRF-API-Logger
An API Logger for your Django Rest Framework project.
Stars: ✭ 184 (+607.69%)
Mutual labels:  django-rest-framework
Cetus-GUI
cetus web端管理工具
Stars: ✭ 53 (+103.85%)
Mutual labels:  django-rest-framework
django todo app
python django를 활용한 웹 개발 튜토리얼! todo_app 만들기
Stars: ✭ 82 (+215.38%)
Mutual labels:  django-rest-framework
deploy-django
A bash script to deploy a django project for production sites.
Stars: ✭ 85 (+226.92%)
Mutual labels:  django-rest-framework

drf_dynamics

Motivation

Handles the hassle of handling the amount of fields to be serialized and queryset changes for each request for you.

Example:

GET /api/party/?fields=id,title

response

[
    {
        "id": 1,
        "title": "foo"
    },
    {
        "id": 2,
        "title": "bar"
    }
]

sql

SELECT
   "party_party"."id",
   "party_party"."title",
   "party_party"."host_id" 
FROM
   "party_party"

GET /api/party/?fields=id,title,host.id,host.username

response

[
    {
        "id": 1,
        "title": "foo",
        "host": {
            "id": 1,
            "username": "root"
        }
    },
    {
        "id": 2,
        "title": "bar",
        "host": {
            "id": 1,
            "username": "root"
        }
    }
]

sql

SELECT
   "party_party"."id",
   "party_party"."title",
   "party_party"."host_id",
   "auth_user"."id",
   "auth_user"."username",
   "auth_user"."first_name",
   "auth_user"."last_name",
   "auth_user"."email",
   "auth_user"."is_staff",
   "auth_user"."is_active",
   "auth_user"."date_joined" 
FROM
   "party_party" 
   INNER JOIN
      "auth_user" 
      ON ("party_party"."host_id" = "auth_user"."id")

Requirements

  • Python >= 3.5
  • Django >= 1.11
  • DjangoRestFramework >= 3.7.0

Installation

pip install drf_dynamics

Usage

DynamicQuerySetMixin

Usage example:

class PartyViewSet(DynamicQuerySetMixin, ModelViewSet):
    queryset = Party.objects.all()
    serializer_class = PartySerializer

The only thing it does by default is parse the fields query parameter and pass it to the serializer. It doesn't modify the queryset yet. For that you'll need to use dynamic_queryset decorator (see below). If you want to modify the actions, for which this should work, change the dynamic_fields_actions class attribute on the viewset:

Note: it has to be a set

class PartyViewSet(DynamicQuerySetMixin, ModelViewSet):
    queryset = Party.objects.all()
    serializer_class = PartySerializer
    dynamic_fields_actions = {"list"}

Default is:

{
    "create",
    "list",
    "retrieve",
    "update",
    "partial_update",
}

DynamicFieldsMixin

Usage example:

class PartySerializer(DynamicFieldsMixin, serializers.ModelSerializer):
    class Meta:
        model = Party
        fields = (
            "id",
            "title",
            "host",
        )

Now, if the viewset passes the parsed requested fields to the serializer, the fields will change depending on the request.

representation_fields

You can specify additional fields by using the representation_fields attribute. Those will be read-only, will override default fields, and don't have to be specified in the Meta.fields attribute (useful if there's a chance those fields won't be present on the instance).

You can use serializers in those fields, that also inherit from DynamicFieldsMixin and nest those as much as you want.

Usage example:

class PartySerializer(DynamicFieldsMixin, serializers.ModelSerializer):
    class Meta:
        model = Party
        fields = (
            "id",
            "title",
            "host",
        )

    representation_fields = {
        "host": PersonSerializer(),
        "invites": InviteSerializer(many=True),
        "invites_count": serializers.IntegerField(),
    }

dynamic_queryset(prefetches, annotations, selects)

A viewset decorator that enables the dynamic queryset change depending on the request.

You have to specify all the prefetch_related and select_related lookups, and annotation queryset methods your serializer may require to render its fields using this decorator, which will allow for those modifications to be dynamically applied.

You must specify queryset on your viewset for this decorator to work.

Usage example:

@dynamic_queryset(
    prefetches="invites",
    annotations="invites_count",
    selects=(
        "host",
        "invites.sender",
        "invites.recipient",
    ),
)
class PartyViewSet(DynamicQuerySetMixin, ModelViewSet):
    queryset = Party.objects.all()
    serializer_class = PartySerializer

Each parameter can accept either a single string or a sequence of strings. The strings are then applied to their parent prefetch's queryset if there is one, or to the viewset's queryset otherwise. In case of prefetches and selects the decorator assumes that the field's name corresponds to the queryset's select_related or prefetch_related lookup, where all the dots are converted to __. For annotations, it will search for a method on the queryset that has a format of with_{field_name}. Your queryset methods will receive Request object as the first argument.

If that's not the case for you, you can override lookups and methods names by supplying a mapping either as an argument or the last element of the sequence which will be supplied as an argument:

@dynamic_queryset(
    prefetches=(
        "invites",
        {"invites.answer": "response"},
    ),
    annotations={
        "invites_count": "invites_count",
    },
    selects=(
        "invites.sender",
        "invites.recipient",
        {"host": "user"},
    ),
)
class PartyViewSet(DynamicQuerySetMixin, ModelViewSet):
    queryset = Party.objects.all()
    serializer_class = PartySerializer

Keep in mind, that the specified lookup must be applied from the parent prefetch's queryset context if there is one, hence the {"invites.answer": "response"} line.

DynamicPrefetch

If you need even more control over your prefetches, those can be applied using DynamicPrefetch instance. It accepts the same arguments as Django's Prefetch and works in the same way, but can also accept a callable instead of the queryset argument. The callable will be supplied with a Request object as its first argument.

Usage example:

@dynamic_queryset(
    prefetches=(
        "invites.answer",
        "invites.answer.details",
        {"invites": DynamicPrefetch("invites", Invite.objects.for_user)},
    ),
    ...
)
class PartyViewSet(DynamicQuerySetMixin, ModelViewSet):
    queryset = Party.objects.all()
    serializer_class = PartySerializer

The callable not necessarily has to be a queryset method. Any callable which accepts one argument and returns an appropriate queryset will do.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].