Why would you use Django without hitting the database with the ORM? Most of the times the ORM works as you'd expect, and even allow you to perform searches like this:
class Foo(models.Model):
code = models.CharField(max_length=10, ...)
class Bar(models.Model):
code = models.CharField(max_length=10, ...)
foo = models.ForeignKey(Foo, ...)
And perform a query like this:
Bar.objects.get(code='baz', foo_code='bat')
Which would be the same, but better, than:
select bar.* from yourapp_bar bar inner join yourapp_foo foo on (bar.foo_id = foo.id) where bar.code = 'baz' and foo.code = 'bat'
Shorter and more maintainable.
Now, speaking about Django Rest Framework and Django in general: Although the latter modifications to both Django and DRF involve you cannot suddenly expect nested objects be created in the same moment the parent objects are (e.g. Foo is parent, while Bar is nested), as it happens in relation managers (Django) and create/update methods in the ModelSerializer class, you can still trust Django to save your time, effort, and life by using it instead of SQL.
I will give you an example with DRF. We will assume only Foo models are involved here. Which one would you prefer?
# yourapp.urls
from .views import UserViewSet
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'users', UserViewSet)
urlpatterns = router.urls
# yourapp.views
class FooViewSet(viewsets.ModelViewSet):
"""
A viewset that provides the standard actions for
a single foo element
"""
queryset = Foo.objects.all()
serializer_class = FooSerializer
# I am assuming you created the FooSerializer to map certain fields...
or ...
# yourapp.urls
from .views import mywholeurl
from django.conf.urls import url
urlpatterns = [
url('users/(\d+)', mywholeview),
]
# yourapp.views
from django.db import connection
from rest_framework import status
from rest_framework.response import Response
def mywholeview(request, id):
cursor = connection.cursor()
if request.method in ('POST', 'PUT'):
cursor.execute('update yourapp_foo set %s where id = %%s' % ', '.join(["%s=%%s" % p[0] for p in request.data.items()]), list(p[1] for p in request.data.items()) + [id])
row = cursor.fetchone()
if row[0]
return Response(status=status.HTTP_201_ACCEPTED)
else:
return Response(status=status.HTTP_404_NOT_FOUND)
elif request.method = 'GET':
cursor.execute('select * from yourapp_foo where id = %s', [id])
row = cursor.fetchone()
if row:
columns = [col[0] for col in cursor.description]
data = zip(columns, row)
return Response(data, status=status.HTTP_200_OK)
else:
return Response(status=status.HTTP_404_NOT_FOUND)
elif request.method = 'DELETE':
cursor.execute('delete from yourapp_foo where id = %s', [id])
row = cursor.fetchone()
if not int(row[0]):
return Response(status=status.HTTP_404_NOT_FOUND)
else:
return Response(status=status.HTTP_204_NO_CONTENT)
the latter code is untested and only serves for teoretical purpose. it is pretty insecure and not intended to be executed in production since it is a bad idea
I would prefer with the shortest approach.
My conclusion is: learn the ORM! If you need to respect your database because it is preexisting, you could use managed models. But always... use the ORM and the features given to you by both Django and DRF.
./manage.py makemigrationsand./manage.py migrateand your database will change according to the changes in you models.