我正在尝试为我的模型进行迁移:
from django.db import models
TAKEN = (
(True, 'Yes'),
(False, 'No')
)
class Room(models.Model):
name = models.CharField(max_length=32)
number = models.IntegerField()
taken = models.BooleanField(choices=TAKEN)
description = models.CharField(max_length=128)
ROOMS_CHOICE = (Room.objects.filter(taken=False))
class Reservation(models.Model):
date = models.DateField()
hours = models.IntegerField()
choice = models.OneToOneField(Room, on_delete=models.CASCADE, choices=ROOMS_CHOICE)
Run Code Online (Sandbox Code Playgroud)
模型的表格:
from django import forms
from .models import TAKEN, ROOMS_CHOICE
class NewRoomForm(forms.Form):
name = forms.CharField(label='Name', max_length=32)
number = forms.IntegerField(label='Room Number')
taken = forms.ChoiceField(choices=TAKEN, label='Taken', widget=forms.Select)
description = forms.CharField(label='Description', widget=forms.Textarea)
class ReservationForm(forms.Form):
date = forms.DateField(label='Date', widget=forms.SelectDateWidget)
hours = forms.IntegerField(label='hours', max_value=8)
choice = forms.ChoiceField(choices=ROOMS_CHOICE, label='room', widget=forms.Select)
Run Code Online (Sandbox Code Playgroud)
当我尝试进行迁移时,会出现 ProgrammingError:
django.db.utils.ProgrammingError: (1146, "Table 'conference_room.conference_room' doesn't exist")
Run Code Online (Sandbox Code Playgroud)
我尝试制作一个视图,用户可以从可用房间(未占用的房间 - 采取=假)预订会议室。我假设我在构建 OneToOne 关系和基于 Room 模型编写选择时犯了一些错误,这就是错误出现的原因。如何重写我的模型和表单?
这里面确实存在不少问题。
导致您出现问题的实际上不是您的 OneToOneField,而是在 ROOMS_CHOICE 的定义中您在模块级别进行查询的事实 - 因此它将在首次导入模型文件时执行,然后迁移有机会运行. 这种事情需要在一个方法中完成,在这种情况下可能__init__是表单的(如果你根本不需要它,你不需要 - 见下文)。
然而,还有几个问题。首先,您不应该使用 OneToOne;这意味着一个房间只能有一个预订,这显然不是这种情况。您需要一个外键,它是一对多的关系。
然后,您不应在此处使用 ChoiceField。Django 包含一个用于从模型中获取选择的字段:它称为 ModelChoiceField,它需要一个查询集:
choice = forms.ModelChoiceField(queryset=Room.objects.filter(taken=False), label='room', widget=forms.Select)
Run Code Online (Sandbox Code Playgroud)
所以你实际上根本不需要定义 ROOMS_CHOICE。
(我还要指出,taken在 Room 上设置一个字段也没有意义;一个房间只在特定时间被占用。您实际上需要查询在预订日期/时间未预订的房间,在用户实际选择该日期之前您不能这样做。)