根据foreignkey上的函数过滤Django GenericRelation

时间:2015-02-12 12:02:01

标签: python django enums django-queryset

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

"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
        }
    },

我有一个具有属性的类/枚举(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功能移到其他地方?

1 个答案:

答案 0 :(得分: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()]