Django创建没有形式的实例模型

时间:2019-02-15 09:02:04

标签: python django

我正在尝试创建“ Partita”模型的实例,但是我不想手动设置带有表单的字段。我需要为字段(它们是两个ForeignKey)设置一个随机整数,该整数引用外键的ID。

这是为了创建一种足球比赛的创建者,其中“ partita”(意大利语中的比赛)由team1和team2(在我的代码“ casa”和“ trasferta”中)组成?我该怎么办?

我尝试了此操作,但它抛出:找不到页面,没有FantaSquadra匹配给定的查询。

views.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)

models.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_fantasquadra

class 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 个答案:

答案 0 :(得分:3)

首先(部分无关,但并非完全无关),您不应在此处使用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实例的trafertaPartita属性(并且不保存)。这也是没有用的,因为Django查询集已经提供了一种创建(真正创建)新记录的方法,该记录非常令人惊讶地命名为'create()`:

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

关于收到的错误消息:creaP()方法是一个实例方法,因此应该在实例上调用它(在这种情况下,Python会自动将您调用该方法的实例传递为)。第一个('self')参数),而不是在类上。好了,您也可以在类上调用它,但随后必须显式传递一个Partita实例-这意味着您必须首先创建一个实例。仅传递未在之前定义的名称,显然只会导致NameError。

请不要冒犯,但您似乎并不太了解自己在做什么,just try anything until it seems to work。这种编程方法是a well known antipattern,实际上是行不通的。我建议您花一些时间来学习Python(做官方教程+浏览文档)和Django(同上),这将节省您很多时间和痛苦。