Кросс-таблицы фильтрации набора запросов DRF Serializer - PullRequest
3 голосов
/ 29 января 2020

Я использую Django REST Framework для настройки экспериментов, которые проводятся с использованием разных имен входа для разных служб. Как настроить набор запросов из набора BasicLogins в зависимости от выбранной службы.


Контекст

При настройке эксперимента вы выбрали службу и несколько участвующих BasicLogins. Есть определенные c логины, которые 1-к-1 связаны с BasicLogin. Допустим, у нас есть BasicLogin, ALogin, BLogin и CLogin. Может случиться, что не все указанные c логины существуют для данного BasicLogin, например,

  • BasicLogin 1 : имеет связанные логины для сервисов A и B
  • BasicLogin 2 : связанные логины для службы C
  • BasicLogin 3 : имеет соответствующие логины для служб A , B , C

Django REST Framework powered form to configure an Experiment

BasicLogin имеет метод support, который ищет, связан ли с ним логин, указанный в Service c. Если такой специфицированный c объект Login существует, объект BasicLogin поддерживает данную службу.

class BasicLogin(models.Model):
    name = models.CharField(max_length=25)
    password = models.CharField(max_length=25)
    disabled = models.BooleanField(default=False, blank=True)

    def supports(self, service_name):
        """ Returns whether a specific Login for a given service is available for a BaseLogin object."""
        if service_name == "a":
            return ALogin.objects.filter(basic_account=self) is not None
        elif service_name == "b":
            return BLogin.objects.filter(basic_account=self) is not None
        elif service_name == "c":
            return CLogin.objects.filter(basic_account=self) is not None

ExperimentSerializer можно легко использовать для фильтрации включенных базовых учетных записей.

class class ExperimentSerializer(serializers.HyperlinkedModelSerializer):
    service = serializers.HyperlinkedRelatedField(
        queryset=Service.objects.all(), many=False, view_name="service-detail"
    )

    basic_logins = serializers.HyperlinkedRelatedField(
        view_name="basiclogin-detail",
        many=True,
        read_only=False,
        queryset=BasicAccount.objects.filter(disabled=False)  
        # ^ Here is where I'd like to only show BasicLogins that support the service 
        # if possible by using the "supports" method of BasicLogin
    )

Вопрос

Можно ли отфильтровать набор запросов BasicLogin RelatedField в ExperimentSerializer, чтобы он содержал только BasicLogins с соответствующим указанным c логином для данной службы?

, например, на показанном рисунке Сервис " A " выбран, поэтому должны отображаться только BasicLogins с соответствующим A логином.


Вот пример с полным кодом :

from django.db import models


######## MODELS
### Service model
class Service(models.Model):
    name = models.CharField(max_length=64, blank=False, null=False)

### Basic login model containing general information
class BasicLogin(models.Model):
    name = models.CharField(max_length=25)
    password = models.CharField(max_length=25)
    disabled = models.BooleanField(default=False, blank=True)

    def supports(self, service_name):
        """ Returns whether a specific Login for a given service is available for a BaseLogin object."""
        if service_name == "a":
            return ALogin.objects.filter(basic_account=self) is not None
        elif service_name == "b":
            return BLogin.objects.filter(basic_account=self) is not None
        elif service_name == "c":
            return CLogin.objects.filter(basic_account=self) is not None

### Specific models for different services
class ALogin(models.Model):
    a_id = models.CharField(max_length=64)  # exemplary

    basic_login = models.OneToOneField(BasicLogins, related_name="a_account")

class BLogin(models.Model):
    b_id = models.CharField(max_length=64)  # exemplary
    b_api_hash = models.CharField(max_length=64)  # exemplary

    basic_login = models.OneToOneField(BasicLogins, related_name="b_account")

class CLogin(models.Model):
    c_password = models.CharField(max_length=64)  # exemplary

    basic_login = models.OneToOneField(BasicLogins, related_name="c_account")

### Model combining the previous models
class Experiment(models.Model):
    basic_logins = models.ManyToManyField(BasicLogins, "experiments")
    service = models.ForeignKey(Service, related_name="experiments")


######## SERIALIZERS
class class ExperimentSerializer(serializers.HyperlinkedModelSerializer):
    service = serializers.HyperlinkedRelatedField(
        queryset=Service.objects.all(), many=False, view_name="service-detail"
    )

    basic_logins = serializers.HyperlinkedRelatedField(
        view_name="basiclogin-detail",
        many=True,
        read_only=False,
        queryset=BasicAccount.objects.filter(disabled=False)  # <--- Here is where I'd like to only show BasicLogins that support the service using the "supports" method
    )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...