oTree Forum >

AttributeError: 'int' object has no attribute '_sa_instance_state'

#1 by papayapap (edited )

I am learning to use ExtraModel, so I created a simple example below. Unfortunately, it gives me the error in the title and I am not sure why. StackOverflow answers suggest this comes because an integer (ID) is being interpreted as an ORM object.

Anybody knows that this means in an Otree context?


############### init.py ####################


from otree.api import *


class C(BaseConstants):
    NAME_IN_URL = 'store_data'
    PLAYERS_PER_GROUP = None
    NUM_ROUNDS = 1
    NUM_EMPLOYERS = 3
    NUM_WORKERS = 7


class Subsession(BaseSubsession):
    pass


class Group(BaseGroup):
    is_finished = models.BooleanField(initial=False)
    job_id = models.IntegerField(initial=0)


class Player(BasePlayer):
    is_employer = models.IntegerField()
    worker_is_employed = models.IntegerField(initial=0, min=0, max=1)
    employer_num_workers = models.IntegerField(initial=0, min=0, max=3)


class JobOffer(ExtraModel):
    group = models.Link(Group)
    employer_id = models.Link(Player)
    wage = models.IntegerField(min=0, max=100)
    effort = models.IntegerField(min=0, max=10)


# FUNCTIONS
def creating_session(subsession: Subsession):
    players = subsession.get_players()
    if subsession.round_number == 1:
        for p in players:
            if p.id_in_group <= C.NUM_EMPLOYERS:
                p.participant.is_employer = True
            else:
                p.participant.is_employer = False
        for p in players:
            if p.participant.is_employer:
                p.is_employer = 1
            else:
                p.is_employer = 0


# PAGES
class MyPage(Page):
    form_model = 'group'

    @staticmethod
    def js_vars(player: Player):
        return dict(my_id=player.id_in_group, is_employer=player.is_employer)

    @staticmethod
    def live_method(player: Player, data):
        group = player.group
        my_id = player.id_in_group

        print('Received: ', data)
        print(my_id)

        if data['information_type'] == 'offer':
            # check if offer was legit. If yes...
            group.job_id = group.job_id + 1
            print(group.job_id)
            employer_id = data['employer_id']
            wage = data['wage']
            effort = data['effort']

            JobOffer.create(
                    group=group,
                    employer_id=employer_id,
                    wage=wage,
                    effort=effort,
                )

            offer = JobOffer.filter(group=group)
            print(offer)



class ResultsWaitPage(WaitPage):
    pass


class Results(Page):
    pass


page_sequence = [MyPage, ResultsWaitPage, Results]



######################## MyPage



{{ block title }}

<form>
    <div class="row">
        <div class="col">
            <input type="text" id="wage" class="form-control" placeholder="Wage">
        </div>
        <div class="col">
            <input type="text" id="effort" class="form-control" placeholder="Effort">
        </div>
        <div class="col">
            <button type="button" class="btn btn-secondary" id="send_offer" onclick="sendOffer()"> Send Offer </button>
        </div>
    </div>
</form>


<script>

    function sendOffer() {
        let offered_wage = parseInt(document.getElementById("wage").value);
        let effort_requested = parseInt(document.getElementById("effort").value);
        let my_id = parseInt(js_vars.my_id);
        } else {
            liveSend({
                "information_type": "offer",
                "employer_id": my_id,
                "wage": offered_wage,
                "effort": effort_requested
            });
            document.getElementById("effort").value = "";
            document.getElementById("wage").value = "";
        }
    }


</script>

{{ endblock }}




Full error message:

