I have the following Django urls/views and Models:
Models
ORDER_COLUMN_CHOICES = Choices(
('0', 'id'),
('1', 'code'),
('2', 'code_type'),
('3', 'created'),
('4', 'updated'),
('5', 'valid'),
)
class Identifier(TimeStampMixin, models.Model):
code_type = models.CharField(max_length=10, null=True)
code = models.CharField(max_length=12)
account = models.ForeignKey(Account, on_delete=models.CASCADE, null=True)
actflag = models.CharField(max_length=1, blank=True)
valid = models.BooleanField(default=False)
def __str__(self):
return self.code
class Meta:
db_table = "portfolio_identifier"
def query_identifier_by_args(**kwargs):
draw = int(kwargs.get('draw', None)[0])
length = int(kwargs.get('length', None)[0])
start = int(kwargs.get('start', None)[0])
search_value = kwargs.get('search[value]', None)[0]
order_column = kwargs.get('order[0][column]', None)[0]
order = kwargs.get('order[0][dir]', None)[0]
order_column = ORDER_COLUMN_CHOICES[order_column]
# django orm '-' -> desc
if order == 'desc':
order_column = '-' order_column
queryset = Identifier.objects.all()
total = queryset.count()
if search_value:
queryset = queryset.filter(Q(id__icontains=search_value) |
Q(code__icontains=search_value) |
Q(code_type__icontains=search_value) |
Q(created__icontains=search_value) |
Q(updated__icontains=search_value) |
Q(valid__icontains=search_value))
count = queryset.count()
queryset = queryset.order_by(order_column)[start:start length]
return {
'items': queryset,
'count': count,
'total': total,
'draw': draw
}
URLS
from . import views
from rest_framework.routers import DefaultRouter
from apps.portfolio.views import IdentifierViewSet
router = DefaultRouter()
router.register(r'portfolio', IdentifierViewSet)
urlpatterns = [
path('portfolios/', views.portfolios, name="portfolios"),
path('portfolio/<str:pk>/', views.portfolio, name="portfolio"),
path('api/', include(router.urls)),
]
Views
def portfolio(request, pk):
portfolio = Account.objects.get(id=pk)
identifiers = Identifier.objects.filter(account=pk)
context = {"portfolio": portfolio, "identifiers": identifiers}
return render(request, 'portfolio.html', context)
class IdentifierViewSet(viewsets.ModelViewSet):
queryset = Identifier.objects.all()
serializer_class = IdentifierSerializer
authentication_classes = []
def list(self, request, **kwargs):
try:
identifier = query_identifier_by_args(**request.query_params)
serializer = IdentifierSerializer(identifier['items'], many=True)
result = dict()
result['data'] = serializer.data
result['draw'] = identifier['draw']
result['recordsTotal'] = identifier['total']
result['recordsFiltered'] = identifier['count']
return Response(result, status=status.HTTP_200_OK, template_name=None, content_type=None)
except Exception as e:
return Response(e, status=status.HTTP_404_NOT_FOUND, template_name=None, content_type=None)
Within the Views I have a Class based view IdentifierViewSet
with the following queryset line queryset = Identifier.objects.all()
which retreievs all data from the db model however I would like to only retrieve queryset based on portfolio associated with the user's account which works using the following lines of code taken from the function based view portfolio
:
portfolio = Account.objects.get(id=pk)
identifiers = Identifier.objects.filter(account=pk)
I was unable to pass the pk from urls to this class based view but was able to do so with teh function based view.
How can I go about passing the above object queries to within the Class based view to replace the queryset in the Class based view queryset = Identifier.objects.all()
? Thanks
CodePudding user response:
To do that you can override the get_queryset
method from the Django ModelViewSet.
def get_queryset(self):
portfolio = Account.objects.get(id=self.request.account.pk)
#... do something
identifiers = Identifier.objects.filter(account=self.request.account.pk)
return identifiers
CodePudding user response:
There are list()
, retrieve()
, create()
, update()
, partial_update()
, destroy()
functions and the pk
parameter can be passed to four functions except list and create.
For example, for PUT method of the API, you can customize the update
function.
class IdentifierViewSet(viewsets.ModelViewSet):
queryset = Identifier.objects.all()
serializer_class = IdentifierSerializer
authentication_classes = []
def list(self, request, *args, **kwargs):
...
def update(self, request, pk):
# you can get the pk here
print(pk)
# you can get the object with the current `pk`
instance = self.get_object()
...
You can also customize other functions like this.