কোড চালাবেন যখন জ্যাঙ্গো কেবলমাত্র একবার শুরু করবেন?


177

আমি একটি জাঙ্গো মিডলওয়্যার ক্লাস লিখছি যা আমি আরম্ভ করার সময় একবারেই কার্যকর করতে চাই এবং অন্য কিছু আরব্রিট্রি কোড শুরু করতে চাই। আমি খুব সুন্দর সমাধান sdolan পোস্ট করেছে অনুসরণ করেছেন এখানে কিন্তু "হ্যালো" বার্তা টার্মিনালে আউটপুট দুইবার । যেমন

from django.core.exceptions import MiddlewareNotUsed
from django.conf import settings

class StartupMiddleware(object):
    def __init__(self):
        print "Hello world"
        raise MiddlewareNotUsed('Startup complete')

এবং আমার জ্যাঙ্গো সেটিংস ফাইলে, আমি ক্লাসটি তালিকায় অন্তর্ভুক্ত করেছি MIDDLEWARE_CLASSES

তবে যখন আমি রান্সারভার ব্যবহার করে জ্যাঙ্গো চালাই এবং একটি পৃষ্ঠার অনুরোধ করি, আমি টার্মিনালে আসি

Django version 1.3, using settings 'config.server'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
Hello world
[22/Jul/2011 15:54:36] "GET / HTTP/1.1" 200 698
Hello world
[22/Jul/2011 15:54:36] "GET /static/css/base.css HTTP/1.1" 200 0

কোনও ধারণা কেন "হ্যালো ওয়ার্ল্ড" দু'বার ছাপা হয়? ধন্যবাদ।


1
শুধু কৌতূহলের জন্য, আপনি কী অনুভব করেছিলেন যে init .pi কোডটি কেন দুবার কার্যকর করা হয়?
মিউট্যান্ট

3
@ মিউট্যান্ট এটি কেবল রানসরভারের অধীনে দু'বার সম্পাদিত হবে ... এর কারণ এটি হ'ল রানসরভার অ্যাপ্লিকেশনগুলি পরিদর্শন করার জন্য প্রথমে লোড করে এবং পরে সার্ভারটি শুরু করে। এমনকি চালকটির অটোরলোডের পরেও কোডটি একবারে কার্যকর করা হয়।
পাইকলার

1
বাহ আমি এখানে এসেছি .... সুতরাং @ পাইক্লারের মন্তব্যের জন্য আপনাকে আবারও ধন্যবাদ, আমি এটাই ভাবছিলাম।
ওয়েস্টার্নগান

উত্তর:


112

নীচে পাইকলারের উত্তর থেকে আপডেট: জ্যাঙ্গো 1.7 এর এখন এই সম্পর্কে একটি হুক রয়েছে


এইভাবে করবেন না।

ওয়ান-টাইম স্টার্টআপ জিনিসের জন্য আপনি "মিডলওয়্যার" চান না।

আপনি শীর্ষ স্তরের কোডটি কার্যকর করতে চান urls.py। সেই মডিউলটি একবার আমদানি করা হয় এবং কার্যকর করা হয়।

urls.py

from django.confs.urls.defaults import *
from my_app import one_time_startup

urlpatterns = ...

one_time_startup()

1
@ আন্ড্রেই: ম্যানেজমেন্ট কমান্ডগুলি সম্পূর্ণ পৃথক সমস্যা। সমস্ত পরিচালনা কমান্ডের আগে বিশেষ ওয়ান-টাইম স্টার্টআপের ধারণাটি বোঝা শক্ত। আপনাকে নির্দিষ্ট কিছু সরবরাহ করতে হবে । সম্ভবত অন্য প্রশ্নে।
এস .লট

1
Url.py এ সাধারণ পাঠ্য প্রিন্ট করার চেষ্টা করা হয়েছিল, কিন্তু কোনও আউটপুট ছিল না। কি হচ্ছে ?
স্টিভ কে

