我正在尝试创建“ 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
答案 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
实例的traferta
和Partita
属性(并且不保存)。这也是没有用的,因为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(同上),这将节省您很多时间和痛苦。