HELP! Choices field not rendering in HTML page

I have a model with 3 Charfields with choices, I am struggling to render the choices in my html page. On the html page, I had a card color coded between 3 colors. Instead of rendering based on selected choice in the backend, it renders the same results across different vin searches.

Here is the model in model.py

class VehicleStatus(models.Model):
    """
    Represents the status of a vehicle, including accident history, odometer fraud, and theft involvement.
    """
    ACCIDENT_HISTORY = [
        ("NHA","No History of Accidents"),
        ("OIIA", "Once Involved In Accident"),
        ("CAD", "Currently Accident Damaged"),
    ]

    ODOMETER_FRAUD = [
        ("NOF", "No Odometer Fraud"),
        ("SOF",  "Suspected Odometer Fraud"),
    ]

    THEFT_INVOLVEMENT = [
        ("NHT", "No History of Theft"),
        ("OIT",  "Once Involved In Theft"),
        ("STI", "Suspected Theft Involvement"),
    ]

    vin_number = models.OneToOneField(Vin, on_delete=models.CASCADE, related_name='vehiclestatus', db_index=True, help_text="Vehicle Identification Number")
    accident_history = models.CharField(max_length=30, choices=ACCIDENT_HISTORY, default='NHA', help_text="History of accidents involving the vehicle")
    odometer_fraud = models.CharField(max_length=30, choices=ODOMETER_FRAUD, default='NOF', help_text="Indicates if the vehicle has suspected odometer fraud")
    theft_involvement = models.CharField(max_length=30, choices=THEFT_INVOLVEMENT, default='NHT', help_text="Indicates if the vehicle has been involved in theft")
    owner_history = models.IntegerField(help_text="Number of previous owners of the vehicle", default=0)
    
    
    def __str__(self):
        return f"Vehicle Status for VIN {self.vin_number}"

    class Meta:
        verbose_name = "Vehicle Status"
        verbose_name_plural = "Vehicle Statuses"

Here is the view that handles the rendering everything to the search.html

def search(request):
    # Retrieve the VIN number from the GET request
    vin = request.GET.get('vin_number')
    vehicle = None
    specs = None
    inspections = []
    history_records = []
    vehicle_status = []
    message = None

    if vin:
        try:
            # Query the Vin model
            vehicle = get_object_or_404(Vin, vin_number=vin)

            # Retrieve related model data
            specs = getattr(vehicle, 'specs', None)
            inspections = vehicle.inspections.all()
            history_records = vehicle.history.all()
            vehicle_status = vehicle.history.all()

        except Vin.DoesNotExist:
            # If no vehicle is found, set a message
            message = "No vehicle found with the provided VIN number."
        except Exception as e:
            # Handle other potential errors
            message = f"An error occurred: {str(e)}"
    else:
        # If the form is not filled, set a message
        message = "Please enter a VIN number to search."

    # Render the template with the data and message
    return render(request, 'autohistory/search.html', {
        'vehicle': vehicle,
        'specs': specs,
        'inspections': inspections,
        'history_records': history_records,
        'vehicle_status': vehicle_status,
        'message': message,
    })

Here is the html code for one the choices field

 <!-- Accident History Card -->
                                      <div class="col-md-4 mb-3">
                                          <div class="card 
                                              {% if vehicle_status.accident_history == 'NHA' %}bg-success text-white
                                              {% elif vehicle_status.accident_history == 'OIIA' %}bg-warning text-dark
                                              {% else%}bg-danger text-white{% endif %}">
                                              <div class="card-header">
                                                  <h5 class="card-title mb-0">
                                                      <i class="fas fa-car-crash me-2"></i>
                                                      Accident History
                                                  </h5>
                                              </div>
                                              <div class="card-body">
                                                  <p class="card-text">
                                                      <strong>Status:</strong> {{ vehicle_status.get_accident_history_display }}
                                                  </p>
                                                  <p class="card-text small">
                                                      {% if vehicle_status.accident_history == 'NHA' %}
                                                          This vehicle has no history of accidents.
                                                      {% elif vehicle_status.accident_history == 'OIIA' %}
                                                          This vehicle was involved in an accident once.
                                                      {% else %}
                                                          This vehicle is currently damaged due to an accident.
                                                      {% endif %}
                                                  </p>
                                              </div>
                                          </div>
                                      </div>

