Django: उपयोगकर्ता लॉग इन करते समय संकेत?


83

मेरे Django ऐप में, जब उपयोगकर्ता लॉग इन करता है और उपयोगकर्ता लॉग आउट होने पर उन्हें चलाना बंद कर देता है, तो मुझे कुछ आवधिक पृष्ठभूमि वाले काम शुरू करने की आवश्यकता होती है, इसलिए मैं एक सुरुचिपूर्ण तरीके की तलाश कर रहा हूं

  1. एक उपयोगकर्ता लॉगिन / लॉगआउट के बारे में सूचित करें
  2. क्वेरी उपयोगकर्ता लॉगिन स्थिति

मेरे दृष्टिकोण से, आदर्श समाधान होगा

  1. प्रत्येक द्वारा भेजा गया एक संकेत django.contrib.auth.views.loginऔर... views.logout
  2. एक विधि django.contrib.auth.models.User.is_logged_in(), के अनुरूप ... User.is_active()या... User.is_authenticated()

Django 1.1.1 के पास ऐसा नहीं है और मैं स्रोत को पैच करने और इसे जोड़ने के लिए अनिच्छुक हूं (यह सुनिश्चित नहीं है कि यह कैसे करना है, वैसे भी)।

एक अस्थायी समाधान के रूप में, मैंने एक is_logged_inबूलियन फ़ील्ड को UserProfile मॉडल में जोड़ा है जो डिफ़ॉल्ट रूप से साफ़ हो जाता है, पहली बार उपयोगकर्ता द्वारा लैंडिंग पृष्ठ को हिट किया जाता है (द्वारा परिभाषित)LOGIN_REDIRECT_URL = '/' ) सेट और बाद के अनुरोधों में क्वियर किया जाता है। मैंने इसे UserProfile में जोड़ा है, इसलिए मुझे केवल उस उद्देश्य के लिए अंतर्निहित उपयोगकर्ता मॉडल से व्युत्पन्न और अनुकूलित करने की आवश्यकता नहीं है।

मुझे यह समाधान पसंद नहीं है। यदि उपयोगकर्ता ने लॉगआउट बटन को स्पष्ट रूप से क्लिक किया है, तो मैं ध्वज को साफ़ कर सकता हूं, लेकिन अधिकांश समय, उपयोगकर्ता केवल पृष्ठ छोड़ देते हैं या ब्राउज़र को बंद कर देते हैं; इन मामलों में झंडा साफ करना मेरे लिए सीधे तौर पर उचित नहीं है। इसके अलावा (कि बल्कि डेटा मॉडल स्पष्टता nitpicking, हालांकि), is_logged_inUserProfile में नहीं है, लेकिन उपयोगकर्ता मॉडल में है।

क्या कोई वैकल्पिक तरीकों के बारे में सोच सकता है?


4
कृपया एक नया उत्तर चुनने पर विचार करें। वर्तमान में स्वीकृत एक 1.3 में जोड़े गए सिग्नल के प्रकाश में बहुत खराब विकल्प है।
ब्रायसन

1
आप सही हे; स्वीकृत उत्तर को बदल दिया।
ssc

जवाबों:


153

आप इस तरह से एक संकेत का उपयोग कर सकते हैं (मैं मॉडल थिंकपैड में मेरा डाल दो)

from django.contrib.auth.signals import user_logged_in


def do_stuff(sender, user, request, **kwargs):
    whatever...

user_logged_in.connect(do_stuff)

Django डॉक्स देखें: https://docs.djangoproject.com/en/dev/ref/contrib/auth/#module-django.contrib.auth.signals और यहाँ http://docs.djangoproject.com/en/dev/ विषयों / संकेत /


8
अब जब कि Django 1.3 प्रस्तावों इन संकेतों, यह एक है बहुत लॉगिन / लॉगआउट करने के लिए कॉल लपेटकर की तुलना में बेहतर समाधान। इसका मतलब यह भी है कि यदि आप लॉग-इन के नए तरीके सेट करते हैं - उदाहरण के लिए, फेसबुक / ट्विटर / ओपनआईडी लॉगिन - वे अभी भी काम करेंगे।
जॉर्डन रीटर

9
बल्कि तब डाल दिया कि models.pyइसके बजाय मैं कोड signals.pyऔर ऑटो आयात कर मॉड्यूल की __init__.pyफ़ाइल में रखने का सुझाव देता हूं ।
डैनियल सोकोलोस्की

लॉगिन और लॉगआउट पर जावास्क्रिप्ट चलाने के लिए इस सिग्नल का उपयोग कैसे करें?
आशीष गुप्ता

16

@PhoebeB उत्तर के अलावा: आप @receiverइस तरह से डेकोरेटर का उपयोग कर सकते हैं :

