Как вернуть отдельное, связанное значение из формы Django?

#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 часов…