Django: General Questions about API views
I am working on a project and I have a front-end in React which makes some basic CRUD axios calls to the Django server.
I am trying to figure the best way to administer my Django views to receive and process these requests. I understand this very much depends on the how my application needs to function. But at the moment, I am just trying to create simple views (which joins a couple of data models together and returns)
This is the approach in action:
class Hero(models.Model):
character = models.ForeignKey(
Card, on_delete=models.CASCADE, related_name="class_id", null=True
)
weapon = models.ForeignKey(
Card, on_delete=models.CASCADE, related_name="weapon_id", null=True
)
player = models.OneToOneField(Player, on_delete=models.PROTECT, null=True)
class Game(models.Model):
hero1 = models.ForeignKey(
Hero, on_delete=models.PROTECT, related_name="hero1_id", null=True
)
hero2 = models.ForeignKey(
Hero, on_delete=models.PROTECT, related_name="hero2_id", null=True
)
hero3 = models.ForeignKey(
Hero, on_delete=models.PROTECT, related_name="hero3_id", null=True
)
hero4 = models.ForeignKey(
Hero, on_delete=models.PROTECT, related_name="hero4_id", null=True
)
and then I would write a view as such,
class GameHeroView(APIView):
serializer_class = HeroSerializer
def get(self, request, id=0):
game_id = request.query_params.get("id")
if game_id is None:
game_id = id
# Create an empty list for serialized data
serialized_data = []
sql = (
" \
SELECT gh.* \
FROM gauntlet_game gg, \
gauntlet_hero gh \
WHERE gg.id = "
+ str(game_id)
+ " \
AND (gg.hero1_id = gh.id \
OR gg.hero2_id = gh.id \
OR gg.hero3_id = gh.id \
OR gg.hero4_id = gh.id)"
)
heros = Hero.objects.raw(sql)
serialized_data = HeroSerializer(heros, many=True).data
# Create the custom response object
response_data = {
"count": len(serialized_data),
"next": None, # You can set this to the next page URL if pagination is used
"previous": None, # You can set this to the previous page URL if pagination is used
"results": serialized_data,
}
return Response(response_data)
Here, for example, I want to get all the heroes for each game entry(which already exists). The current approach I am taking is,
- create a new view class specifically for each case,
- define get, post, put, etc methods for each view.
So, for example, if i needed to update all heroes for a single game_id, I can implement a put method here in this class. Apart from these methods, no other method should exist, and only a new class should be created.
Here are my questions:
- Is this a viable approach or am I being restrictive.
- In django tools, Is there any particular tool to look at what is being requested? I have many errors sometimes with the method type being wrong or some issue with how the request parameters are being set and it can get hard to debug.
Any tutorials/links are appreciated.
I would recommend you to have a look at django rest framework model view sets
This suits your usecase really well. You basically want to do the crud operations on model, this ModelViewSet will allow you to list, create, delete, update, get (single). In case you for example only need list, and create, you can simply delete the mixins accordingly.
class ModelViewSet(mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet):
Then if you would like to do a certain filter in your ViewSet, it makes sense to include the django-filter package, which allows you to put in a filterset_fields
, see below:
class CalculationViewSet(viewsets.ModelViewSet):
queryset = Calculation.objects.all()
serializer_class = CalculationSerializer
filterset_fields = {
'project': ["exact"],
}
In this example I allow to filter the queryset from the url like this:
localhost:8000/calculations/?project=3
It will then only get the calculations which have project_id
3
.
Please note that in your endpoint you introduce a security risk for SQL injection as well. You do no validation for your game_id
, this means that hackers could put in a malicious SQL query which will have more access then your app would want to provide.