8
ইউআরএল.পি কোডটি কেবল প্রথম অনুরোধেই কার্যকর করা হয় (অনুমান করুন এটি @ স্টেভেকের প্রশ্নের উত্তর দেয়) (
জানাগো

4
এটি প্রতিটি কর্মীর জন্য একবার মৃত্যুদন্ড কার্যকর করে, আমার ক্ষেত্রে এটি মোট 3 বার কার্যকর করা হয়।
রাফেল

9
@ হালিলপাজারলাম এই উত্তরটি পুরানো - আপনি পাইক্লারের কাছ থেকে উত্তরটি ব্যবহার করা উচিত।
মার্ক চ্যাকারিয়ান

271

আপডেট: জাজানো 1.7 এখন একটি হুক

ফাইল: myapp/apps.py

from django.apps import AppConfig
class MyAppConfig(AppConfig):
    name = 'myapp'
    verbose_name = "My Application"
    def ready(self):
        pass # startup code here

ফাইল: myapp/__init__.py

default_app_config = 'myapp.apps.MyAppConfig'

জ্যাঙ্গোর জন্য <1.7

এক নম্বর উত্তরটি আর কাজ করবে বলে মনে হচ্ছে না, প্রথম অনুরোধের পরে urls.py লোড করা হয়েছে।

কি ইদানীং কাজ করেছে আপনার INSTALLED_APPS কোন এক সূচনার কোড করা হয় Init .py যেমনmyapp/__init__.py

def startup():
    pass # load a big thing

startup()

ব্যবহার করার সময় ./manage.py runserver... এটি দু'বার কার্যকর করা হবে, তবে এটি কারণ কারণ চালকরা মডেলগুলিকে প্রথমে বৈধ করার জন্য কিছু কৌশল আছে ইত্যাদি ... সাধারণ মোতায়েন বা এমনকি যখন চালক অটো পুনরায় লোড হয়, এটি কেবল একবার কার্যকর করা হয়।


4
আমি মনে করি যে প্রকল্পটি লোড করে এমন প্রতিটি প্রক্রিয়ার জন্য এটি কার্যকর করা হয়। সুতরাং, কেন এটি কোনও স্থাপনার দৃশ্যে সঠিকভাবে কাজ করবে না তা আমি ভাবতে পারি না। এটি পরিচালনা আদেশের জন্য কাজ করে। +1
স্কাইলার সেভল্যান্ড

2
আমি বুঝতে পারি যে সার্ভারটি শুরু হওয়ার সাথে সাথে এই সমাধানটি কিছু স্বেচ্ছাসেবক কোড কার্যকর করতে ব্যবহার করা যেতে পারে তবে লোড হবে এমন কিছু ডেটা ভাগ করা কি সম্ভব ? উদাহরণস্বরূপ, আমি এমন একটি বস্তু লোড করতে চাই যাতে একটি বিশাল ম্যাট্রিক্স থাকে, এই ম্যাট্রিক্সটি একটি ভেরিয়েবলের মধ্যে রেখে এবং এটি একটি ওয়েব এপিআইয়ের মাধ্যমে ব্যবহার করতে পারি, প্রতিটি অনুরোধে একজন ব্যবহারকারী করতে পারে। এ জাতীয় জিনিস কি সম্ভব?
প্যাট্রিক

2
ডকুমেন্টেশন বলছে এটি কোনও ডাটাবেস ইন্টারঅ্যাকশন করার জায়গা নয়। এটি প্রচুর কোডের জন্য অনুপযুক্ত করে তোলে। এই কোডটি কোথায় যেতে পারে?
চিহ্নিত করুন

3
সম্পাদনা: একটি সম্ভাব্য হ্যাক হ'ল কমান্ড লাইনগুলির যে কোনও আর্গুমেন্ট পরীক্ষা করা (এক্সের জন্য 'sys.argv এ x' ['মেকিমেগ্রেশনস', 'মাইগ্রেট']])
কনচিলেক্ল্যাটার

2
যদি আপনার স্ক্রিপ্টটি দু'বার চলতে থাকে তবে আপনি এই উত্তরটি দেখুন: stackoverflow.com/a/28504072/5443056
ব্র্যাডেন হল্ট

37

এই প্রশ্নটি জঙ্গো প্রকল্পগুলির জন্য ব্লগ পোস্ট এন্ট্রি পয়েন্ট হুকে ভাল উত্তর পেয়েছে , যা জাঙ্গো> = 1.4 এর জন্য কাজ করবে।

মূলত, আপনি এটি করতে ব্যবহার করতে পারেন <project>/wsgi.py, এবং সার্ভারটি শুরু হওয়ার পরে এটি কেবল একবার চালানো হবে, তবে আপনি যখন কমান্ডগুলি চালাবেন না বা কোনও নির্দিষ্ট মডিউল আমদানি করবেন তখন নয়।

import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{ project_name }}.settings")

