Как передать аргумент pk внутри представления на основе класса в кверисет в Django

У меня есть следующие Django urls/views и 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
    }

УРЛЫ

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)),

]

Виды

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)

В рамках представления у меня есть представление на основе класса IdentifierViewSet со следующей строкой queryset queryset = Identifier.objects.all(), которая получает все данные из модели базы данных, но я хотел бы получить только queryset на основе портфеля, связанного с учетной записью пользователя, который работает, используя следующие строки кода, взятые из представления на основе функции portfolio:

 portfolio = Account.objects.get(id=pk)

 identifiers = Identifier.objects.filter(account=pk)

Я не смог передать пк из урлов в этот вид на основе класса, но смог сделать это с видом на основе функции.

Как я могу передать вышеуказанные объектные запросы в представление на основе классов, чтобы заменить набор запросов в представлении на основе классов queryset = Identifier.objects.all()? Спасибо

Для этого вы можете переопределить метод get_queryset из 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

Существуют функции list(), retrieve(), create(), update(), partial_update(), destroy(), причем параметр pk может передаваться четырем функциям, кроме list и create.

Например, для метода PUT API можно настроить функцию update.

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()
        ...

Вы также можете настроить другие функции подобным образом.

Вернуться на верх