Storing HTTP_X_FORWARDED_FOR in Django
I occasionally get a
ProgrammingError: value too long for type character(15)
when people post to my blog. There aren't any fields in my model declared to have a max_length of 15 so I was always a little confused and in almost all cases, it was a spammer anyway so never took the time to investigate further.
But then someone just emailed me and told me they were getting a 500 when posting a comment to my blog. So I decided to investigate and that's where it started getting interesting...
./manage.py sql leonardo
revealed no sign of a field of length 15 either. So I went into the DB (in my case PostgreSQL)'s shell.
author_ipaddress | character(15)
Like many blogs, I capture the IP address of the commenter so I can block spam.
In my model I have:
author_ipaddress = models.IPAddressField(null=True)
Which Django's ORM translates to:
"author_ipaddress" inet NULL
which PostgreSQL is obviously storing as a character(15).
Why would an IP Address be more than 15 characters, though?
Well, I went back to the error log and noticed this:
'HTTP_X_FORWARDED_FOR': '192.168.0.127, 126.96.36.199',
(note: I changed the second address to protect the original poster)
You see, because the Apache instance running django is behind another webserver (on the same machine), I can't rely on REMOTE_ADDR because it's always 127.0.0.1. So I log HTTP_X_FORWARDED_FOR.
What I didn't realise until now is that HTTP_X_FORWARDED_FOR can be a list.
I guess the best solution is to just change the field to a CharField.
Other Djangonauts who are logging HTTP_X_FORWARDED_FOR might want to heed this warning: don't use IPAddressField.