# Run startup code!
....

from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()

আবার এই মন্তব্যটি কোডটি একবারে কার্যকর করবে তা নিশ্চিত করতে একটি মন্তব্য যুক্ত করুন। কোনও লক ব্যবস্থাপনার দরকার নেই।
ATOzTOA

স্ক্রিপ্টগুলি এখানে সংযোজন করা হয়েছে যখন মনে হয় পরীক্ষার কাঠামো শুরু হয় তখন সম্পাদিত হয় না
লুইসু

এই উত্তরটি কেবল কার্যকর হয়নি এমন সমাধানগুলির জন্য আড়াই দিনের সন্ধান শেষ করে।
নীল মুনরো

3
নোট করুন যে ওয়েবসাইটে যখন প্রথম অনুরোধ করা হয় তখন এটি কার্যকর করা হয়, আপনি যখন আপাচি শুরু করবেন না।
ব্যবহারকারী984003

18

যদি এটি পাইক্লারের উত্তর ছাড়াও কাউকে সহায়তা করে তবে "--noreload" বিকল্প রানারভারকে স্টার্টআপে দু'বার কমান্ড চালানো থেকে বিরত রাখবে:

python manage.py runserver --noreload

তবে এই কমান্ডটি অন্যান্য কোডের পরিবর্তনের পরে রানসারভার পুনরায় লোড করবে না।


1
ধন্যবাদ এটি আমার সমস্যার সমাধান! আমি আশা করি যখন আমি স্থাপন করি যখন এটি ঘটে না
গাবো

2
একটি বিকল্প হিসাবে, আপনি বিষয়বস্তুর পরীক্ষা করতে পারবেন os.environ.get('RUN_MAIN')একমাত্র আপনার কোড চালানো মূল প্রক্রিয়া একবার (দেখুন stackoverflow.com/a/28504072 )
bdoering

হ্যাঁ, এই প্লাস পাইক্লারের উত্তরটি আমার পক্ষেও কাজ করেছিল, কারণ এটি একাধিক ready(self)কলগুলিকে কেবল একবারই চালু করতে সক্ষম হয়েছিল। চিয়ার্স!
ডার্কসিগনাস

জ্যাঙ্গো runserverডিফল্টরূপে পৃথক (পৃথক) পিড সংখ্যা সহ দুটি প্রক্রিয়া শুরু করে। --noreloadএটি একটি প্রক্রিয়া শুরু করে তোলে।
ইউজিন গ্র। ফিলিপভ

15

@ পাইক্লারের পরামর্শ অনুসারে, জ্যাঙ্গো ১.++ তে আপনাকে তার উত্তরে বর্ণিত হুক ব্যবহার করা উচিত, তবে আপনি যদি চান যে আপনার ফাংশনটি কেবল তখনই চালিত হয় যখন রান সার্ভার বলা হয় (এবং যখন মাইগ্রেশন, মাইগ্রেট, শেল ইত্যাদি করা হয় না) ), এবং আপনি নীচে অ্যাপ্লিকেশনজিট্র নোট রেডি ব্যতিক্রমগুলি এড়াতে চান :

ফাইল: myapp/apps.py

import sys
from django.apps import AppConfig

class MyAppConfig(AppConfig):
    name = 'my_app'

    def ready(self):
        if 'runserver' not in sys.argv:
            return True
        # you must import your modules here 
        # to avoid AppRegistryNotReady exception 
        from .models import MyModel 
        # startup code here

