Reputation: 11420
Follwing is my model
class Group(Log_Active_Owned_Model_Mixin):
group_name = SafeCharField(max_length = 100, null=False, blank=False, sanitize_cb=safe_name_sanitizer)
group_creator = ForeignKey(to=PSS_User, null=False, related_name="group_creator")
members = ManyToManyField(to=PSS_User, through="GroupMemberShip", related_name="group_member")
class Meta:
ordering = ("Meta", )
## other methods also exists in this class.
class GroupMemberShip(Log_Active_Owned_Model_Mixin, ResolvableModelMixin):
MEMBER_NONE = 1
MEMBER_ADMIN = 2
MEMBER_STANDARD = 4
VALID_MEMBERSHIPS = (
(MEMBER_ADMIN, "Admin" ),
(MEMBER_STANDARD, "Standard" ),
(MEMBER_NONE, "None" )
)
member = ForeignKey(to=PSS_User, null=False, related_name="groups")
group = ForeignKey(to=Group, null=False, related_name="members")
membership_type = SmallIntegerField(editable=False, null=False, blank=False, choices=VALID_MEMBERSHIPS)
membership_request = ForeignKey(to=GroupMemberShipRequest, null=True, blank=True) # null True for group creator
class Meta:
ordering = ("date_created")
unique_together = ("member", "group")
## other methods also exists in this class.
class GroupMemberShipRequest(Log_Active_Owned_Model_Mixin):
GRP_MEMBERSHIP_REQ_STATUS_ACCEPTED = 1
GRP_MEMBERSHIP_REQ_STATUS_REJECTED = 2
GRP_MEMBERSHIP_REQ_STATUS_PENDING = 4
VALID_REQUEST_STATUSES = (
(GRP_MEMBERSHIP_REQ_STATUS_ACCEPTED, "Accepted"),
(GRP_MEMBERSHIP_REQ_STATUS_REJECTED, "Rejected"),
(GRP_MEMBERSHIP_REQ_STATUS_PENDING, "Pending")
)
# TODO :-
# Add a field in request-type. There are two types of requests :-
# User can request admin to include him in the request.
# Admin can request other user, to become part of given group.
GRP_REQUEST_ACTIVE = 1
GRP_REQUEST_PASSIVE = 2
VALID_GRP_REQUESTS = (
(GRP_REQUEST_ACTIVE, "Active"),
(GRP_REQUEST_PASSIVE, "Passive")
)
request_initiator = ForeignKey(to=PSS_User, null=False, blank=False)
request_acceptor_rejector = ForeignKey(to=PSS_User, null=True, blank=False)
request_status = SmallIntegerField(null=False, editable=False, choices=VALID_REQUEST_STATUSES, default=GRP_MEMBERSHIP_REQ_STATUS_PENDING)
target_group = ForeignKey(to=Group, null=False, blank=False, related_name="members")
request_type = SmallIntegerField(null=False, editable=False, default=GRP_REQUEST_ACTIVE, choices=VALID_GRP_REQUESTS)
Now following are the different types of operations, that can be possible with this Group model :-
For create/delete operations, things are clear, but I am confused about update operation, as there are multiple things that can be updated. At present, I have added helper methods in Group class, which does all of above mentioned activities.
My question is, How can I integrate it with DRF(Django Rest Framework) ModelViewSets. Since there is only one update() method, which can serve only one of above mentioned update scenarios. How can I handle other updates scenarios ?(One probable solution, I think is using an operation type flag in request and checking it in update() method to decide, which model method to invoke, But it's bit naive solution. Is there any better way to do this in Django Rest Framework?)
Thanks in advance.
Upvotes: 1
Views: 540
Reputation: 8897
Consider this article Best Practices for Designing a Pragmatic RESTful API
Treat it like a sub-resource with RESTful principles. For example, GitHub's API lets you star a gist with PUT /gists/:id/star and unstar with DELETE /gists/:id/star.
In you case there is 4 different actions with a group. I see two ways for solving it in DRF. By following the tip above, you could use @detail_route decorator:
from rest_framework.decorators import detail_route
class GroupViewSet(viewsets.ModelViewset):
@detail_route(methods=['put', 'delete'])
def send_invite(self, request, pk=None):
# check for the method provided
# do your logic and return a Response object
pass
It will add additional endpoint to viewsets router which follow after detail page
/api/groups/:id/send_invite/
It will works fine with simple tasks. But when you need a complicated nested logic you may find useful this package drf-nested-routers. It allows you to build viesets upon each other.
/api/groups/:id/admin/:id/
But sometimes it is overkill and it violates best practice for designing API
Upvotes: 1