The main parts of the Django Rest Framework are views (ViewSets, ApiViews, etc.) and serializers. None of these are the perfect place to write logic. As you already mentioned, writing logic in any representation is not good. What for?
- Cannot use the same logic from another part of the application
- It is not possible to encapsulate logic (you need to call the view for the logic to run)
- There is no way to unit test logic because it is associated with a view
IMHO, models are not a good place to write logic. Think of the model as defining your database. I would put them as simple as possible. You can override "save" and other methods to perform trivial tasks. Any other advanced features should live outside of it.
I can think of two best places for what you need:
One of them is django signal
Better is a custom class. Encapsulate / separate the logic in your class (you can use static or instance methods, it doesn't matter), and then you can:
- Unit test those methods / mock this class
- Reusing this logic somewhere else
- Simplify your code according to KISS principle
- Use it from a signal containing a simple signal code.
- Use it from the celery task (if you will implement this in the future) without changing one line of your code.
UPDATE An example of how to organize the code.
From the comments it is clear that the signal will not work, because the analysis operation will be performed at the request of the user. A signal would be useful if this operation should be performed automatically while saving a specific model.
I assume that you know how to use the django-rest-framework api views or views, serializers, etc. I do not know how about this, better ask another question. This will be a python explanation rather than anything else.
In your application module, create the app_business_logic.py file or whatever you want to name. You can place it at the same level as models.py, for example, but this is not necessary:
class HoldingsAnalyser:
Now, in the api view or in the django-rest-framework view, create a POST method that will be called when the client application user clicks a button (this button generates analysis):
from yourapp.app_business_logic import HoldingsAnalyser class StockPortfolioViewSet(WhatEverMixingYouNeedToInheritFrom): serializer_class = whatever
The URL for this will be something like http://server.com/api_path/stockportfolio/21/run_analysis/ , where 21 will be the StockPortfolio identifier