12
এটি কি প্রোডাকশন মোডে চলে? আফাইক মোডে কোনও "রানসরভার" শুরু হয়নি।
নারদোক

এর জন্য ধন্যবাদ! আমি উন্নত পাইথন নির্ধারণকারী আমার app এর মধ্যে এবং আমি যখন manage.py কমান্ড চলমান নির্ধারণকারী চালানোর জন্য চায়নি।
lukik

4

নোট করুন যে আপনি নির্ভরযোগ্যতা ডাটাবেসের সাথে সংযোগ করতে পারবেন না বা AppConfig.readyফাংশনের অভ্যন্তরে মডেলগুলির সাথে ইন্টারঅ্যাক্ট করতে পারবেন না ( ডক্সে সতর্কতাটি দেখুন )।

আপনার যদি আপনার স্টার্ট-আপ কোডে ডাটাবেসটির সাথে ইন্টারঅ্যাক্ট করতে হয় তবে একটি সম্ভাবনা হ'ল connection_createdডাটাবেসের সংযোগের পরে সূচনা কোডটি কার্যকর করতে সিগন্যালটি ব্যবহার করা ।

from django.dispatch import receiver
from django.db.backends.signals import connection_created

@receiver(connection_created)
def my_receiver(connection, **kwargs):
    with connection.cursor() as cursor:
        # do something to the database

স্পষ্টতই, এই সমাধানটি প্রতিটি ডাটাবেস সংযোগে একবার চলমান কোডের জন্য, প্রতি প্রকল্পের জন্য একবার নয়। সুতরাং আপনি CONN_MAX_AGEসেটিংটির জন্য একটি বোধগম্য মান চাইবেন যাতে আপনি প্রতিটি অনুরোধে আরম্ভের কোডটি পুনরায় চালাচ্ছেন না। এছাড়াও লক্ষ্য করুন যে বিকাশ সার্ভার উপেক্ষা করেCONN_MAX_AGE , সুতরাং আপনি একবার বিকাশের অনুরোধ অনুযায়ী কোডটি চালাবেন।

99% সময় এটি একটি খারাপ ধারণা - ডাটাবেস সূচনা কোডটি মাইগ্রেশনে যেতে হবে - তবে এমন কিছু ব্যবহারের ক্ষেত্রে রয়েছে যেখানে আপনি দেরী আরম্ভ করতে পারবেন না এবং উপরের ক্যাভেটগুলি গ্রহণযোগ্য।


2
আপনার স্টার্টআপ কোডে ডাটাবেস অ্যাক্সেস করতে হলে এটি একটি ভাল সমাধান। একটি সরল পদ্ধতি এটা শুধুমাত্র একবার চালানোর আছে হয় পেতে my_receiverথেকে নিজেকে বিচ্ছিন্ন ফাংশন connection_createdসংকেত, নির্দিষ্টভাবে নিচের টি যোগ my_receiverফাংশন: connection_created.disconnect(my_receiver)
অ্যালান

1

আপনি যখন সার্ভার চালানোর সময় একবার "হ্যালো ওয়ার্ল্ড" মুদ্রণ করতে চান, প্রার্ট ("হ্যালো ওয়ার্ল্ড") স্টার্টআপমিটওয়ালার বাইরে রেখে দিন

from django.core.exceptions import MiddlewareNotUsed
from django.conf import settings

class StartupMiddleware(object):
    def __init__(self):
        #print "Hello world"
        raise MiddlewareNotUsed('Startup complete')

print "Hello world"

3
হাই অস্কার! সুতরাং, আমরা পছন্দ করি যে উত্তরগুলি কেবল কোড নয়, ইংরেজিতে একটি ব্যাখ্যা অন্তর্ভুক্ত করে। আপনি কীভাবে / কেন আপনার কোডটি সমস্যার সমাধান করে তার একটি সংক্ষিপ্ত ব্যাখ্যা দিতে পারেন?
ম্যাক্স ভন হিপ্পেল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.