Django Каналы отменяют сопрограммные сообщения - PullRequest
0 голосов
/ 22 марта 2020

Привет, я разрабатываю приложение с django. Я перечитал всю документацию Django Канал документации и не смог найти. Когда пользователь подключен к потребителю, я добавляю пользователя в группу. И когда изменился экземпляр модели, я отправляю сигнал потребителю каждому экземпляру клиента в группе, но я посылаю сигнал постоянно, поэтому моя проблема начинается здесь, и я хочу, чтобы предыдущие сообщения отменялись при отправке сигнала. Я просто хочу, чтобы последние сообщения, отправленные в группу, go. Я не мог найти способ решить это

from channels.generic.websocket import AsyncWebsocketConsumer
from channels.db import database_sync_to_async
from channels.exceptions import DenyConnection
from main.consumers import AsyncWebsocketConsumer

from auctions.models import Auction, Lot, AuctionBid, AuctionReport, AuctionSaloon, LandLot, HouseLot, Deposit, UserFlag, Participant
from liveauction.serializers import ROAuctionBidSerializer, ROAuctionSerializer, ROHouseLotSerializer, ROLandLotSerializer, ROLotSerializer, ROParticipantSerializer, ROFlagCoverageRangeSerializer, RONormalAuctionSerializer

from django.core.exceptions import ObjectDoesNotExist
import json
import asyncio


