Django ValueError: Невозможно присвоить "<SimpleLazyObject: <CustomUser: >>": "Booking.user" должен быть экземпляром "Customer".
Цель проста: Я создаю платформу для аренды автомобилей, где клиенты могут разместить заказ на автомобиль. Простой "заказ" содержит автомобиль, начальную и конечную даты. Форма должна автоматически сохранять аутентифицированного пользователя как создателя.
В нем используется CreateView с таким кодом:
class BookingCreate(CreateView):
model = Booking
fields = ['car', 'start_date', 'end_date']
permission_classes = [permissions.IsAuthenticated]
def form_valid(self, form):
form.instance.user = self.request.user
return super().form_valid(form)
Форма работает нормально, но при отправке выдает такую ошибку:
ValueError at /rentals/booking/create Невозможно присвоить "<SimpleLazyObject: <CustomUser: Test2 Two>>": "Booking.user" должен быть экземпляром "Customer".
Я просмотрел предыдущие ответы, и лучшее решение было найдено в этой теме, которая рекомендовала использовать этот код вместо этого
def form_valid(self, form):
form.instance.user = Booking.objects.get(user=self.request.user)
return super().form_valid(form)
Однако, это изменение возвращает немного другую ошибку:
Ошибка значения в /rentals/booking/create Невозможно выполнить запрос "Test2 Two": Должен быть экземпляр "Customer". У меня есть модель customUser и модель "customer", которая наследуется от нее.
.
Для дополнительного контекста я использую модель customUser. Поскольку у меня есть несколько типов пользователей (в частности, владельцы и клиенты автомобилей), я использую специальную таблицу с булевыми полями, чтобы отметить каждый тип как True на основе регистрационной формы, которую они используют, согласно этому учебнику this.
Вот соответствующий код (его много, поэтому я добавил только нужные части):
models.py
from accounts.models import CustomUser
class User(CustomUser):
is_customer = models.BooleanField(default=False)
is_owner = models.BooleanField(default=False)
class Owner(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
def __str__(self):
return self.user.first_name
class Customer(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
cars = models.ManyToManyField('Car', blank=True)
...
def get_absolute_url(self):
return reverse('rental:customer-detail', args=[str(self.id)])
def __str__(self):
return f'{ self.user.first_name } { self.user.last_name }'
class Booking(models.Model):
"""Stores the bookings, for example when it was made, the booking date, and the car ID."""
# Unique ID for this booking.
id = models.UUIDField(primary_key=True, default=uuid.uuid4, help_text="Automatically generated unique ID. Do not change.")
user = models.ForeignKey('Customer', on_delete=models.SET_NULL, null=True)
car = models.ForeignKey(Car, on_delete=models.SET_NULL, null=True)
start_date = models.DateField(default=timezone.now)
end_date = models.DateField(null=True)
...
Ваш self.request.user (или пользователь, под которым вы вошли в систему), похоже, является экземпляром CustomUser, но вы пытаетесь присвоить экземпляр User объекту Booking. Хотя он имеет те же поля (поскольку наследуется от класса CustomUser), он является другим объектом.
Я думаю, вы хотите сделать CustomUser абстрактной моделью? Вы должны добавить abstract к классу CustomUser. См: https://docs.djangoproject.com/en/4.1/topics/db/models/#abstract-base-classes
class Meta:
abstract = True
Тогда вам также нужно выбрать правильную модель пользователя в настройках, например: AUTH_USER_MODEL = 'users.User', например
https://docs.djangoproject.com/en/4.1/topics/auth/customizing/#substituting-a-custom-user-model
Также во втором варианте вы назначаете Booking вместо связанного пользователя. Сделайте следующее:
def form_valid(self, form):
form.instance.user = Booking.objects.get(user=self.request.user).user
return super().form_valid(form)
Я бы рекомендовал вам использовать get_object_or_404()
, и вам нужно назначить user
, а не Booking
экземпляр так:
def form_valid(self, form):
form.instance.user=get_object_or_404(Booking,user=self.request.user).user
return super().form_valid(form)