Django ORM not seeing a new field

Hi,

I have 2 websites (one is a form, the other accesses the form data, displays it for other purposes).

Recently, I Added a postal code field (postalcode) in the form. Did a makemigrations and migrate as usual. In the DB, the new field is there and when the form saves, the postal code saves as expected. So, it’s not a typo or some obvious mistake like that.

But, when I’m in the other website and try to access the form data, every field is accessible but not the new one, postal code. When I try to force it on VSCode (doesn’t see it), it triggers an error ‘this object doesn’t have a postalcode attribute.’

When I use the python shell in the form website, I see the postalcode field.

Any idea what could cause this ?

Thanks.

Welcome @st-cen !

In order to try and help you with this, we’ll need to see the code involved. This would be the models, forms, and views involved in the pages you are viewing.

Note: When posting code (or templates, error messages, tracebacks, etc), enclose the code between lines of three backtick - ` characters. This means you’ll have a line of ```, then your code, then another line of ```. This forces the forum software to keep your code properly formatted.

Hi Ken,

This is the model where I added the postalcode field
form/models.py

class ReservationForm(models.Model):
    station = models.IntegerField(verbose_name="Station ID", null=True, blank=True)
    group_date_arrival = models.DateTimeField()
    group_date_departure = models.DateTimeField()
    reason_of_stay = models.CharField(max_length=200, blank=True, null=True)
    person_firstname = models.CharField(max_length=100, blank=False, null=False)
    person_lastname = models.CharField(max_length=100, blank=False, null=False)
    person_email = models.EmailField(max_length=100, blank=False, null=False)
    person_phone = models.CharField(max_length=50, blank=False, null=False)
    organization = models.CharField(max_length=100, blank=False, null=False)
    billing_address = models.CharField(max_length=100, blank=False, null=False)
    city = models.CharField(max_length=75, blank=False, null=False)
    province = models.IntegerField(verbose_name="Province ID", null=True, blank=True)
    postalcode = models.CharField(max_length=20, null=True, blank=True)
    language_preference = models.CharField(max_length=25, blank=False, null=False)
    project_number = models.CharField(max_length=50, blank=True, null=True)
    diatery_notes = models.TextField(max_length=200, blank=True, null=True)
    general_notes = models.TextField(max_length=200, blank=True, null=True)
    has_been_imported = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)

This is the form that is working well. It saves all the data as expected.
form/forms.py

class SimpleForm(forms.ModelForm):
    province = forms.ChoiceField(choices=[])  # Initialize empty, will populate in __init__
    station = forms.ChoiceField(choices=[])   # Initialize empty for station

    group_date_arrival = forms.DateTimeField(
        widget=DateInput(attrs={'class': 'datepicker'}),  # Use class to initialize jQuery datepicker
        required=True,
        error_messages={'required': 'Obligatoire / Required'}
    )
    group_date_departure = forms.DateTimeField(
        widget=DateInput(attrs={'class': 'datepicker'}),
        required=True,
        error_messages={'required': 'Obligatoire / Required'}
    )

    class Meta:
        model = ReservationForm
        fields = ['group_date_arrival', 'group_date_departure', 'person_firstname', 'person_lastname', 'person_email', 'person_phone', 'organization', 'billing_address', 'city', 'province', 'station', 'reason_of_stay', 'language_preference', 'project_number', 'diatery_notes', 'general_notes', 'postalcode']

    
    def clean(self):
        cleaned_data = super().clean()
        arrival_date = cleaned_data.get('group_date_arrival')
        departure_date = cleaned_data.get('group_date_departure')

        if arrival_date and departure_date:
            if departure_date <= arrival_date:
                raise forms.ValidationError("La date de départ doit être après la date d'arrivée. / Departure date must be after arrival date.")

        return cleaned_data
    
    
    def __init__(self, *args, **kwargs):
        super(SimpleForm, self).__init__(*args, **kwargs)
        
        # Using your custom methods to fetch choices and adding the default choice
        self.fields['province'].choices = [(None, ' Choisir / Choose ')] + self.fetch_province_choices()
        self.fields['province'].error_messages.update({'required': 'Obligatoire / Required'})
        self.fields['station'].choices = [(None, ' Choisir / Choose ')] + self.fetch_station_choices()
        self.fields['station'].error_messages.update({'required': 'Obligatoire / Required'})
        # Setting the fields to required will make Django check that a valid option has been selected
        self.fields['group_date_arrival'].required = True        
        self.fields['group_date_departure'].required = True
        self.fields['person_firstname'].required = True
        self.fields['person_firstname'].error_messages.update({'required': 'Obligatoire / Required'})        
        self.fields['person_lastname'].required = True
        self.fields['person_lastname'].error_messages.update({'required': 'Obligatoire / Required'})        
        self.fields['person_email'].required = True
        self.fields['person_email'].error_messages.update({'required': 'Obligatoire / Required'})
        self.fields['person_phone'].required = True
        self.fields['person_phone'].error_messages.update({'required': 'Obligatoire / Required'})
        self.fields['organization'].required = True
        self.fields['organization'].error_messages.update({'required': 'Obligatoire / Required'})
        self.fields['postalcode'].required = True
        self.fields['postalcode'].error_messages.update({'required': 'Obligatoire / Required'})
        self.fields['billing_address'].required = True
        self.fields['billing_address'].error_messages.update({'required': 'Obligatoire / Required'})
        self.fields['city'].required = True
        self.fields['city'].error_messages.update({'required': 'Obligatoire / Required'})
        self.fields['reason_of_stay'].required = True
        self.fields['reason_of_stay'].error_messages.update({'required': 'Obligatoire / Required'})
        self.fields['language_preference'].required = True
        self.fields['language_preference'].error_messages.update({'required': 'Obligatoire / Required'})

This is the other website fetching data from the form. The line that doesn’t work properly is:
reservation = get_object_or_404(FormReservationform.objects.using(‘reservation’), pk=pk). Seems to fetch everything but the postalcode field.

using(‘reservation’) is the schema for the form DB.

other website/views.py

def reservation_detail(request, pk):
    
    try:
        # Ensure pk is an integer
        pk = int(pk)
    except ValueError:
        raise Http404("Invalid reservation ID")    
    
    reservation = get_object_or_404(FormReservationform.objects.using('reservation'), pk=pk)
    guests = FormGuests.objects.using('reservation').filter(reservation_id=pk)
       
    total_guests = guests.count()
    station = Station.objects.get(id=reservation.station)
    station_name = station.station_name_fr
    province_name = Province.objects.get(id=reservation.province).province_name_fr
    station_capacity = station.capacity

    start_date, end_date = get_reservation_dates(reservation)   
    requested_days = get_requested_days(start_date, end_date)
    months = generate_month_list(start_date, end_date)  # For regular calendar
    days_with_reservations = get_reservations_by_day(station, start_date, end_date)
    calendars, available_beds_dict = generate_calendars(months, station, start_date, end_date, guests, station_capacity, requested_days)

    # Populate days_with_reservations for each calendar month
    for calendar in calendars:
        year, month = calendar['year'], calendar['month']
        calendar['days_with_reservations'] = days_with_reservations.get((year, month), {})

    # Generate modal availability data
    modal_availability = generate_modal_availability(station, 3)

    # Calculate total requested beds
    total_requested_beds = guests.count()  # Assuming each guest requires one bed

    return render(request, 'reservations/demande_details.html', {
        'reservation': reservation,
        'station_name': station_name,
        'province_name': province_name,
        'guests': guests,
        'total_guests': total_guests,
        'calendars': calendars,
        'requested_days': requested_days,
        'available_beds_dict': available_beds_dict,
        'station_capacity': station_capacity,
        'availability': modal_availability,  # Pass the modal availability data to the template
        'total_requested_beds': total_requested_beds  # Pass the total requested beds to the template
    })

In the template, I simply display the data with reservation.field. Everything shows up but the postalcode.

Let me know if you need something else.

Thanks,

Yes, what is the FormReservationform model definition? Does it have the postalcode field defined in it?

Hi Ken,

That’s it !!
I’m a little embarassed TBH.

The ‘FormReservationform’ is an unmanaged table and completely forgot to redo inspectdb on it.

Added the postalcode and voilà!

Many thanks,