使用ModelMultipleChoiceField保存时发生ValueError

时间:2019-01-18 21:52:27

标签: python django django-forms

我正在写一个旅馆预订系统。我有一个名为“ 预订”的模型。我可以创建一个包含开始日期,结束日期的预订,预订一个房间并分配1位客人。但是,当我修改模型,表单和视图以保存1个以上的房间和客人时,我开始遇到ValueError。

我收到的错误是:

ValueError at /reservation/new
Cannot assign "<QuerySet [<Guest: Ringo Star>]>": "Reservation.fk_guest" must be a "Guest" instance.

我知道我需要分配一个Guest实例,但是我不知道如何。

models.py

class Property(models.Model):
    name = models.CharField(max_length=30)
    address = models.CharField(max_length=50, blank=True)
    city = models.CharField(max_length=50, blank=True)
    state = models.CharField(max_length=2, choices=STATE_CHOICES, default='NY', blank=True)
    zip = models.CharField(max_length=5, blank=True)
    description = models.CharField(max_length=255, blank=True)

    class Meta:
        verbose_name = "Property"
        verbose_name_plural = "Properties"

    def __str__(self):
        return f"{self.name}"


class Room(models.Model):
    name = models.CharField(max_length=25)
    number = models.IntegerField(blank=True)
    fk_Property = models.ForeignKey(Property, on_delete=models.CASCADE)

    class Meta:
        verbose_name = "Room"
        verbose_name_plural = "Rooms"

    def __str__(self):
        return f"{self.name} in {self.fk_Property}"


class Guest(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    address = models.CharField(max_length=50, blank=True)
    city = models.CharField(max_length=50, blank=True)
    state = models.CharField(max_length=2, choices=STATE_CHOICES, default='NY', blank=True)
    zip = models.CharField(max_length=5, blank=True)
    phone = models.CharField(max_length=10, blank=True)
    email = models.CharField(max_length=50, blank=True)
    dob = models.DateField(null=True)

    class Meta:
        verbose_name = "Guest"
        verbose_name_plural = "Guests"

    def __str__(self):
        return f"{self.first_name} {self.last_name}"


class Reservation(models.Model):
    date_start = models.DateField()
    date_end = models.DateField()
    fk_guest = models.ForeignKey(Guest, on_delete=models.CASCADE)
    fk_room = models.ForeignKey(Room, on_delete=models.CASCADE)
    created_date = models.DateField(auto_now_add=True)
    modified_date = models.DateField(auto_now=True)
    # created_by = models.ForeignKey(Guest, on_delete=models.CASCADE)
    # modified_by = models.ForeignKey(Guest, on_delete=models.CASCADE)

    class Meta:
        verbose_name = "Reservation"
        verbose_name_plural = "Reservations"

    def __str__(self):
        return f"{self.date_start} to {self.date_end} reserved by {self.fk_guest} in {self.fk_room}"

forms.py

import datetime

from django import forms
from django.forms import ModelForm
# from django.forms.extras.widgets import SelectDateWidget

from .models import Guest, Reservation, Room


class GuestForm(forms.ModelForm):
    class Meta:
        model = Guest
        fields = {'first_name', 'last_name', 'address',
              'city', 'state', 'zip', 'phone', 'email', 'dob'}


class NewReservationsForm(forms.ModelForm):
    # date_start = forms.DateField(label='Start Date', widget=SelectDateWidget)
    # date_end = forms.DateField(label='End Date', widget=SelectDateWidget)
    date_start = forms.DateField(label='Start Date')
    date_end = forms.DateField(label='End Date')
    fk_guest = forms.ModelMultipleChoiceField(label="Guest(s)", queryset=Guest.objects.all())
    fk_room = forms.ModelMultipleChoiceField(label="Room(s)", queryset=Room.objects.all())

    class Meta:
        model = Reservation
        fields = ['date_start', 'date_end', 'fk_guest', 'fk_room']

views.py

@login_required
def reservation_new(request):
    if request.method == 'POST':
        # TODO Create ability to select multiple rooms and multiple guests.
        form = NewReservationsForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('reserve:reservation_list')
        else:
            return HttpResponse("New Registration form failed validation!", form)
else:
    form = NewReservationsForm()
    context = {
        "form": form,
    }
    return render(request, 'reserve/reservation_new.html', context)

1 个答案:

答案 0 :(得分:0)

问题是Reservation.fk_guestRervation.fk_room是外键,当它们需要为ManyToManyField时。那应该使您对开发工作不感兴趣。

class Reservation(models.Model):
    guests = models.ManyToManyField(Guest, on_delete=models.CASCADE)
    rooms = models.ManyToManyField(Room, on_delete=models.CASCADE)