#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.