I'm trying to combine this answer and this one, with a bit of for looping.
On creating a character, I want to add all possible skills with a value of 0 but I'm getting confused on how to follow the above answers.
I have this mixin:
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
(eventually, the cross_character_types
will be expanded)
And this model:
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
What I've started writing is this, on the NWODCharacter model:
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)
This doesn't work as I don't think I'm passing in the right objects.
Based on this answer though:
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) ])
In this situation, what is my ThroughModel
? Is it CharacterSkillLink.content_object.model
?
How do I do this in my scenario? I'm sorry if this is trivial, but I'm struggling to get my head round it.
It looks to me like CharacterSkillLink
itself is your through model in this case... it generically joins a content type to a SkillAbility
If you think about it, it also makes sense that if you're doing a bulk_create
the objects that you pass in must be of the same model you're doing a bulk_create
on.
So I think you want something like this:
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
])
Note you had too many pairs of []
inside your bulk_create
.
Also I think you should use SkillAbility.objects.get_or_create()
... for a foreign key you need the related object to exist. Just doing SkillAbility()
won't fetch it from the db if it already exists and won't save it to the db if it doesn't.