#1 by qzyyb123
Hi there, I am trying to run some live page codes which could be used in the previous otree version. However, when I try to replicate it, it fails. receiving data... receiving proposal... recording history... Exception in ASGI application Traceback (most recent call last): File "d:\otree\project\venv\lib\site-packages\uvicorn\protocols\websockets\websockets_impl.py", line 162, in run_asgi result = await self.app(self.scope, self.asgi_receive, self.asgi_send) File "d:\otree\project\venv\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 45, in __call__ return await self.app(scope, receive, send) File "d:\otree\project\venv\lib\site-packages\starlette\applications.py", line 112, in __call__ await self.middleware_stack(scope, receive, send) File "d:\otree\project\venv\lib\site-packages\starlette\middleware\base.py", line 21, in __call__ await self.app(scope, receive, send) File "d:\otree\project\venv\lib\site-packages\otree\errorpage.py", line 214, in __call__ await self.app(scope, receive, send) File "d:\otree\project\venv\lib\site-packages\starlette\middleware\base.py", line 21, in __call__ await self.app(scope, receive, send) File "d:\otree\project\venv\lib\site-packages\starlette\middleware\sessions.py", line 75, in __call__ await self.app(scope, receive, send_wrapper) File "d:\otree\project\venv\lib\site-packages\otree\patch.py", line 16, in __call__ await self.app(scope, receive, send) File "d:\otree\project\venv\lib\site-packages\starlette\routing.py", line 582, in __call__ await route.handle(scope, receive, send) File "d:\otree\project\venv\lib\site-packages\starlette\routing.py", line 299, in handle await self.app(scope, receive, send) File "d:\otree\project\venv\lib\site-packages\starlette\endpoints.py", line 74, in dispatch raise exc from None File "d:\otree\project\venv\lib\site-packages\starlette\endpoints.py", line 68, in dispatch await self.on_receive(websocket, data) File "d:\otree\project\venv\lib\site-packages\otree\channels\consumers.py", line 126, in on_receive await self.post_receive_json(data, **self.cleaned_kwargs) File "d:\otree\project\venv\lib\site-packages\otree\channels\consumers.py", line 193, in post_receive_json await live_payload_function( File "d:\otree\project\venv\lib\site-packages\otree\live.py", line 45, in live_payload_function retval = call_live_method_compat(live_method, player, payload) File "d:\otree\project\venv\lib\site-packages\otree\live.py", line 99, in call_live_method_compat return player.call_user_defined(live_method, payload) File "d:\otree\project\venv\lib\site-packages\otree\database.py", line 627, in call_user_defined return func(self, *args, **kwargs) File "D:\Otree\Project\Software\negotiation\models.py", line 184, in live_negotiation Proposal.objects.create(player=self, AttributeError: type object 'Proposal' has no attribute 'objects' The code is: models.py class Player(BasePlayer): skippedWaitPage = models.BooleanField(initial=False) treatment = models.StringField() first_move = models.BooleanField() first_offer = models.CurrencyField() match_id = models.IntegerField() match_gender = models.StringField() def chat_nickname(self): return '{}'.format(self.participant.vars["role"]) def live_negotiation(self, data): print("receiving data...") # type of data sent from page t = data["type"] # proposal sent? if t == "proposal": proposal = data["proposal"] # if proposal is valid (less than total revenue)... if proposal <= self.group.total_revenue: print("receiving proposal...") # is this the first proposal? if so, record variables if self.group.num_proposals == 0: self.first_move = True self.first_offer = c(proposal) self.get_others_in_group()[0].first_move = False # record now most recent proposal self.group.num_proposals += 1 if self.participant.vars["role"] == "Worker": self.group.workers_current_proposal = c(proposal) else: self.group.managers_current_proposal = c(proposal) # record history of proposals print("recording history...") Proposal.objects.create(player=self, group=self.group, role=self.participant.vars["role"], proposal=proposal, secs=time.time()-self.participant.vars["timeStartedNegotiation"]) # proposal or connect? if t in ["proposal", "connect"]: # return response to page proposals = [] for i in Proposal.objects.filter(group=self.group).order_by('id'): proposals.append([i.role, i.proposal]) response = dict(type="proposals", proposals=proposals) return {0: response} # wage accepted elif t == "accept": print("wage accepted...") # record accepted worker's wage if self.group.final_workers_wage is None: if self.participant.vars["role"] == "Worker": self.group.worker_accepted = True self.group.final_workers_wage = self.group.managers_current_proposal self.group.final_managers_profit = self.group.total_revenue - self.group.final_workers_wage else: self.group.manager_accepted = True self.group.final_workers_wage = self.group.workers_current_proposal self.group.final_managers_profit = self.group.total_revenue - self.group.final_workers_wage # submit page for all response = dict(type="negotiation_finished") return {0: response} def waiting_too_long(self): return time.time() - self.participant.vars['wait_page_arrival'] > 4*60 class Proposal(models.ExtraModel): player = models.Link(Player) group = models.Link(Group) role = models.StringField() proposal = models.CurrencyField() secs = models.StringField() def custom_export(players): # header row yield ["session.code", "participant.code", "player.id_in_group", "group.id_in_subsession", "role", "proposal", "secs"] # other rows for proposal in Proposal.objects.order_by('id'): player = proposal.player group = proposal.group participant = player.participant yield [player.session.code, participant.code, player.id_in_group, group.id_in_subsession, participant.vars["role"], proposal.proposal, proposal.secs] pages.py class Negotiation(Page): timeout_seconds = 4*60 live_method = 'live_negotiation' def js_vars(self): return dict( max=self.group.total_revenue, my_role=self.participant.vars["role"] ) def is_displayed(self): return self.player.skippedWaitPage is not True def vars_for_template(self): return dict( nickname=self.player.chat_nickname(), my_role=self.participant.vars["role"], other_role=self.player.get_others_in_group()[0].participant.vars["role"], other_gender=self.player.get_others_in_group()[0].participant.vars["gender"], other_birthSeason=self.player.get_others_in_group()[0].participant.vars["birthSeason"], other_eyeColour=self.player.get_others_in_group()[0].participant.vars["eyeColour"], other_siblings=self.player.get_others_in_group()[0].participant.vars["siblings"], total_revenue=self.group.total_revenue, treatment=self.participant.vars['treatment'] ) def before_next_page(self): # did they decide in time? if self.timeout_happened: self.group.agreement = False self.group.timeout_happened = True if self.participant.vars["role"] == "Worker": self.group.final_workers_wage = self.participant.vars["contributionsNoise"] * 0.2 self.group.final_managers_profit = self.player.get_others_in_group()[0].participant.vars["contributionsNoise"] * 0.2 else: self.group.final_workers_wage = self.player.get_others_in_group()[0].participant.vars["contributionsNoise"] * 0.2 self.group.final_managers_profit = self.participant.vars["contributionsNoise"] * 0.2 else: self.group.agreement = True # set payoffs if self.participant.vars["role"] == "Worker": self.player.payoff += self.group.final_workers_wage else: self.player.payoff += self.group.final_managers_profit Any suggestions are greatly appreciated!
#2
by
Chris_oTree
See ExtraModel documentation here: https://otree.readthedocs.io/en/latest/misc/advanced.html#extramodel Change Proposal.objects.create() to Proposal.create(). There is also Proposal.filter(). And no more .order_by() etc.
#3 by qzyyb123
Thanks Chris! I've fixed it.