I am new to Django & DRF and I am trying to replace the default api view given from ModelViewSet (scr1,scr2,scr3) with custom HTML templates. Default view works just fine, i've tested with postman and it can do CRUD functions(at least it seems so), but I have no idea how to substitute the default views with custom html pages. I did follow DRF docs - it worked, also searcged solutions(this one was promising), but I simply can't adopt it my situation. Please help!
models.py:
from django.db import models
class Package(models.Model):
prod_name = models.CharField(max_length=255, default=0)
quantity = models.IntegerField(default=0)
unit_price = models.IntegerField(default=0)
def __str__(self):
return self.prod_name
class Orders(models.Model):
order_id = models.CharField(max_length=255, default=0)
package = models.ManyToManyField(Package)
is_cod = models.BooleanField(default=False)
def __str__(self):
return self.order_id
serializers.py:
from rest_framework import serializers
from .models import Package, Orders
class PackageSerializer(serializers.HyperlinkedModelSerializer):
id = serializers.IntegerField()
prod_name = serializers.CharField(max_length=255, default=0)
quantity = serializers.IntegerField(default=0)
unit_price = serializers.IntegerField(default=0)
class Meta:
model = Package
fields = "__all__"
class OrderSerializer(serializers.HyperlinkedModelSerializer):
package = PackageSerializer(many=True)
def get_or_create_packages(self, packages):
print("this is package in gocp:", packages)
package_ids = []
i = 0
for package in packages:
print("i=", i)
i += 1
package_instance, created = Package.objects.get_or_create(pk=package.get('id'), defaults=package)
print("package id:", package.get('id'))
package_ids.append(package_instance.pk)
print("package_ids:", package_ids)
return package_ids
def create_or_update_packages(self, packages):
package_ids = []
for package in packages:
package_instance, created = Package.objects.update_or_create(pk=package.get('id'), defaults=package)
package_ids.append(package_instance.pk)
return package_ids
def create(self, validated_data):
print("this is validated_data:", validated_data)
package = validated_data.pop('package', [])
print("this is package:", package)
order = Orders.objects.create(**validated_data)
order.package.set(self.get_or_create_packages(package))
return order
def update(self, instance, validated_data):
package = validated_data.pop('package', [])
instance.package.set(self.create_or_update_packages(package))
fields = ['order_id', 'is_cod']
for field in fields:
try:
setattr(instance, field, validated_data[field])
except KeyError: # validated_data may not contain all fields during HTTP PATCH
pass
instance.save()
return instance
class Meta:
model = Orders
fields = "__all__"
views.py:
from .serializers import OrderSerializer, PackageSerializer
from .models import Package, Orders
from rest_framework import viewsets
class OrderViewSet(viewsets.ModelViewSet):
serializer_class = OrderSerializer
queryset = Orders.objects.all()
class PackageViewSet(viewsets.ModelViewSet):
serializer_class = PackageSerializer
queryset = Package.objects.all()
urls.py:
from django.urls import path, include
router = DefaultRouter()
router.register(r'order', OrderViewSet, basename='orders')
router.register(r'package', PackageViewSet, basename='package')
urlpatterns = [
path('api/', include(router.urls)),
]
I am assuming that:
- list(), create()/update() needs to be modified in views.py (class OrderViewSet & PackageViewSet), but how? I did try many different options to define - list(), create()/update() functions, but nothing worked, for example(in this particular case im not allowed to overide existing list method):
@action (renderer_classes=[TemplateHTMLRenderer], detail=True)
def list(self, request, *args, **kwargs):
template_name = 'order_list.html'
queryset = self.filter_queryset(self.get_queryset())
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data, template_name='order_list.html')
- Actual html templates need to conform to the nested model that I have and I am not sure how it would work with nested data. Since I can't solve the 1st point, can't test out and try to solve the 2nd point.
Will rendering_form serializer work? Taking the DRF docx exaple from work?:
{% load rest_framework %}
<html><body>
<h1>Orders - {{ orders.order_id }}</h1>
<form action="{% url 'order-detail' pk=orders.pk %}" method="POST">
{% csrf_token %}
{% render_form serializer %}
<input type="submit" value="Save">
</form>
</body></html>
Perhaps I should forget ModelsViewSet and go with APIView?(though in this particular case if there exist a solution I would prefer to know it).