There are a couple things.

  • Your view references a Vin model, but you haven’t posted that here. That prevents us from understanding the relationship between Vin and VehicleStatus

  • You’re populating two variables for your context with the same data - this doesn’t seem like it would be what you’re intending:

Does vehicle_status come from Vin.history?

If so, then vehicle_status is a queryset and not an individual object, which means that your reference to vehicle_status.accident_history would not be correct. You would need to iterate over vehicle_status for each instance to get the accident_history for that instance.

Here is the Vin model below. The Vehicle Status model has a one to one relationship with the Vin model. Using the view, it allows us to create a search from so we query the database using the Vin number which is connected to the vehicle status and other models.

The vin model:

# Vin model
class Vin(models.Model):
    vin_number = models.CharField(max_length=20, default=None, unique= True)

    def __str__(self):
        return self.vin_number

In your view, vehicle is an instance of Vin.

What is the history attribute that you are referring to in this code?

Its from a history model I think. Any suggestions on how I can better retrieve the model data in the views?

class History(models.Model):
    vin_number = models.ForeignKey('Vin', on_delete=models.CASCADE,related_name='history', verbose_name='VIN Number')
    date_of_service = models.DateField(verbose_name='Service Date', default="", blank=True)
    vehicle_service = models.BooleanField(verbose_name='Is it planned service', default='Any',)
    next_vehicle_service = models.DateField(verbose_name='Next Service Due', default="", blank=True) 
    mileage_at_service = models.IntegerField(validators=[MinValueValidator(0)], verbose_name='Mileage at Service')
    worked_performed = models.CharField(max_length=200, verbose_name='Work Performed')
    performed_by = models.CharField(max_length=50, verbose_name='Service Provider')
    cost = models.DecimalField(max_digits=8, decimal_places=2, 
        validators=[MinValueValidator(0)], verbose_name='Service Cost')
    notes = models.TextField( max_length=2000, blank=True, verbose_name='Additional Notes')

    def __str__(self):  # Changed from __int__ to __str__
        return f"{self.vin_number} - {self.date_of_service}"

    class Meta:
        ordering = ['-date_of_service']  # New: Most recent services first
        verbose_name = 'Service History'
        verbose_name_plural = 'Service Histories'

But I’m not seeing where there’s any relationship between this history and the vehicle status.

As I pointed out in my first reply, this doesn’t seem like the right reference.

I think the issue is here but I have no clue how to fix it. I am still a beginner trying to understand how Django retrieve the data. I tried to us use

vehicle_status = vehicle.vehicle_status.all() 

to retrieve the data but does not work

The reference through a OneToOne relationship is not a queryset, it’s a direct reference to the related object.

Review the docs at One-to-one relationships | Django documentation | Django

Given an instance of Vin named vehicle, and the definition in VehicleStatus:

vin_number = models.OneToOneField(Vin, on_delete=models.CASCADE, related_name='vehiclestatus', db_index=True, help_text="Vehicle Identification Number")
                                                                               ^^^^^^^^^^^^^

then vehicle.vehiclestatus is the reference to the related VehicleStatus.

I finally got it to work and yes @KenWhitesell it was on how I retrieved the data VehicleStatus model. I added the vehicle_status and set it to None. In the if statement, I used the vehicle_status = getattr(vehicle, 'vehiclestatus', None) to retrieve the data. I also organised the code the same as in the if statement/ where its retrieved above on the return render

'vehicle': vehicle,
       'specs': specs,
       'vehicle_status': vehicle_status,
       'inspections': inspections,
       'history_records': history_records,
       'error_message': error_message,

Here is the full search view

def search(request):
    vin = request.GET.get('vin_number')
    vehicle = None
    specs = None
    inspections = []
    history_records = []
    vehicle_status = None
    error_message = None

    if vin:
        try:
            vehicle = Vin.objects.get(vin_number=vin)

            # Retrieve related model data safely
            specs = getattr(vehicle, 'specs', None)
            vehicle_status = getattr(vehicle, 'vehiclestatus', None)
            inspections = vehicle.inspections.all()
            history_records = vehicle.history.all()
        except Vin.DoesNotExist:
            error_message = f"No vehicle found with VIN: {vin}"
    
    return render(request, 'autohistory/search.html', {
        'vehicle': vehicle,
        'specs': specs,
        'vehicle_status': vehicle_status,
        'inspections': inspections,
        'history_records': history_records,
        'error_message': error_message,
    })