在 Django 中自动填充一组通用的多对多字段?
Posted
技术标签:
【中文标题】在 Django 中自动填充一组通用的多对多字段?【英文标题】:Autopopulate a set of generic many to many fields in Django? 【发布时间】:2015-04-10 19:29:29 【问题描述】:我正在尝试将this 答案和这个one 结合起来,并带有一点 for 循环。
在创建角色时,我想添加值为 0 的所有可能技能,但我对如何遵循上述答案感到困惑。
我有这个混音:
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
(最终,cross_character_types
将被扩展)
还有这个模型:
class CharacterSkillLink(Trait, CrossCharacterMixin):
PRIORITY_CHOICES = (
(1, 'Primary'), (2, 'Secondary'), (3, 'Tertiary')
)
skill = models.ForeignKey('SkillAbility')
priority = models.PositiveSmallIntegerField(
choices=PRIORITY_CHOICES, default=None)
speciality = models.CharField(max_length=200, null=True, blank=True)
def __str__(self):
spec_string = " (" + self.speciality + ")" if self.speciality else ""
return self.skill.skill.label + spec_string
我开始写的是这个,在 NWODCharacter 模型上:
def save(self, *args, **kwargs):
if not self.pk:
character_skills_through = CharacterSkillLink.content_object.model
CharacterSkillLink.objects.bulk_create([
[character_skills_through(skill=SkillAbility(
skill), content_object=self) for skill in SkillAbility.Skills]
])
super(NWODCharacter, self).save(*args, **kwargs)
这不起作用,因为我认为我传递的对象不正确。
虽然基于此answer:
from django.db import models class Users(models.Model): pass class Sample(models.Model): users = models.ManyToManyField(Users) Users().save() Users().save() # Access the through model directly ThroughModel = Sample.users.through users = Users.objects.filter(pk__in=[1,2]) sample_object = Sample() sample_object.save() ThroughModel.objects.bulk_create([ ThroughModel(users_id=users[0].pk, sample_id=sample_object.pk), ThroughModel(users_id=users[1].pk, sample_id=sample_object.pk) ])
在这种情况下,我的ThroughModel
是什么?是CharacterSkillLink.content_object.model
吗?
如何在我的场景中执行此操作?如果这是微不足道的,我很抱歉,但我正在努力解决它。
【问题讨论】:
能否让我知道如何改进问题? 【参考方案1】:在我看来,CharacterSkillLink
在这种情况下本身就是您的直通模型...它通常将内容类型连接到 SkillAbility
如果您考虑一下,如果您正在执行bulk_create
,那么您传入的对象必须与您正在执行bulk_create
的模型相同。
所以我认为你想要这样的东西:
def save(self, *args, **kwargs):
initialise_skill_links = not self.pk
super(NWODCharacter, self).save(*args, **kwargs)
if initialise_skill_links:
CharacterSkillLink.objects.bulk_create([
CharacterSkillLink(
skill=SkillAbility.objects.get_or_create(skill=skill)[0],
content_object=self
)
for skill in SkillAbility.Skills
])
请注意,您的 bulk_create
中有太多的 []
对。
另外我认为你应该使用SkillAbility.objects.get_or_create()
... 作为你需要相关对象存在的外键。如果它已经存在,只是做SkillAbility()
不会从数据库中获取它,如果它不存在,则不会将它保存到数据库中。
【讨论】:
刚刚下班回家。明天会尝试使用这个。顺便说一句,你是对的,CharacterSkillLink
是我的原型……我不知道我在想什么。
这在我的管理页面上运行良好,但它没有在该内联的下拉框中(单独的问题)显示任何技能。我删除了内联以查看它是否会创建和保存技能,但现在它给了我两个错误。第一个在错误页面的顶部:ValueError at /admin/characters/mage/add/
和 Cannot assign "(<SkillAbility: Academics>, False)": "CharacterSkillLink.skill" must be a "SkillAbility" instance.
然后,Error in formatting: 'CharacterSkillLink' object has no attribute 'speciality'
设置 speciality = ""
并指定无效。帮忙?
我发现问题get_or_create
返回一个元组,技能被分配给这个元组,而不是SkillAbility
对象。这似乎应该可以工作(它不会出错),但我认为它不起作用。我添加了一个 GenericRelation 到它,当我保存并尝试访问 mage_instance.skills.all()
它返回并清空列表。
我已经用你想要做的编辑更新了答案,还添加了[0]
来处理元组问题
是的,问题是还没有object_id
可以设置,因为我们在if not self.pk
块中执行此代码...将更新答案以上是关于在 Django 中自动填充一组通用的多对多字段?的主要内容,如果未能解决你的问题,请参考以下文章
如何在引导选项卡块中按 django 模板中的多对多字段过滤对象
CASCADE 究竟如何与 Django 中的多对多字段一起工作