class AuctionConsumer(AsyncWebsocketConsumer):

    active_auction = None
    active_lot = None
    permissions = []
    channel_groups = []
    flag_coverage_ranges = []

    async def connect(self):
        if self.scope['user']:
            user = self.scope['user']
            print(self.scope['user'])
            if user.is_anonymous:
                await self.close()
            else:
                self.active_auction = await self._get_active_auction()
                print(self.active_auction)
                if self.active_auction is not None:
                    print(self.active_auction.get_channel_name())
                    self.channel_groups.append(self.channel_layer.group_add(
                        self.active_auction.get_channel_name(), self.channel_name))
                    asyncio.gather(*self.channel_groups)
                    self.permissions = await self._get_user_permission(self.scope['user'])
                    self.flag_coverage_ranges = self.active_auction.flag_coverage_ranges.all()
                    await self.accept()
                else:
                    await self.close()

    async def disconnect(self, code):
        asyncio.gather(*self.channel_groups)
        await super().disconnect(code)

    async def receive(self, text_data):
        content = json.loads(text_data)
        message_type = content.get('command')
        print(message_type)
        if await self.has_permission(message_type):
            if message_type == 'create.bid':
                await self.create_bid(content, True if self.has_permission('create.bid') else False)
            elif message_type == 'delete.bid':
                await self.delete_bid(content)
            elif message_type == 'update.bid':
                await self.update_bid(content)
            elif message_type == 'change.lot':
                await self.change_lot(content)
            elif message_type == 'update.auction':
                await self.update_auction(content)
            elif message_type == 'update.approve':
                await self.update_approve(content)
            else:
                await self.raise_error('Command not found.')
        else:
            raise DenyConnection('User is not authorized.')

    async def create_bid(self, event, auto_next_bid=True):
        print('create_bid called')
        if self.active_auction.approve_mode:
            print("teklif vermek kilitli şuan ?")
            return
        user_flag = event.get('data').get('flag') if event.get('data').get('flag', False) else await self.get_first_flag()
        participant = int(event.get('data').get('participant')) if event.get(
            'data').get('participant', False) else int(self.scope['user'].participant.id) if hasattr(self.scope['user'], 'participant') else ''
        bid_amount = event.get('data').get('bid') if event.get('data').get(
            'bid', False) else self.active_auction.current_lot.next_bid_amount
        auto_next_bid = False
        if not user_flag or float(bid_amount) < float(self.active_auction.current_lot.next_bid_amount):
            print("bura")
            pass

        if 'admin' not in self.permissions:
            getted_current_participant = await self._get_participant(participant)
            participant_deposit = getted_current_participant.deposit.filter(
                auction__id=self.active_auction.id)
            print("teminatı arıyoruz")
            if participant_deposit.exists():
                if (participant_deposit.deposit - participant_deposit.get_used_flag_deposit_amount()) < self.active_auction.current_lot.minimum_deposit:
                    print("teminatı yetersiz")
                    return
            else:
                print("teminatı yok")
                return
            last_flag_participant = None
            try:
                tenor_bids = self.active_auction.current_lot.tenor_bids
                bid = tenor_bids
                if bid.exists():
                    bid = bid.last()
                    last_flag_participant = bid.participant
                    print(bid)
                if last_flag_participant is not None:
                    print(last_flag_participant)
                    if getted_current_participant is not None:
                        print(getted_current_participant)
                        if getted_current_participant.id == last_flag_participant.id:
                            print("veremez teklif")
                            return

            except Exception as e:
                print(e)

        bid_template = {
            "flag": user_flag if not isinstance(user_flag, UserFlag) else user_flag.pk,
            "bid":  bid_amount if auto_next_bid is not True else self.active_auction.current_lot.next_bid_amount,
            "user": self.scope['user'].id,
            "lot": self.active_auction.current_lot.id,
            "participant": participant
        }
        await self._create_bid(bid_template)
        await self.send_everyone_updated_auction()

    async def delete_bid(self, event):
        ...

        await self.send_everyone_updated_auction()

    async def update_bid(self, event):
        ...

        await self.send_everyone_updated_auction()

    async def change_lot(self, event):
        ...

        await self.send_everyone_updated_auction()

    async def add_bid_to_lot(self, bid):
        ...

        await self.send_everyone_updated_auction()

    async def update_auction(self, event):
        print('update_auction called')
        auction_data = event.get('data', None)

        if auction_data is None:
            auction = await self._update_auction(self.active_auction)

            if self.has_permission('watch') and not self.has_permission('admin'):
                auction_data = RONormalAuctionSerializer(auction).data
            else:
                auction_data = ROAuctionSerializer(auction).data

        await self.send(text_data=json.dumps({
            'type': 'update.auction',
            'data': auction_data,
            'permissions': self.permissions,
            'flag_coverage_ranges': [ROFlagCoverageRangeSerializer(i).data for i in self.flag_coverage_ranges],
        }))

    async def update_approve(self, event):
        ...

        await self.send_everyone_updated_auction()

    async def send_everyone_updated_auction(self):
        auction = await self._update_auction(self.active_auction)
        serialized_data = {
            "id": auction.id,
            "slug": auction.slug,
            "current_lot": {
                "slug": auction.current_lot.slug,
                "last_bid": None if auction.current_lot.last_bid is None else {
                    "id": auction.current_lot.last_bid.id,
                    "slug": auction.current_lot.last_bid.slug,
                    "flag": auction.current_lot.last_bid.flag if auction.current_lot.last_bid.flag is None else {
                        "id": auction.current_lot.last_bid.flag if auction.current_lot.last_bid.flag is None else auction.current_lot.last_bid.flag.id,
                        "slug": auction.current_lot.last_bid.flag.slug,
                        "flag_number": auction.current_lot.last_bid.flag.flag_number,
                    },
                    "participant": auction.current_lot.last_bid.participant if auction.current_lot.last_bid.flag is None else {
                        "id": auction.current_lot.last_bid.participant.id,
                        "slug": auction.current_lot.last_bid.participant.slug,
                        "participant_type": auction.current_lot.last_bid.participant.participant_type,
                    },
                },
                "current_bid_amount": auction.current_lot.current_bid_amount,
                "next_bid_amount": auction.current_lot.next_bid_amount,
                "tenor_status": auction.current_lot.tenor_status,
                "type": auction.current_lot.type,
                "lot_number": auction.current_lot.lot_number,
                "title": auction.current_lot.title,
                "description": auction.current_lot.description,
                "minimum_deposit": auction.current_lot.minimum_deposit,
                "appraised_price": auction.current_lot.appraised_price,
                "status": auction.current_lot.status,
                "increament_amount": auction.current_lot.increament_amount,
                "tenor": auction.current_lot.tenor,
            },
            "saloons": [],
            "title": auction.title,
            "description": auction.description,
            "status": auction.status,
            "approve_mode": auction.approve_mode,
            "participants": []
        }

        await self.channel_layer.group_send(group=self.active_auction.get_channel_name(), message={
            'type': 'update.auction',
            'data': serialized_data
        })

    @database_sync_to_async
    def _open_approve(self):
        ...

    @database_sync_to_async
    def _close_approve(self):
        ...

    @database_sync_to_async
    def get_first_flag(self):
        ...

    @database_sync_to_async
    def _update_auction(self, auction):
        if auction is not None:
            serializer = None
            try:
                auction = Auction.objects.prefetch_related('lots__bids').get(pk=auction.pk)
                return auction
            except ObjectDoesNotExist:
                return None
        else:
            raise Exception('Have not yet active auction')

    @database_sync_to_async
    def _delete_bid(self, content):
        ...

    @database_sync_to_async
    def _update_bid(self, content):
        ...

    @database_sync_to_async
    def _create_bid(self, content):
        ...


    @database_sync_to_async
    def _get_participant(self, participant_id):
        ...

    @database_sync_to_async
    def _add_bid_to_lot(self, content):
        ...

    @database_sync_to_async
    def _get_user_permission(self, user):
        ...

    @database_sync_to_async
    def _get_active_auction(self):
        ...

    # TODO: Müzayededeki en son aktif Lot getirelecek
    @database_sync_to_async
    def _get_active_lot(self):
        ...

    @database_sync_to_async
    def _change_lot(self, content):
        ...

    @database_sync_to_async
    def has_permission(self, permission):
        ...
...