Проблема фильтрации Django Rest Framework ViewSet на основе пользовательского поля внешнего ключа

У меня есть проект django, над которым я работаю. В этом проекте две модели. Есть модели user и account. Я интегрирую наборы представлений django rest framework. Я включу их ниже. Сейчас я интегрирую в проект 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

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

person Omar Jandali    schedule 29.01.2019    source источник
comment
Пожалуйста, поделитесь своим urls.py   -  person HuLu ViCa    schedule 29.01.2019
comment
Добавлю в исходный пост внизу @HugoLuisVillalobosCanto   -  person Omar Jandali    schedule 29.01.2019


Ответы (1)


Я вижу, что вы используете стандартные функции 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)
person HuLu ViCa    schedule 29.01.2019
comment
Я хочу передать <username>, а затем выполнить фильтрацию на основе моделей пользователей username field. Будет ли это делать приведенный выше код. И если в URL-адресе нет имени пользователя, я хочу получить все учетные записи в базе данных. Я хочу использовать этот параметр username вместо первичного ключа ... - person Omar Jandali; 29.01.2019
comment
Я внес некоторые правки, чтобы учесть ваш комментарий. С помощью этого кода вы можете передать ‹username› в качестве параметра и получить все записи, равные username. Вы также можете получить все записи в Account, если не пройдете ни одного username - person HuLu ViCa; 29.01.2019
comment
Спасибо, попробую. Я уже 2 дня пытаюсь решить эту проблему. У меня был другой вопрос о переполнении стека, и я ходил кругами по поводу решения. ржу не могу - person Omar Jandali; 29.01.2019
comment
Удачи. Если вы хотите попробовать более сложные запросы для поиска, проверьте это: docs. djangoproject.com/en/2.1/topics/db/search - person HuLu ViCa; 29.01.2019
comment
Я хотел использовать второй рекомендованный метод и получил эту ошибку AssertionError at /api/users/account/omarjandali/ Cannot apply DjangoModelPermissionsOrAnonReadOnly on a view that does not set .queryset` или получил .get_queryset() метод. `Когда я выполнял api/users/account/omarjandali - person Omar Jandali; 29.01.2019
comment
У меня все работает нормально. Спасибо. у меня была орфографическая ошибка - person Omar Jandali; 29.01.2019
comment
Пожалуйста. Буду признателен за выбор моего ответа. - person HuLu ViCa; 29.01.2019