【问题标题】:Filter Django GenericRelation based on function on foreignkey根据外键上的函数过滤 Django GenericRelation
【发布时间】:2015-04-13 03:48:54
【问题描述】:

我想找到与我的角色相关的适合各种类别的属性。最终我想要这个输出:

"Attributes": {
        "Physical": {
            "Level": 1,
            "Strength": 1,
            "Dexterity": 1,
            "Stamina": 1
        },
        "Mental": {
            "Level": 2,
            "Intelligence": 1,
            "Wits": 1,
            "Resolve": 1
        },
        "Social": {
            "Level": 3,
            "Presence": 1,
            "Manipulation": 1,
            "Composure": 1
        }
    },

我有一个包含属性的 Class/Enum(AutoNumber),以及一种查找哪个是哪个的方法:

class AttributeAbility(models.Model):

    class Attributes(AutoNumber):
        INTELLIGENCE = ()  # Mental, Power
        WITS = ()  # Mental', 'Finesse
        RESOLVE = ()  # Mental', 'Resistance
        STRENGTH = ()  # Physical', 'Power
        DEXTERITY = ()  # Physical', 'Finesse
        STAMINA = ()  # Physical', 'Resistance
        PRESENCE = ()  # Social', 'Power
        MANIPULATION = ()  # Social', 'Finesse
        COMPOSURE = ()  # Social', 'Resistance

    attribute = EnumField(Attributes)

    @property
    def attribute_type(self):
        attribute_group = lambda attribute: (
            int((attribute.value - 1) / 8)) + 1 % 3

        return Category(attribute_group(self.attribute))

class Category(AutoNumber):
    MENTAL = ()
    PHYSICAL = ()
    SOCIAL = ()

我使用这些类将 AttributeAbility 与我的角色联系起来:

class CrossCharacterMixin(models.Model):
    cross_character_types = models.Q(app_label='mage', model='mage')
    content_type = models.ForeignKey(ContentType, limit_choices_to=cross_character_types,
                                     null=True, blank=True)
    object_id = models.PositiveIntegerField(null=True)
    content_object = GenericForeignKey('content_type', 'object_id')

    class Meta:
        abstract = True

class CharacterAttributeLink(Trait, CrossCharacterMixin):
    MIN = 1
    PRIORITY_CHOICES = (
        (0, 'Unassigned'), (1, 'Primary'), (2, 'Secondary'), (3, 'Tertiary')
    )
    attribute = models.ForeignKey('AttributeAbility')
    priority = models.PositiveSmallIntegerField(
        choices=PRIORITY_CHOICES, default=0
    )

    def __str__(self):
        return self.attribute.attribute.label

然后是我拥有的法师:

attributes = GenericRelation('CharacterAttributeLink')

@property
def physical_attributes(self):
    type_id = Category['PHYSICAL']
    return self.attributes.filter(attribute_type=type_id)

但我收到的错误是:Cannot resolve keyword 'attribute_type' into field. Choices are: attribute, attribute_id, content_type, content_type_id, current_value, id, maximum_value, object_id, priority

我的功能是这样的:

@property
def physical_attributes(self):
    type_id = Category['PHYSICAL']
    return self.attributes.filter(attribute__attribute_type=type_id)

我收到此错误:Related Field got invalid lookup: attribute_type 这有点道理(尽管我在文档中看到过:>>> Entry.objects.filter(blog_id=4))。

最后添加__exact,给了我这个:Relation fields do not support nested lookups....此时我迷路了。我需要custom manager 吗?我需要将我的physical_attribute 函数移到别处吗?

【问题讨论】:

    标签: python django enums django-queryset


    【解决方案1】:

    我最终创建了一个自定义管理器:

    class CategoryManager(models.Manager):
    
        '''
        Class to manage instances that rely on the category enum
        '''
    
        def physical(self):
            return [categorised_item for categorised_item in super(CategoryManager, self).get_queryset().all()
                    if categorised_item.category == Category['PHYSICAL']]
    
        def mental(self):
            return [categorised_item for categorised_item in super(CategoryManager, self).get_queryset().all()
                    if categorised_item.category == Category['MENTAL']]
    
        def social(self):
            return [categorised_item for categorised_item in super(CategoryManager, self).get_queryset().all()
                    if categorised_item.category == Category['SOCIAL']]
    

    然后将其添加到我的 AttributeAbility 模型中:

    objects = CategoryManager()
    

    并在我的角色模型上定义此属性:

    @property
    def social_skills(self):
        return [self.skills.filter(skill=skill) for skill
                in SkillAbility.objects.social()]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-08
      • 1970-01-01
      • 2016-06-10
      • 2021-06-06
      • 2020-09-07
      • 2012-01-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多