Django,获取IP位置

30

我希望通过检测用户IP地址来将我的用户重定向到网站的特定位置区域。

在 Django 1.1.1 下,最好的实现方式是什么?

谢谢。

编辑:我想要基于欧洲的城市进行定位。


你想如何区分用户?基于国家?大陆?所说的语言?等等? - Nick Presta
7个回答

38

GeoDjango 看起来适合您的需求。我不确定您想如何引导用户,但是使用GeoIP API,您可以这样做:

from django.contrib.gis.utils import GeoIP
g = GeoIP()
ip = request.META.get('REMOTE_ADDR', None)
if ip:
    city = g.city(ip)['city']
else:
    city = 'Rome' # default city

# proceed with city

文档详细地解释了一切;我建议您花些时间仔细阅读。


2
2015年,仍然是Geoip跟踪的最佳选择吗? - Coderaemon
7
自Django 1.9起,此方法已被弃用,请改用GeoIP2(https://docs.djangoproject.com/en/1.10/ref/contrib/gis/geoip2/)。 - Jordan Dimov

25

虽然已经提到了GeoIP,但我发现pygeoip更容易安装,如果你想将其嵌入应用程序而不是安装在Python的site-packages中,它就是最佳选择。尽管如此,它仍能与免费的MaxMind数据库(例如GeoLite City)完美配合使用。

使用示例(与GeoIP几乎相同):

>>> import pygeoip
>>> gi = pygeoip.GeoIP(GEOIP_DATABASE, pygeoip.GEOIP_STANDARD)
>>> gi.record_by_addr(ip)
{'country': '...', 'country_code': '...', ...}

这对于Windows非常实用。强烈推荐。 - cheenbabes
免费下载MaxMind遗留数据库:国家城市 - Dennis Golomazov
1
pygeoip现在已经被弃用。 - Salvioner

3
这是一个解决方案,来自DjangoSnippets;顺便说一句,不确定为什么下面的代码没有使用urlparse;但这可以修复 :-)
(看了其他答案,似乎你有很多选择。这个选项可能不被首选,因为它依赖于一个免费的第三方服务。)
from urllib2 import urlopen, Request
import re, socket
from django.conf import settings

domain_re = re.compile('^(http|https):\/\/?([^\/]+)')
domain = domain_re.match(settings.SITE_URL).group(2)

def getUserCountry(ip):
    url = "http://api.wipmania.com/" + ip + "?" + domain
    socket.setdefaulttimeout(5)
    headers = {'Typ':'django','Ver':'1.1.1','Connection':'Close'}
    try:
        req = Request(url, None, headers)
        urlfile = urlopen(req)
        land = urlfile.read()
        urlfile.close()
        return land[:2]
    except Exception:
        return "XX"

来自WIPmania的说明:如果您每个日历日少于10,000个请求,那么使用API是免费的,无论是个人还是商业用途。这是一个简单而强大的API,允许您通过单个链接查询WorldIP数据库。

3
你可以在某个地方维护一个已知IP地址的缓存,这样每当有人访问你的网站时就不必每次都向WIPmania请求了。 - Saulius Žemaitaitis
如何将用户的“位置”保存在“数据库”中? - Lars

1

基于一些免费服务。

虽然速度不快,但您可以添加更多的免费服务:

设置:

IPCOUNTRY_APYKEY = [
{# free tier 2 querys per second
    "url": "http://api.ipinfodb.com/v3/ip-country/?ip={ip}&key={key}&format=json",
    "params": {
        "key": "*****************************",
    },
    "fieldname": "countryCode",
}, 
{# free tier 150 querys per minute and https is not suported in free tier
    "url": "http://ip-api.com/json/{ip}?fields=2",
    "params": {},
    "fieldname": "countryCode",
}, 
{# free tier 1.500 queries per day
    "url": "https://api.ipdata.co/{ip}?api-key={key}",
    "params": {
        "key": "*****************************",
    },
    "fieldname": "country_code",
}, 
{# free tier 10.000 queries per month and https is not suported in free tier
    "url": "http://api.ipstack.com/{ip}?access_key={key}",
    "params": {
        "key": "*****************************",
    },
    "fieldname": "country_code",
},
{# free tier 10.000 queries per month and https is not suported in free tier
    "url": "http://api.ipapi.com/{ip}?access_key={key}",
    "params": {
        "key": "*****************************",
    },
    "fieldname": "country_code",
},

]

代码:

import json
import urllib3

from django.conf import settings

for service in settings.IPCOUNTRY_APYKEY:
    url = service["url"].format(ip=ip,**service["params"])
    headers = {'Type': 'django', 'Ver': '1.1.1', 'Connection': 'Close'}
    urllib3.disable_warnings()
    http_call = urllib3.PoolManager()
    try:
        r = http_call.request('GET', url, headers=headers, timeout=1.0)
        if r.status == 200:
            json_response = json.loads(r.data.decode("utf-8"))
            print(json_response[service["fieldname"]])
    except Exception as e:
        pass
    
return None

1
你可以创建一个视图,获取用户的IP地址,然后发出HTTP重定向命令,让他们的浏览器加载你想要的页面。
def redirect_based_on_ip(request):
    ip = request.meta['REMOTE_ADDR']
    if ip == SOMETHING:
        return HttpResponseRedirect('/something')
    elif ip == SOMETHING_ELSE:
        return HttpResponseRedirect('/something_else')
    # ...

如果你想测试一个IP地址是否在特定的块中,那么使用Python的SubnetTree库可能会很有帮助。

0

您可以通过使用IP2Location Python库和IP2Location BIN数据库来实现此目的。首先,从https://www.ip2location.com/database/ip2location购买商业IP2Location数据库或从https://lite.ip2location.com/下载免费的IP2Location LITE数据库。然后,使用以下命令安装IP2Location Python库:pip install IP2Location

安装完成后,打开您的views.py文件并将以下代码添加到文件中:

from django.http import HttpResponse
from django.shortcuts import redirect
import IP2Location

database = IP2Location.IP2Location(YOUR_DATABASE_PATH)

def get_client_ip(request):
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[0]
    else:
        ip = request.META.get('REMOTE_ADDR')
    if ip == '127.0.0.1': # Only define the IP if you are testing on localhost.
        ip = '8.8.8.8'
    return ip

def redirect_view(request):
    ip = get_client_ip(request)
    rec = database.get_all(ip)
    if rec.city == 'London': # Or any other city name
        response = redirect('PATH_REDIRECT_TO')
        return response

def redirectsucess_view(request):
    return HttpResponse('Welcome!')

接下来,打开 urls.py 文件,在 urlpatterns 列表中添加以下代码:

path('redirect/', views.redirect_view),
path('PATH_REDIRECT_TO/', views.redirectsucess_view)

0

我已经制作了一个SO 答案,其中我使用了Cloudflare CDN,他们提供了每个访问者的GEO位置的额外头部信息。优点是我们不需要安装任何外部库或进行任何API调用。重定向可以通过Django中间件实现。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接