Django中创建CardsDesk模型时自动生成78个Card对象的实现方案
实现思路与代码示例
1. 完善Card模型关联
首先给Card模型添加外键关联CardsDesk,确保每张卡牌归属对应牌组;同时将分散的卡牌选项合并为一个完整可遍历的列表,方便批量生成。
修改后的Card模型:
class Card(models.Model): # 关联所属牌组 desk = models.ForeignKey(CardsDesk, on_delete=models.CASCADE, related_name='cards') # 原始分组选项 CHOICES = [ ('Мечи', ( ('Swords_1', 'Туз мечей'), ('Swords_2', 'Двойка мечей'), # ... 其他剑类卡牌 ) ), ] CARDS_TYPE = [ ('Diamonds', ('Diamonds_1', 'Diamonds_1'), ('Diamonds_2', 'Diamonds_2'), # ... 其他花色卡牌 ), ] # 合并所有卡牌选项为扁平列表 ALL_CARD_CHOICES = [] for _, sub_choices in CHOICES: ALL_CARD_CHOICES.extend(sub_choices) for _, sub_choices in CARDS_TYPE: ALL_CARD_CHOICES.extend(sub_choices) # 卡牌类型字段 card_type = models.CharField(max_length=255, choices=ALL_CARD_CHOICES) # 卡牌名称(可自动从选项中获取) name = models.CharField(max_length=255, blank=True) def save(self, *args, **kwargs): if not self.name: self.name = dict(self.ALL_CARD_CHOICES).get(self.card_type) super().save(*args, **kwargs)
2. 重写CardsDesk的save方法自动生成卡牌
在CardsDesk的save方法中判断是否为新创建实例(无pk值),若是则批量生成78张卡牌:
class CardsDesk(models.Model): name = models.CharField(max_length=255, verbose_name='Название колоды', blank=True, null=True) image = models.ImageField(upload_to='media/', verbose_name='Картинка колоды') def save(self, *args, **kwargs): is_new = self.pk is None # 先保存牌组实例 super().save(*args, **kwargs) # 新创建时批量生成卡牌 if is_new: card_objects = [] for card_code, card_name in Card.ALL_CARD_CHOICES: card_objects.append( Card( desk=self, card_type=card_code, name=card_name ) ) # 批量插入效率远高于循环单条保存 Card.objects.bulk_create(card_objects)
3. 替代方案:使用Django post_save信号
若不想修改save方法,可通过信号触发卡牌生成:
from django.db.models.signals import post_save from django.dispatch import receiver @receiver(post_save, sender=CardsDesk) def create_cards_for_desk(sender, instance, created, **kwargs): if created: card_objects = [] for card_code, card_name in Card.ALL_CARD_CHOICES: card_objects.append( Card( desk=instance, card_type=card_code, name=card_name ) ) Card.objects.bulk_create(card_objects)
注意:使用信号需确保代码在Django启动时被加载,可放在models.py或在apps.py的ready方法中导入。
关键注意事项
- 检查
ALL_CARD_CHOICES的总长度是否为78,避免卡牌数量不符 - 优先使用
bulk_create提升批量创建效率 - 若卡牌需初始化其他字段,可在批量创建时直接赋值
内容的提问来源于stack exchange,提问作者skyhelper
相关产品推荐
相关产品推荐