from django.contrib.auth.signals import user_logged_in
from django.dispatch import receiver

@receiver(user_logged_in)
def post_login(sender, user, request, **kwargs):
    ...do your stuff..

और यदि आप इसे signals.pyअपने ऐप में डालते हैं , तो इसे इसमें जोड़ें apps.py:

class AppNameConfig(AppConfig):
    ...
    def ready(self):
        import app_name.signals

13

एक विकल्प Django के लॉगिन / लॉगआउट विचारों को अपने साथ लपेटने का हो सकता है। उदाहरण के लिए:

from django.contrib.auth.views import login, logout

def my_login(request, *args, **kwargs):
    response = login(request, *args, **kwargs)
    #fire a signal, or equivalent
    return response

def my_logout(request, *args, **kwargs):
    #fire a signal, or equivalent
    return logout(request, *args, **kwargs)

फिर आप Django के, और वॉइला के बजाय अपने कोड में इन दृश्यों का उपयोग करते हैं।

यदि आपके पास अनुरोध वस्तु तक पहुंच है, तो लॉगिन स्थिति के संबंध में यह बहुत सरल है; केवल यह देखने के लिए कि वे एक पंजीकृत उपयोगकर्ता या अनाम उपयोगकर्ता और बिंगो हैं, अनुरोध के उपयोगकर्ता विशेषता की जाँच करें। Django प्रलेखन उद्धृत करने के लिए :

if request.user.is_authenticated():
    # Do something for logged-in users.
else:
    # Do something for anonymous users.

यदि आपके पास अनुरोध ऑब्जेक्ट तक पहुंच नहीं है, तो यह निर्धारित करना कि वर्तमान उपयोगकर्ता लॉग इन है, मुश्किल हो रहा है।

संपादित करें:

दुर्भाग्य से, आप कभी User.is_logged_in()कार्यक्षमता प्राप्त नहीं कर पाएंगे - यह HTTP प्रोटोकॉल की एक सीमा है। यदि आप कुछ धारणाएँ बनाते हैं, हालाँकि, आप जो चाहते हैं, उसके करीब पहुँच सकते हैं।

सबसे पहले, आप उस कार्यक्षमता को क्यों नहीं प्राप्त कर सकते हैं? ठीक है, आप किसी को ब्राउज़र बंद करने, या किसी नए को लाने से पहले एक पृष्ठ पर कुछ समय बिताने के बीच का अंतर नहीं बता सकते। HTTP पर बताने का कोई तरीका नहीं है जब कोई वास्तव में साइट छोड़ देता है या ब्राउज़र को बंद कर देता है।

इसलिए आपके पास दो विकल्प हैं जो सही नहीं हैं:

  1. unloadजब उपयोगकर्ता पृष्ठ छोड़ रहा हो, तो उसे पकड़ने के लिए जावास्क्रिप्ट इवेंट का उपयोग करें । आपको यह सुनिश्चित करने के लिए कुछ सावधानीपूर्वक तर्क लिखना होगा कि आप किसी उपयोगकर्ता को लॉग आउट नहीं कर रहे हैं जब वे अभी भी आपकी साइट पर नेविगेट कर रहे हैं ।
  2. जब भी कोई उपयोगकर्ता लॉग इन करे, तो लॉगआउट सिग्नल को आग लगा दें। एक क्रॉन जॉब भी बनाएं जो समाप्त हो चुके सत्रों को समाप्त करने के लिए अक्सर चलता है - जब एक समाप्त सत्र हटा दिया जाता है, तो जांचें कि सत्र के उपयोगकर्ता (यदि यह अनाम नहीं है) में अधिक सक्रिय सत्र नहीं हैं, तो उस स्थिति में आप लॉगआउट सिग्नल को आग लगाते हैं।

ये समाधान गन्दे हैं और आदर्श नहीं हैं, लेकिन वे सबसे अच्छे हैं जो आप कर सकते हैं, दुर्भाग्य से।


यह अभी भी "अधिकांश समय, उपयोगकर्ताओं को केवल पृष्ठ छोड़ने या ब्राउज़र को बंद करने की स्थिति" को संबोधित नहीं करता है।
जोएल एल

