emqx / MQTT-Client-Examples

MQTT Client Examples
https://www.emqx.com
MIT License
820 stars 676 forks source link

django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet. #136

Closed 0716gzs closed 8 months ago

0716gzs commented 9 months ago

If I process the models model while subscribing to mqtt, it will result in django. core. exceptions. AppRegistryNotReady: Apps are not loaded yet

源码 mqtt.py import paho.mqtt.client as mqtt from common.ProductData.BaseData import BaseProductData from .consumer import Consumer import threading

class MQTTClient: client = mqtt.Client(protocol=3) BROKER = 'broker' KEEPALIVE = 50 USER_NAME = 'root' PASSWORD = '123' PORT = 1883

def __init__(self):
    self.broker = self.BROKER
    self.port = self.PORT
    self.keepalive = self.KEEPALIVE
    self.username = self.USER_NAME
    self.password = self.PASSWORD
    # self.connect()

def on_publish(self, client, userdata, mid):
    print("消息发送成功")

def on_log(self, client, userdata, level, buf):
    print(f"MQTT log: {buf}")

def on_subscribe(self, client, userdata, mid, granted_qos):
    print("Subscribed with QoS " + str(granted_qos[0]))

def connect(self):
    def on_connect(client, userdata, flags, rc):
        if rc == 0:
            print("Connected to MQTT Broker!")
            self.client.subscribe(BaseProductData.subscribe_topic(), qos=1)
        else:
            print("Failed to connect, return code %d\n", rc)

    self.client.on_publish = self.on_publish
    self.client.on_log = self.on_log
    self.client.on_message = Consumer.on_message
    # self.client.on_subscribe =

    if self.username and self.password:
        self.client.username_pw_set(self.username, self.password)
    self.client.on_connect = on_connect

    # self.client.connect(self.broker, self.port, self.keepalive)
    self.client.connect_async(self.broker, port=self.port, keepalive=self.keepalive, bind_address="")

def publish(self, topic, msg):
    result = self.client.publish(topic, msg, qos=1)
    status = result[0]
    if status == 0:
        print(f"Send `{msg}` to topic `{topic}`")
    else:
        print(f"Failed to send message to topic {topic}")

# def subscribe(self, topic):
#     self.client.subscribe(topic)
#     # self.client.on_message = on_message
#     self.client.loop_forever()

def disconnect(self):
    self.client.loop_stop()
    self.client.disconnect()

def send_publish(self, msg):
    def on_publish(client, userdata, mid):
        print("消息发送成功")

    self.client.loop_start()
    self.client.on_publish = on_publish

    result = self.client.publish("/topic/send_msg", msg)
    status = result[0]
    if status == 0:
        print(f"Send `{msg}` to topic `/topic/send_msg`")
    else:
        print(f"Failed to send message to topic /topic/send_msg")

client = MQTTClient() client.connect()

import json from common import const from common.views import RowDict from apps.product.models import Product, ProductUser, ProductAutomation from apps.scene.models import Scene from django.core.cache import cache

class ProductHandleClas: def init(self): pass

@classmethod
def update_date(cls, *args, **kwargs):
    kwargs = RowDict(kwargs)
    product = Product.objects.filter(id=kwargs.product_id)
    product_user = ProductUser.objects.filter(product_id=kwargs.product_id, user_id=kwargs.user_id)
    if product and product_user:
        Product.objects.filter(id=kwargs.product_id).update(status=kwargs.status)
        print("处理完成")

class SceneHandleClas:

def __init__(self):
    pass

@classmethod
def update_date(cls, *args, **kwargs):
    pass
    kwargs = RowDict(kwargs)
    key = f"{kwargs.scene_id}{kwargs.user_id}"
    # 根据场景id查询
    scene = Scene.objects.filter(id=kwargs.scene_id, user_id=kwargs.user_id)
    if not scene:
        raise
    # 根据场景id查询自动化
    pa = ProductAutomation.objects.filter(scene_id=kwargs.scene_id, product_id=kwargs.product_id, flag=const.SceneFlag.SPECIFIC).count()
    scene_product_list = json.loads(cache.get(str(key)))
    if scene_product_list and len(cache.get(str(key))) >= pa:
        pa_induction = ProductAutomation.objects.filter(scene_id=kwargs.scene_id, product_id=kwargs.product_id,
                                                        flag=const.SceneFlag.INDUCTION).prefetch_related("product").all()
        for pa in pa_induction:
            pass
    else:
        if isinstance(scene_product_list, list):
            scene_product_list.append(kwargs.product_id)
        else:
            scene_product_list = [kwargs.product_id]
    cache.set(str(key), json.dumps(scene_product_list))
    cache.expire(str(key), 300)

    if scene and pa != 0:
        cls.product(kwargs.product_id, kwargs.user_id, kwargs.status)

@classmethod
def product(cls, product_id, user_id, status):
    product = Product.objects.filter(id=product_id)
    product_user = ProductUser.objects.filter(product_id=product_id, user_id=user_id)
    if product and product_user:
        Product.objects.filter(id=product_id).update(status=status)
        print("处理完成")
        return True
    return False
zibuyu1995 commented 9 months ago

The error message django.core.exceptions.AppRegistryNotReady: Apps are not loaded yet typically occurs in Django when Django's apps are not ready, often because of an attempt to import Django models before Django has been fully initialized. This usually happens when importing Django models outside of an appropriate context, such as at the module level in scripts that are not part of the standard Django workflow (like a standalone script or in this case, an MQTT client).

To resolve this issue in the context of your MQTT client script (mqtt.py), you should consider the following steps:

  1. Delay Importing Django Models: Instead of importing Django models at the top of your MQTT script, import them inside the function or method where they are needed. This ensures that these imports happen after Django has been fully initialized.

  2. Ensure Django Setup: If the MQTT client script is a standalone script and not part of a Django management command, you need to explicitly set up Django. You can do this by adding the following lines at the beginning of your script, before importing any Django models:

    import django
    django.setup()

    This should be done after setting the DJANGO_SETTINGS_MODULE environment variable, which tells Django which settings to use.

  3. Use Django Management Command: If possible, consider converting your MQTT client script into a Django management command. This is a more integrated way to run standalone scripts that require access to Django's features, including models. Django management commands are executed in the context of the Django project, ensuring all the necessary setup is done automatically.

  4. Review Thread Safety: Since you're using threading in your MQTT client, make sure that your Django model operations are thread-safe. Django's ORM isn't inherently thread-safe, so you need to be cautious about accessing or modifying Django models from multiple threads.

By applying these changes, your MQTT client should be able to interact with Django models without encountering the AppRegistryNotReady error. This will integrate MQTT functionalities smoothly within the Django framework.