Exception in ASGI application
Traceback (most recent call last):
  File "C:\Users\felix\AppData\Local\Programs\Python\Python39\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 "C:\Users\felix\AppData\Local\Programs\Python\Python39\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 45, in __call__
    return await self.app(scope, receive, send)
  File "C:\Users\felix\AppData\Local\Programs\Python\Python39\lib\site-packages\starlette\applications.py", line 112, in __call__
    await self.middleware_stack(scope, receive, send)
  File "C:\Users\felix\AppData\Local\Programs\Python\Python39\lib\site-packages\starlette\middleware\base.py", line 21, in __call__
    await self.app(scope, receive, send)
  File "C:\Users\felix\AppData\Local\Programs\Python\Python39\lib\site-packages\otree\errorpage.py", line 214, in __call__
    await self.app(scope, receive, send)
  File "C:\Users\felix\AppData\Local\Programs\Python\Python39\lib\site-packages\starlette\middleware\base.py", line 21, in __call__
    await self.app(scope, receive, send)
  File "C:\Users\felix\AppData\Local\Programs\Python\Python39\lib\site-packages\starlette\middleware\sessions.py", line 75, in __call__
    await self.app(scope, receive, send_wrapper)
  File "C:\Users\felix\AppData\Local\Programs\Python\Python39\lib\site-packages\otree\patch.py", line 16, in __call__
    await self.app(scope, receive, send)
  File "C:\Users\felix\AppData\Local\Programs\Python\Python39\lib\site-packages\starlette\routing.py", line 582, in __call__
    await route.handle(scope, receive, send)
  File "C:\Users\felix\AppData\Local\Programs\Python\Python39\lib\site-packages\starlette\routing.py", line 299, in handle
    await self.app(scope, receive, send)
  File "C:\Users\felix\AppData\Local\Programs\Python\Python39\lib\site-packages\starlette\endpoints.py", line 74, in dispatch
    raise exc from None
  File "C:\Users\felix\AppData\Local\Programs\Python\Python39\lib\site-packages\starlette\endpoints.py", line 68, in dispatch
    await self.on_receive(websocket, data)
  File "C:\Users\felix\AppData\Local\Programs\Python\Python39\lib\site-packages\otree\channels\consumers.py", line 127, in on_receive
    await self.post_receive_json(data, **self.cleaned_kwargs)
  File "C:\Users\felix\AppData\Local\Programs\Python\Python39\lib\site-packages\otree\channels\consumers.py", line 194, in post_receive_json
    await live_payload_function(
  File "C:\Users\felix\AppData\Local\Programs\Python\Python39\lib\site-packages\otree\live.py", line 45, in live_payload_function
    retval = call_live_method_compat(live_method, player, payload)
  File "C:\Users\felix\AppData\Local\Programs\Python\Python39\lib\site-packages\otree\live.py", line 101, in call_live_method_compat
    return live_method(player, payload)
  File "C:\Users\felix\Documents\Otree\test\testproject\store_data\__init__.py", line 81, in live_method
    JobOffer.create(
  File "C:\Users\felix\AppData\Local\Programs\Python\Python39\lib\site-packages\otree\database.py", line 912, in create
    db.add(obj)
  File "C:\Users\felix\AppData\Local\Programs\Python\Python39\lib\site-packages\otree\database.py", line 170, in add
    return self._db.add(obj)
  File "C:\Users\felix\AppData\Local\Programs\Python\Python39\lib\site-packages\sqlalchemy\orm\session.py", line 2023, in add
    self._save_or_update_state(state)
  File "C:\Users\felix\AppData\Local\Programs\Python\Python39\lib\site-packages\sqlalchemy\orm\session.py", line 2039, in _save_or_update_state
    for o, m, st_, dct_ in mapper.cascade_iterator(
  File "C:\Users\felix\AppData\Local\Programs\Python\Python39\lib\site-packages\sqlalchemy\orm\mapper.py", line 3098, in cascade_iterator
    queue = deque(
  File "C:\Users\felix\AppData\Local\Programs\Python\Python39\lib\site-packages\sqlalchemy\orm\relationships.py", line 1938, in cascade_iterator
    tuples = state.manager[self.key].impl.get_all_pending(state, dict_)
  File "C:\Users\felix\AppData\Local\Programs\Python\Python39\lib\site-packages\sqlalchemy\orm\attributes.py", line 967, in get_all_pending
    ret = [(instance_state(current), current)]
AttributeError: 'int' object has no attribute '_sa_instance_state

Write a reply

Set forum username