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)
Вернуться на верх