Проблема фильтрации ViewSet в Django Rest Framework на основе поля пользователя Foreignkey - PullRequest
0 голосов
/ 29 января 2019

У меня есть проект Django, над которым я работаю.В этом проекте две модели.Существует модель user и account.Я объединяю наборы остальных рамок django.Я включу их ниже.Сейчас я интегрирую Django Rest Framework в проект.Я пытаюсь понять, как сделать две вещи.

2 модели:

По умолчанию пользователь django

Модель учетной записи:

class Account(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    _id = models.CharField(max_length=45)
    name = models.CharField(max_length=140)
    balance = models.DecimalField(max_digits=100, decimal_places=2)
    currency = models.CharField(max_length=12)
    bank_name = models.CharField(max_length=120)
    routing = models.CharField(max_length=8)
    _class = models.CharField(max_length=22)
    type = models.CharField(max_length=22)
    active = models.BooleanField(default=True)
    main = models.BooleanField(default=False)
    synapse = models.BooleanField(default=False)
    create_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.user.username + ' - ' + self.name + ': ' + str(self.balance)

1 => Я хочу иметь возможность набирать в конечной точке /api/users/accounts/omarjandlai и получить один или несколько аккаунтов с помощью omarjandali user foreignkey

2 => Я хочу иметь возможность ввести следующее api/users/accounts/ и вернуть все учетные записи, которые есть в базе данных

Я пробовал 4 - 5 различных способов заставить это работать, и я не мог заставить это работать.

Вот мои сериализаторы и просмотры

сериализаторы:

class AccountSerializer(serializers.ModelSerializer):
    class Meta:
        model = Account
        fields = ('user', '_id', 'name', 'balance', 'currency', 'bank_name',
                  'routing', '_class', 'type', 'active', 'main', 'synapse')

Просмотров:

class AccountViewSet(viewsets.ModelViewSet):
    queryset = Account.objects.all();
    serializer_class = AccountSerializer
    filter_backends = (filters.DjangoFilterBackend,)
    filter_fields = ('user',)

что происходит, когда я делаю

api/users/account я вижу все учетные записи

api/users/account/omarjandali Я получаю detail not found

URL:

router = DefaultRouter()
router.register(r'users', UserViewSet, basename='user')
router.register(r'accounts', AccountViewSet, basename='account')
urlpatterns = router.urls

1 Ответ

0 голосов
/ 29 января 2019

Я вижу, что вы используете DefaultRouter функциональность по умолчанию.Таким образом, вы можете получить доступ только к деталям записей, используя их первичный ключ.Поскольку вы не указали ни одно поле в качестве первичного ключа в явном виде (primary=True), Django устанавливает поле id , которое является PositiveIntegerField в качестве первичного ключа модели.Таким образом, если вы хотите получить доступ к деталям записи, вы должны использовать api/users/account/112/.

Вы можете получить доступ к записям по имени, используя фильтры: api/users/account/?search='omarjandali', но вам нужно добавить SearchFilter.

from rest_framework.filters import SearchFilter 

class AccountViewSet(viewsets.ModelViewSet):
    queryset = Account.objects.all();
    serializer_class = AccountSerializer
    filter_backends = (filters.DjangoFilterBackend, SearchFilter)
    filter_fields = ('user',)
    search_fields = ('name',)

Если вы хотите придерживаться шаблона URL api/users/account/omarjandali/, вам нужно добавить его в urls.py и использовать другой набор представлений, чтобы позволить исходному функционироватьв соответствии с DefaultRouter определение:

urls.py:

router = DefaultRouter()
router.register(r'users', UserViewSet, basename='user')
router.register(r'accounts', AccountViewSet, basename='account')

urlpatterns = [
    path('', include(router.urls)),
    path('api/users/account/<str:username>/', views.GetRecordsByNameViewSet.as_view({'get': 'list'}),
]

views.py

from rest_framework.response import Response

class GetRecordsByNameViewSet(viewsets.ViewSet):
    def list(self, request, username):
        accounts = Account.objects.filter(user__username=username)
        accounts_to_return = AccountSerializer(accounts, many=True).data

        return Response(accounts_to_return)
...