Roman
Roman

Reputation: 37

Storing user's IP address in django's database on POST requests

Trying to store user's IP address when he's sending POST requests via submitting my form, tried more than a few suggestions on getting the IP address, but didn't manage to make it work properly as I always get null values stored for the IP in the database table.

I tried using model forms and setting the ip address as a variable inside the form so I can store it more easily into the database using request.META.get, and x_forwarded_for to get the actual address from the request in views.py. My app built as below:

models.py:

class RequestPull(models.Model):
    a =  models.CharField(max_length=10)
    b =  models.CharField(max_length=10)
    ip_address = models.GenericIPAddressField(null=True)

forms.py:

class GetReq(forms.ModelForm):
    class Meta:
        model = RequestPull
            fields = ['a','b','ip_address']

views.py (one of the attempts that give the same result- null values in the database):

def get_client_ip(request):
    remote_address = request.META.get('HTTP_X_FORWARDED_FOR') or request.META.get('REMOTE_ADDR')
    ip = remote_address
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        proxies = x_forwarded_for.split(',')
        while (len(proxies) > 0 and proxies[0].startswith(PRIVATE_IPS_PREFIX)):
            proxies.pop(0)
            if len(proxies) > 0:
                ip = proxies[0]
                print"IP Address",ip
        return ip


def reqPull(request):
    if request.method == 'GET':
        form = GetReq()
    else:
        form = GetReq(request.POST)
        if form.is_valid():
            form.ip_address = get_client_ip(request)
            form.save()

Expected result is an IP address of the user, as one of the values of the form, to be stored in the database. Actual result, as said earlier, is valid values for every field in the form but the ip address, which always stored as null.

Edit. Managed to make it work properly by changing views.py from.

if form.is_valid():
    form.ip_address = get_client_ip(request)
    form.save()

to.

if form.is_valid():
    obj = form.save(commit=False)
    obj.ip_address = get_client_ip(request)
    obj.save()

and by editing the input field in my template.

Upvotes: 1

Views: 4481

Answers (2)

nasser
nasser

Reputation: 5

Your return ip statement is indented too far out. Take it back 4 spaces, this should give you your ip addresses. Python function returns None when no explicit return statement is given or hit during code execution. Indent according to this:

def get_client_ip(request):
    remote_address = request.META.get('HTTP_X_FORWARDED_FOR') or request.META.get('REMOTE_ADDR')
    ip = remote_address
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        proxies = x_forwarded_for.split(',')
        while (len(proxies) > 0 and proxies[0].startswith(PRIVATE_IPS_PREFIX)):
            proxies.pop(0)
            if len(proxies) > 0:
                ip = proxies[0]
                print"IP Address",ip
    return ip

Upvotes: 0

Roman
Roman

Reputation: 37

Managed to make it work properly by changing views.py from.

if form.is_valid():
    form.ip_address = get_client_ip(request)
    form.save()

to.

if form.is_valid():
    obj = form.save(commit=False)
    obj.ip_address = get_client_ip(request)
    obj.save()

and by editing the input field in my template.

For others who may read this, you should also take note of Kevin's comment, and exclude the ip_address field out of the form entirely instead of using hidden input in the template.

Upvotes: 1

Related Questions