根据外键函数过滤 Django GenericRelation
Filter Django GenericRelation based on function on foreignkey
我想找到适合各种类别的与我的角色相关的属性。最终我想要这个输出:
"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
函数移到别处吗?
我最终创建了一个自定义管理器:
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()]
我想找到适合各种类别的与我的角色相关的属性。最终我想要这个输出:
"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
函数移到别处吗?
我最终创建了一个自定义管理器:
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()]