2017-10-06 12 views
1

私は、顧客が注文をした後、その店舗に別の店舗で価格を提示できるオークションシステムを開発しようとしています。チャンネルのコンシューマクラスでdjangoシグナルを使用する

このシステムの興味深い部分は、注文が最初に作成されたときに、利用可能な店舗がそれぞれのオファーを行うのに60秒かかることです。最初の店舗がオファーをしたとき、「オークション」は他の店が自分のオファーを行うのに20秒しかかかりません。彼らが別のオファーをした場合、割り当てられた時間が短くなると、この20秒がリフレッシュされます。オファーは、与えられた最初の60秒を超えることができない、十分な時間がある限り、受信され続けることができます。

class Order(models.Model): 
    customer = models.ForeignKey(Customer) 
    create_time = models.DateTimeField(auto_now_add=True) 
    update_time = models.DateTimeField(auto_now_add=True) 
    total = models.FloatField(default=0) 
    status = models.IntegerField(default=0) 
    delivery_address = models.ForeignKey(DeliveryAddress) 
    store = models.ForeignKey(Store, null=True, blank=True, related_name='orders', on_delete=models.CASCADE) 
    credit_card = models.ForeignKey(CreditCard, null=True, blank=True, related_name='orders') 

class OrderOffer(models.Model): 
    store = models.ForeignKey(Store, related_name="offers", on_delete=models.CASCADE) 
    order = models.ForeignKey(Order, related_name="offers", on_delete=models.CASCADE) 
    create_time = models.DateTimeField(auto_now_add=True) 

これらの要件に加えて、新しいオファーがリアルタイムで到着したときにクライアントを更新したいと考えています。このために、私はdjango-channels WebSocketの実装を使用しています。私は首尾よく私のクライアントとサーバー間のWebSocket通信チャネルを確立することができました

from channels.generic.websockets import WebsocketConsumer 
from threading import Timer 
from api.models import Order, OrderOffer 
from django.db.models.signals import post_save 
from django.dispatch import receiver 

class OrderConsumer(WebsocketConsumer): 

    def connect(self, message, **kwargs): 
     """ 
     Initialize objects here. 
     """ 
     order_id = int(kwargs['order_id']) 
     self.order = Order.objects.get(id=order_id) 
     self.timer = Timer(60, self.sendDone) 
     self.timer.start() 
     self.message.reply_channel.send({"accept": True}) 

    def sendDone(self): 
     self.send(text="Done") 

    # How do I bind self to onOffer? 
    @receiver(post_save, sender=OrderOffer) 
    def onOffer(self, sender, **kwargs): 
     self.send(text="Offer received!") 
     if (len(self.offers) == 0): 
      self.offerTimer = Timer(20, self.sendDone) 
      self.offers = [kwargs['instance'],] 
     else: 
      self.offerTimer = Timer(20, self.sendDone) 

     self.offers.append(kwargs['instance']) 


    def receive(self, text=None, bytes=None, **kwargs): 
     # Echo 
     self.send(text=text, bytes=bytes) 

    def disconnect(self, message, **kwargs): 
     """ 
     Perform necessary disconnect operations. 
     """ 
     pass 

は、私は次のconsumers.pyファイルを持っています。私はメッセージの送信をテストしました。今度は新しいOrderOfferの作成を検出し、クライアントに通知を送信したいと思います。このため、シグナルデコレータがこのパラメータを送信しないため、変数にアクセスして、self.sendを使用する必要があります。これは不可能です。私は自分でonOffer宣言することで、それを強制しようとしましたが、私は次のエラーを取得:私は何とかセットを知らせるキーワード引数にアクセスすることができれば

TypeError: onOffer() missing 1 required positional argument: 'self'

を、私は多分のような何か行うことができます: context = selfを。

私は、元の問題に対する助け、あるいは代替の解決策にも感謝します。 saveメソッドモデルから、この場合には - - あなたは「外」から消費者に話をしたい場合は

答えて

0

あなたはそれに話をチャネル層を使用する必要があります:http://channels.readthedocs.io/en/latest/topics/channel_layers.html

基本的に、あなたの」必要でしょう:

  • は、起動時にグループに消費者を追加するカスタムtypeで新しいOrderOfferがありますたび
  • がグループにメッセージを送信します(おそらく、そのためのIDに基づいて) - たとえば、 {"type": "order.new_offer", "order_offer_id": 45}
  • これを扱う消費者のハンドラを定義します - それはタイプ名に一致する、この場合には、それはあなたがしてソケットを下に話をするself.sendを使用(および場合は、データベースを照会することができるというハンドラでdef order_new_offer(self, event):
  • になるので、イベントメッセージに入れなかったクライアントに送信するための追加情報が必要です)。 https://github.com/andrewgodwin/channels-examples/tree/master/multichat

    :あなたはMultiChatサンプルプロジェクトでは、こののバリエーションを見ることができます

関連する問題