#python #django #forms #django-forms #modelform
Вопрос:
Я работаю над простой системой планирования встреч, в которой клиенты могут привести свой автомобиль для обслуживания. Клиенты могут иметь несколько транспортных средств и иметь логин со всей сохраненной информацией о своем транспортном средстве. Большинство клиентов отслеживают свой автомобиль по номеру «единицы».
Когда они заполняют форму, они выбирают филиал (сервисный центр), в котором они хотят выполнить работу, дату, временной интервал, и они выбирают свое транспортное средство на основе номера единицы. На задней панели устройство и VIN связаны вместе. Однако в настоящее время, когда они отправляют запрос на обслуживание, проходит только их номер подразделения. Мне нужно, чтобы соответствующий VIN проходил автоматически.
Я пытался вернуть отдельные значения из модели транспортного средства (я не могу этого понять), я пытался вернуть их с помощью f’, но это возвращает его в виде одной строки с единицей измерения и VIN вместе. Я потратил, наверное, 3-4 часа, пытаясь разобраться в этом. Любая помощь будет признательна!!
Models.py
class Vehicle(models.Model): unit = models.CharField(max_length=10, help_text="Unit number for the vehicle") vin = models.CharField(max_length=17, unique=True, validators=[MinLengthValidator(17)], help_text="VIN of the vehicle") engine = models.ForeignKey(Engine, on_delete=models.SET_NULL, null=True) engineMfg = models.ForeignKey(engineMfg, on_delete=models.SET_NULL, null=True) sold_to = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True) mileage = models.IntegerField(default=0, help_text="Mileage of the vehicle") class Meta: ordering= ['unit', 'vin'] permissions = ( ('view_all_vehicles', "View All Vehicles"), # this is only a permission to do something, it does NOT change a book state ) def __str__(self): #return f'{self.unit} - {self.vin}' #return self.vin return self.unit class Appointment(models.Model): class Meta: unique_together = ('branch', 'date', 'timeslot') Timeslot_List = ( (0, '07:00 - 09:00'), (1, '09:00 - 11:00'), (2, '13:00 - 15:00'), (3, '15:00 - 17:00'), (4, '17:00 - 19:00'), ) Booking_Status = ( ('a', "Available"), ('b', "Booked"), ('r', "Requested") ) status = models.CharField( max_length=1, choices=Booking_Status, blank=True, default='a', help_text="Booking Availability", ) branch = models.ForeignKey('Branch', on_delete=models.SET_NULL, null=True) unit = models.ForeignKey(Vehicle, related_name='UNIT', on_delete=models.SET_NULL, null=True) vin = models.ForeignKey(Vehicle, related_name='VIN', on_delete=models.SET_NULL, null=True) date = models.DateField(help_text="MM-DD-YY") timeslot = models.IntegerField(choices=Timeslot_List) sold_to = models.ForeignKey(User, on_delete=models.SET_NULL, null=True) def __str__(self): return str(self.sold_to) @property def time(self): return self.Timeslot_List[self.timeslot][1]
Views.py
def new_appointment(request): if request.method == 'POST': form = AppointmentForm(user=request.user, data=request.POST) if form.is_valid(): appt = form.save(commit=False) appt.sold_to = request.user appt.status = 'r' appt.save() return redirect('/') else: form = AppointmentForm(user=request.user) return render(request, 'catalog/appointment_form.html', {'form':form})
Forms.py
class AppointmentForm(forms.ModelForm): class Meta: model = Appointment timeslot = Appointment.objects.filter(status__exact='b') #unit = Vehicle.unit exclude = ('status', 'sold_to', 'vin') widgets = { 'date': DateTimeWidget( attrs={'id': 'date'}, usel10n=True, bootstrap_version=5, options={ 'minView': 2, # month view 'maxView': 3, # year view 'weekStart': 1, 'todayHighlight': True, 'format': 'mm-dd-yy', 'daysOfWeekDisabled': [0,6], 'startDate': date.today().strftime('%Y-%m-%d'), } ), } def clean_date(self): day = self.cleaned_data['date'] if day lt;= date.today(): raise forms.ValidationError("Date should be in the future", code='invalid') if day.isoweekday() in (0,6): raise forms.ValidationError("Must be scheduled on a weekday", code='invalid') return day def __init__(self, **kwargs): sold_to = kwargs.pop('user') super(AppointmentForm, self).__init__(**kwargs) self.fields['unit'].queryset = Vehicle.objects.filter(sold_to=sold_to)
Редактировать: Я также пробовал ниже, но python кричит на меня, что по какой-то причине это запрещено…
unit = models.ForeignKey(Vehicle.unit, on_delete=models.SET_NULL, null=True) vin = models.ForeignKey(Vehicle.vin, on_delete=models.SET_NULL, null=True)
Edit2: Если изменить следующее в представлениях, я подхожу очень близко, но получаю ошибку ниже.
def new_appointment(request): if request.method == 'POST': form = AppointmentForm(user=request.user, data=request.POST) if form.is_valid(): appt = form.save(commit=False) appt.sold_to = request.user appt.vin = appt.unit.vin # lt;--- addition of this line appt.status = 'r' appt.save() return redirect('/')
Ошибка, которую я получаю от добавления строки выше:
Cannot assign "'1XPTD4EXOCD128815'": "Appointment.vin" must be a "Vehicle" instance.
Ответ №1:
ПОНЯЛ, ПОНЯЛ, ПОНЯЛ!!!!!
Мне пришлось установить общее поле CharField в классе назначения:
class Appointment(models.Model): ... vin = models.CharField(max_length=17) ...
Это в сочетании с изменением взглядов, как обсуждалось в правке 2 выше:
def new_appointment(request): ... appt.vin = appt.unit.vin # lt;---- This line here ...
Заставил все работать так, как я хотел!
Сегодня это заняло всего 8 часов…