DRF序列化程序查询集过滤交叉表

时间:2020-01-29 19:15:35

标签: django django-models django-rest-framework django-filter

我正在使用Django REST框架配置针对不同服务使用不同登录名进行的实验。如何根据所选服务调整BasicLogins集合的查询集。


上下文

配置实验时,您选择了服务和多个参与的BasicLogins。 有一些与BasicLogin相关的特定登录名。假设我们有BasicLogin,ALogin,BLogin和CLogin。对于给定的BasicLogin,可能并非所有特定的登录名都存在,例如

  • BasicLogin 1 :具有相关的服务登录名 A B
  • BasicLogin 2 :与服务 C
  • 相关的登录名
  • BasicLogin 3 :具有相关的服务登录名 A B C

Django REST Framework powered form to configure an Experiment

BasicLogin有一个supports方法,该方法可以查找与特定于服务的登录名是否相关。如果存在此类特定的Login对象,则BasicLogin对象支持给定的Service。

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可以轻松用于过滤已启用的BasicAccounts。

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
    )

问题

我可以在ExperimentSerializer中过滤BasicLogin RelatedField的查询集,使其仅包含具有给定服务的相应特定登录名的BasicLogins吗?

例如在显示的图片中选择了服务“ A ”,因此仅应显示具有相应 A 登录名的BasicLogins。


以下是完整代码示例:

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
    )

0 个答案:

没有答案
相关问题