pythondjango

Cannot assign "": "" must be a "User" instance


I'm making a project using the Django framework and is creating a website and is encountering this error:

Cannot assign "<User: >": "Booking.teacher" must be a "User" instance.

this is my model for User:

class User(AbstractUser):
    groups = models.ManyToManyField(
        'auth.Group',
        related_name='custom_user_set',  # Added related_name to avoid conflict
        blank=True,
    )
    user_permissions = models.ManyToManyField(
        'auth.Permission',
        related_name='custom_user_permissions_set',  # Added related_name to avoid conflict
        blank=True,
    )

    ROLE_CHOICES = [
        ('admin', 'Admin'),
        ('teacher', 'Teacher'),
        ('student', 'Student'),
    ]
    role = models.CharField(max_length=10, choices=ROLE_CHOICES)

this is my models.py for the booking:

class Booking(models.Model):
    room = models.ForeignKey(Room, on_delete=models.CASCADE)
    teacher = models.ForeignKey(User, on_delete=models.CASCADE, limit_choices_to={'role': 'teacher'})
    date = models.DateField()
    start_time = models.TimeField()
    end_time = models.TimeField()
    purpose = models.CharField(max_length=255, blank=True, null=True)

    class Meta:
        unique_together = ('room', 'date', 'start_time', 'end_time')

    def __str__(self):
        return f"{self.room.name} - {self.date} ({self.start_time} to {self.end_time})"

this is my forms.py:

class BookingForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['teacher'].queryset = User.objects.filter(groups__name='teacher')  # Filter teachers

    class Meta:
        model = Booking
        fields = ['room', 'date', 'start_time', 'end_time', 'teacher']
        widgets = {
            'date': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}),
            'start_time': forms.TimeInput(attrs={'type': 'time', 'class': 'form-control'}),  # Updated to start_time
            'end_time': forms.TimeInput(attrs={'type': 'time', 'class': 'form-control'}),  # Added end_time
            'room': forms.TextInput(attrs={'class': 'form-control'}),
            'teacher': forms.Select(attrs={'class': 'form-control'}),
        }

    def clean(self):
        cleaned_data = super().clean()
        room = cleaned_data.get('room')
        date = cleaned_data.get('date')
        start_time = cleaned_data.get('start_time')
        end_time = cleaned_data.get('end_time')


        # Check for booking conflicts
        if Booking.objects.filter(room=room, date=date, start_time=start_time, end_time=end_time).exists():

            raise ValidationError('This room is already booked for the selected date and time.')

        return cleaned_data

and this is my views:

def booking_calendar(request):
    rooms = Room.objects.all()  # Fetch all rooms for the dropdown
    bookings = Booking.objects.all()

    if request.method == 'POST':
        form = BookingForm(request.POST)
        if form.is_valid():
            booking = form.save(commit=False)
            booking.teacher = request.user if request.user.groups.filter(name='teacher').exists() else None  # Assign the current user as the teacher if they are a teacher
            if booking.teacher is None:
                messages.error(request, 'You do not have permission to create a booking as a teacher.')  # Error message


            booking.save()
            messages.success(request, 'Booking created successfully!')
            return redirect('booking_calendar')
        else:
            messages.error(request, 'There was an error in your booking. Please check the form.')

    else:
        form = BookingForm()

    return render(request, 'booking_calendar.html', {'bookings': bookings, 'form': form, 'rooms': rooms})  # Pass rooms to the template

I tested to see if the form works and reflects into the database in making a booking but there's only this error Cannot assign "<User: mhar>": "Booking.teacher" must be a "User" instance. I'm a beginner in this and is my first time seeing this error. I'm stuck in this error pls help


Solution

  • You did not install the customized User model as the default user model, so request.user is a django.contrib.auth.models.User object, whereas teacher is a my_app.models.User model, and the two are thus in conflict.

    You will need to set the AUTH_USER_MODEL setting [Django-doc] to your user model, so:

    # settings.py
    
    # …
    
    AUTH_USER_MODEL = 'my_app.User'

    with my_app the name of the app where you defined User.

    if Booking.objects.filter(room=room, date=date, start_time=start_time, end_time=end_time).exists():

    This does not check all possible conflicts. For example if there is a booking between 10AM and 13PM, and you want to book the room between 11AM and 14PM, this will not raise any validation error. You need to check with:

    if (
        Booking.objects.exclude(pk=self.instance.pk)
        .filter(
            room=room, date=date, start_time__lt=end_time, end_time__gt=start_time
        )
        .exists()
    ):
        pass

    Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation [Django-doc].