आपके उत्तर के लिए धन्यवाद, निश्चित रूप से लॉगिन / लॉगआउट लपेटने से मुझे स्रोत को पैच करने से बचाता है, हालांकि खुद के पास होना चाहिए। थोड़ा सुधार, यद्यपि: यदि लॉगिन को कॉल करने से पहले my_login में सिग्नल भेजा जाता है, तो उपयोगकर्ता सिग्नल हैंडलर में अभी भी गुमनाम है। बेहतर (यह मत सोचो कि इसे ठीक से स्वरूपित किया जाएगा): my_login (अनुरोध) को परिभाषित करें: प्रतिक्रिया = लॉगिन (अनुरोध) #fire एक संकेत, या समकक्ष वापसी प्रतिक्रिया इसके अलावा, मैं पहले से ही is_authenticated का उपयोग कर रहा हूं, मुझे बस एक महसूस हो रहा था कि मुझे आवश्यकता होगी उस से भी अधिक। अब तक, हालांकि, डेटा मॉडल में मेरा नया is_logged_in टुकड़ा अप्रयुक्त है।
ssc

चारों तरफ अच्छे अंक। मुझे लगता है कि मैंने वास्तव में is_logged_inसामान को बहुत अच्छी तरह से संबोधित नहीं किया था (क्षमा याचना, मुझे लगता है कि मैंने पोस्ट को पढ़ने का एक बड़ा काम नहीं किया है), लेकिन मैंने उस क्षेत्र में क्या मदद की पेशकश करने के लिए उत्तर को अपडेट किया है। । यह एक असंभव समस्या का एक सा है, दुर्भाग्य से।
ShZ

3

इसके लिए एक त्वरित समाधान होगा, आपके ऐप के _ _ init _ _.py में निम्न कोड रखें:

from django.contrib.auth.signals import user_logged_in
from django.dispatch import receiver


@receiver(user_logged_in)
def on_login(sender, user, request, **kwargs):
    print('User just logged in....')

1

एकमात्र विश्वसनीय तरीका (जो यह भी पता लगाता है कि उपयोगकर्ता ने ब्राउज़र को कब बंद किया है) last_requestहर बार किसी क्षेत्र को अपडेट करने के लिए उपयोगकर्ता किसी पृष्ठ को लोड करता है।

यदि आपके पास एक पेज खुला है, तो आप एक आवधिक AJAX अनुरोध भी कर सकते हैं जो सर्वर को हर मिनट में पिंग करता है।

फिर एक एकल पृष्ठभूमि का काम करें जो हाल के उपयोगकर्ताओं की एक सूची प्राप्त करें, उनके लिए नौकरियां बनाएं और उन सूची में मौजूद नहीं होने वाले उपयोगकर्ताओं के लिए नौकरियों को साफ़ करें।


यह मापने का सबसे अच्छा तरीका है कि कोई उपयोगकर्ता लॉग इन है या नहीं। आपको मूल रूप से लॉग-इन उपयोगकर्ताओं का एक रोस्टर रखना होगा और यह जांचना होगा कि उनकी अंतिम पहुंच क्या थी और एक टाइमआउट पर निर्णय लें। यदि आप टाइमआउट को 10 मिनट की तरह सेट करते हैं, और फिर प्रत्येक वेबपेज पर हर 5 मिनट में एक अजाक्स अनुरोध भी होता है, जबकि कोई पृष्ठ सक्रिय होता है, तो स्थिति को अद्यतित रखना चाहिए।
जॉर्डन रेइटर

1

लॉगआउट का संदर्भ देते हुए, जैसा कि उनके द्वारा स्पष्ट रूप से एक बटन पर क्लिक करने का विरोध किया गया है (जो कोई भी नहीं करता है), का अर्थ है निष्क्रिय समय की मात्रा को चुनना जो "लॉग आउट" के बराबर है। phpMyAdmin 15 मिनट के डिफ़ॉल्ट का उपयोग करता है, कुछ बैंकिंग साइटें 5 मिनट के रूप में कम उपयोग करती हैं।

इसे लागू करने का सबसे सरल तरीका कुकी-आजीवन को बदलना होगा। आप इसे निर्दिष्ट करके अपनी पूरी साइट के लिए कर सकते हैं settings.SESSION_COOKIE_AGE। वैकल्पिक रूप से, आप इसका उपयोग करके प्रति-उपयोगकर्ता के आधार पर (मानदंड के कुछ मनमाने सेट के आधार पर) बदल सकते हैं HttpResponse.setcookie()। आप अपना स्वयं का संस्करण बनाकर render_to_response()और प्रत्येक प्रतिक्रिया पर आजीवन इसे सेट करके इस कोड को केंद्रीकृत कर सकते हैं ।


0

किसी न किसी विचार - आप इसके लिए मिडलवेयर का उपयोग कर सकते हैं। जब संबंधित URL अनुरोध किया जाता है तो यह मिडलवेयर अनुरोधों और फायर सिग्नल को संसाधित कर सकता है। यह भी प्रतिक्रियाओं और आग संकेत प्रक्रिया कर सकता है जब कार्रवाई वास्तव में दी गई।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.