اذهب إلى المحتوى

السؤال

نشر

أنا أستخدم الكائن GeoIP لكي أحصل على عنوان IP الخاص بالمستخدم في ملف العرض view التالي:

from django.contrib.gis.utils import GeoIP
from django.shortcuts import render_to_response


def details(request):
  geoip = GeoIP()
  lat, long = geoip.lat_lon(request.META['REMOTE_ADDR'])
  return render_to_response('My_Details.html', locals())

لكن المشكلة أنه يظهر لي الخطأ التالي:

KeyError at /mypage/
    'REMOTE_ADDR'
    Request Method: GET
    Request URL:    http://localhost:8000/mypage/
    Django Version: 1.2.4
    Exception Type: KeyError
    Exception Value:    
    'REMOTE_ADDR'
    Exception Location: /mysite/details/views.py in home, line 9
    Python Executable:  /usr/bin/python
    Python Version: 2.7
    Python Path:    ['/mysite', '/usr/local/lib/python2.7/dist-packages/flup-1.0.2-py2.6.egg', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-linux2', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/pymodules/python2.7']
    Server time:    Thu, 2 Aug 2021 20:42:50 +0200

أعتقد أن الخطأ بسبب المفتاح REMOTE_ADDR، ولكن لا أعرف كيفية إصلاح هذا الخطأ.

أستخدم جانغو Django الإصدار 1.2.4 وبايثون 2.7

Recommended Posts

  • 1
نشر

يمكنك أن تقوم بعمل دالة تقوم بإرجاع عنوان IP ، كالتالي:

def getClientIP(request):
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    # في حالة وجود العنصر HTTP_X_FORWARDED_FOR سوف يحتوي على عنوان IP في بدايته
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[0]
    else:
        ip = request.META.get('REMOTE_ADDR')
    return ip

لاحظ كيف تم إستخدام التابع get حتى تحتدث مشكلة في حالة عدم وجود المفتاح REMOTE_ADDR (سوف يتم إرجاع None في هذه الحالة).

كما يجب أن تتأكد من إعدادات reverse proxy بشكل صحيح (إن وجد)، على سبيل المثال: تثبيت mod_rpaf  لخادم الويب Apache.

ملاحظة: يحتوي العنصر X-Forwarded-For على عنوان IP في بدايته في أغلب الأحيان، ولكن في أحيان أخرى مثل في خوادم Heroku يتم وضع عنوان IP في نهايته، أي أنك يجب أن تستخدم -1 بدلًا من 0، كالتالي:

def getClientIP(request):
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    # في حالة وجود العنصر HTTP_X_FORWARDED_FOR سوف يحتوي على عنوان IP في بدايته
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[-1].strip()
    else:
        ip = request.META.get('REMOTE_ADDR')
    return ip

الآن يمكنك أن تستعمل الدالة كالتالي:

client_ip = getClientIP(request)

كما يمكنك أن تستعمل حزمة جاهزة للحصول على عنوان IP مثل حزمة django-ipware، أولًا يجب تثبيتها من خلال أحد الطرق التالية:

1. easy_install django-ipware

2. pip install django-ipware

3. git clone http://github.com/un33k/django-ipware
    a. cd django-ipware
    b. run python setup.py install

4. wget https://github.com/un33k/django-ipware/zipball/master
    a. unzip the downloaded file
    b. cd into django-ipware-* directory
    c. run python setup.py install

ويتم إستعمال الحزمة كالتالي:

# في ملف عرض view أو middleware حيث يكون الكائن `request` متاحًا

from ipware import get_client_ip

ip, is_routable = get_client_ip(request)
if ip is None:
    # تعذر الحصول على عنوان IP الخاص بالعميل
    pass
else:
    # في حالة وجود عنوان IP
    print(ip)

 

  • 0
نشر

إجابة سامح رائعة كالعادة.. وبالنسبة لإجابته الأولى أيضاً يمكننا أن نضيف تحسين عليها. بدلاً من أخذ أول IP في قائمة X_FORWARDED_FOR ، أخذ أول واحد ليس في عنوان IP داخلي معروف، حيث أن بعض أجهزة التوجيه لا تحترم البروتوكول، ويمكنك رؤية ips الداخلية باعتبارها القيمة الأولى في القائمة:

PRIVATE_IPS_PREFIX = ('10.', '172.', '192.', )

def get_client_ip(request):
	#request العميل من ال ip الحصول على  
    remote_address = request.META.get('REMOTE_ADDR')
    #None إذا كانت متوفرةوإلا   REMOTE_ADDR  لتكون  ip  تعيين القيمة الافتراضية للـ
    ip = remote_address
    #HTTP_X_FORWARDED_FOR من private ليس بروكسي وليس ip حاول الحصول على أول عنوان
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        proxies = x_forwarded_for.split(',')
        #الخاص  ips   إزالة ال
        while (len(proxies) > 0 and
                proxies[0].startswith(PRIVATE_IPS_PREFIX)):
            proxies.pop(0)
        #الأول الذي ليس خاصاً (من البروكسي)  ip أخذ عنوان
        if len(proxies) > 0:
            ip = proxies[0]
    return ip

 

  • 0
نشر

أحياناً عند  التعامل مع proxies يعيدون أحياناً ip متعددة  في HTTP_X_FORWARDED_FOR ولذلك للحصول على ال ip الحقيقي سيكون آخر ip في ال list لذلك سينستخدم إجابة سامح مع تعديل بسيط كالتالي 

def get_client_ip(request):
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[-1].strip()
    else:
        ip = request.META.get('REMOTE_ADDR')
    return ip

 

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...