You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Django中两个随机样本匹配相同外键Race值

问题描述

我正在开发一个生成随机奇幻角色名的Django应用,使用以下模型:

class VillagerFirstNames(models.Model):
    first_name=models.CharField(max_length=30, unique=True)
    race = models.ForeignKey(Race, on_delete=models.CASCADE)

    def __str__(self):
        return self.first_name
class VillagerLastNames(models.Model):
    last_name = models.CharField(max_length=30, unique=True)
    race = models.ForeignKey(Race, on_delete=models.CASCADE)

    def __str__(self):
        return self.last_name

问题出在视图中:为了使用random.sample获取随机样本,我需要将查询集转为列表,代码如下:

foreign_first = list(VillagerFirstNames.objects.all())
foreign_first_random = random.sample(foreign_first, 3)
context["foreign_first"] = foreign_first_random
foreign_last = list(VillagerLastNames.objects.filter(race__race=foreign_first_random.race))
context["foreign_last"] = random.sample(foreign_last, 3)

我希望获取的姓氏与随机抽取的名字属于相同Race,但上述写法中,foreign_first_random是列表,不存在race属性,无法实现匹配,请求解决方法。

解决方案

根据需求场景,提供两种可行的实现方式:

场景1:生成的3组姓名统一属于同一个随机种族

先随机选定一个种族,再基于该种族抽取对应的名字和姓氏:

# 随机获取一个种族实例
random_race = Race.objects.order_by('?').first()

# 抽取该种族下的3个名字(先判断数据量避免报错)
first_name_candidates = list(VillagerFirstNames.objects.filter(race=random_race))
foreign_first_random = random.sample(first_name_candidates, 3) if len(first_name_candidates) >=3 else first_name_candidates
context["foreign_first"] = foreign_first_random

# 抽取同一种族下的3个姓氏
last_name_candidates = list(VillagerLastNames.objects.filter(race=random_race))
foreign_last = random.sample(last_name_candidates, 3) if len(last_name_candidates) >=3 else last_name_candidates
context["foreign_last"] = foreign_last

场景2:每个名字匹配对应种族的姓氏(3个名字可来自不同种族)

遍历抽取到的名字列表,逐个获取对应种族的姓氏:

foreign_first = list(VillagerFirstNames.objects.all())
foreign_first_random = random.sample(foreign_first, 3)
context["foreign_first"] = foreign_first_random

# 为每个名字匹配同种族的姓氏
foreign_last_list = []
for name_obj in foreign_first_random:
    # 获取当前名字所属种族的姓氏集合
    race_last_names = list(VillagerLastNames.objects.filter(race=name_obj.race))
    if race_last_names:
        # 随机选一个姓氏添加到列表
        foreign_last_list.append(random.choice(race_last_names))
context["foreign_last"] = foreign_last_list

补充说明

  • order_by('?')是Django中随机获取单条数据的常规写法,数据量不大时性能足够。
  • 抽取样本前判断列表长度,避免random.sample因样本数量不足抛出异常。

内容的提问来源于stack exchange,提问作者Colin Crusott

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 12:45:38