为了账号安全,请及时绑定邮箱和手机立即绑定

Django创建没有表单的实例模型

Django创建没有表单的实例模型

胡子哥哥 2021-11-09 19:28:29
我正在尝试创建“Partita”模型的实例,但我不想手动设置带有表单的字段;我需要使用一个随机整数来设置字段(它们是两个外键),该整数指的是外键的 id。这是为了创建一种足球比赛的创建者,其中“Partita”(意大利语比赛)由 team1 和 team2(在我的代码“casa”和“trasferta”中)组成,我该怎么做?我试过这个,但它抛出:找不到页面,没有 FantaSquadra 匹配给定的查询。视图.py:def createPartite(request):    num1=0    num2=0    gior=0    while num1==num2:        num1 = str(random.randint(1,3))        num2 = str(random.randint(1,3))        if num1!=num2:            gior=gior+1    cas= get_object_or_404(FantaSquadra, pk=num1)    tra= get_object_or_404(FantaSquadra, pk=num2)    partita = Partita.creaP(cas,tra)    partita.save()    contesto = {        'partita': partita    }    return render(request, 'sondaggio/partite.html',contesto)模型.py:class FantaSquadra(models.Model):    proprietario = models.ForeignKey(User, on_delete=models.CASCADE,unique=True)    nome_fantasquadra = models.CharField(max_length=200,unique = True)    punteggio = models.IntegerField(default=0)    def __str__(self):        return self.nome_fantasquadraclass Partita(models.Model):    giornata = models.IntegerField(default=1)    casa=models.ForeignKey(FantaSquadra,on_delete=models.CASCADE, related_name='fantasquadra_casa', unique=True)    traferta = models.ForeignKey(FantaSquadra, on_delete=models.CASCADE, related_name='fantasquadra_trasferta', unique=True)    def __str__(self):        return "giornata "+str(self.giornata)    def creaP(self,cas,trasfert):        self.casa = cas        self.traferta = trasfert        return self
查看完整描述

1 回答

?
温温酱

TA贡献1752条经验 获得超4个赞

首先(部分无关但不完全),你不应该get_object_or_404()在这里使用。此函数只是详细视图中递归代码模式的简单快捷方式(尝试获取模型实例并在未找到时返回 404 HTTP 响应)。检索模型实例的正确方法是YourModel.objects.get(pk=xxx),YourModel.DoesNotExist如果找不到匹配的记录,它将引发异常。


第二点(部分无关但很好),您的视图应该只接受 POST 请求 - GET 请求不得修改服务器状态。


现在问/您的问题:您当然只能使用现有的 FantaSquadra 记录,并且不能保证您的随机数与现有的 pk 匹配。你可以用蛮力的方式解决它:


while True:

    num = random.randint(1,3)

    try:

        obj = FantaSquadra.objects.get(pk=num)

        break

    except FantaSquadra.DoesNotExist:

        continue

但这会非常低效。一个更简单的解决方案是从现有FantaSquadra pk 列表中随机挑选一个 pk :


 pks = list(FantaSquadra.objects.values_list("pk", flat=True))

 num = random.choice(pks)

 # now you're garanteed to have a matching object

 obj = FantaSquadra.objects.get(pk=num)

作为一个额外的好处,您现在可以通过在选择记录之前过滤您的查询集来限制潜在的候选人。


编辑:


此外,您的Partita.creaP()方法显然是错误的——它不“创建”任何东西,它只更新当前实例的casa和traferta属性Partita(并且不保存它)。它也没有用,因为 Django 查询集已经提供了一种创建(真正创建)新记录的方法,非常令人惊讶的是,它命名为 'create()`:


  partita = Partita.objects.create(casa=cas,traferta=tra)

至于您收到的错误消息:您的creaP()方法是一个实例方法,因此应该在实例上调用它(在这种情况下,Python 会自动将您调用该方法的实例作为第一个('self')参数传递) ,不在课堂上。好吧,你也可以在类上调用它,但是你必须明确地传递一个Partita实例——这意味着你必须首先创建一个。只是路过尚未定义的名称之前,只能导致一个NameError明显。


请不要冒犯,但看起来您并不真正了解自己在做什么,只是尝试任何事情直到它似乎起作用为止。这种编程方法是众所周知的反模式,实际上,它行不通。我建议你花点时间学习Python(做官方教程+浏览文档)和Django(同上),这会节省你很多时间和痛苦。


查看完整回答
反对 回复 2021-11-09
  • 1 回答
  • 0 关注
  • 168 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信