Hoow to use pydal tags for authorization ?

112 views
Skip to first unread message

Alexander Beskopilny

unread,
Jul 29, 2022, 7:23:14 AM7/29/22
to py4web
Hello!

( Maybe I'm doing something wrong? )

my application

# models.py
from .common import db, Field
from pydal.validators import *
from pydal.tools.tags import Tags

if not db(db.auth_user).count():
    u1 = {
        "username": "anil",
        "email": "an...@nil.com",
        "password": str(CRYPT()("xyz12345")[0]),
        "first_name": "Anil_first",
        "last_name": "Anil_Last",
    }

    for e in [u1, ]: db.auth_user.insert(**db.auth_user._filter_fields(e) )
    db.commit()

    grps = Tags(db.auth_user, 'grps')

    grps.add(1, 'manager')
    grps.add(1, 'dancer' )
    grps.add(1, 'teacher')
    grps.add(1, 'teacher')
    grps.add(1, 'teacher')
    grps.add(1, 'teacher')
    db.commit()

# controllers.py
from py4web import action, request, abort, redirect, URL
from yatl.helpers import A
from .common import db, session, T, cache, auth, logger, authenticated, unauthenticated, flash
from pydal.tools.tags import Tags

print( db(db.auth_user_tag_grps).select() )

grps2 = Tags(db.auth_user, 'grps')

@action('find_by_tag/{group_name}')
@action.uses(db)
def find(group_name):
    users = db(grps2.find([group_name])).select(orderby=db.auth_user.first_name | db.auth_user.last_name)
    return {'users': users}

@action("index")
@action.uses("index.html", auth, T)
def index():
    user = auth.get_user()
    message = T("Hello {first_name}".format(**user) if user else "Hello")
    actions = {"allowed_actions": auth.param.allowed_actions}
    return dict(message=message, actions=actions)

-----------------------------------------------------------------

result

[2022-07-29T14:07:40.155898]: Traceback (most recent call last):
  File "/home/w3p/set7-py39/py4web/py4web/core.py", line 1317, in import_app
    module = importlib.machinery.SourceFileLoader(
  File "<frozen importlib._bootstrap_external>", line 529, in _check_name_wrapper
  File "<frozen importlib._bootstrap_external>", line 1029, in load_module
  File "<frozen importlib._bootstrap_external>", line 854, in load_module
  File "<frozen importlib._bootstrap>", line 274, in _load_module_shim
  File "<frozen importlib._bootstrap>", line 711, in _load
  File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 850, in exec_module
  File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
  File "/home/w3p/set7-py39/py4web/apps/etag/__init__.py", line 10, in <module>
    from . import controllers
  File "/home/w3p/set7-py39/py4web/apps/etag/controllers.py", line 11, in <module>
    grps2 = Tags(db.auth_user, 'grps')
  File "/home/w3p/anaconda3/envs/set7-py39/lib/python3.9/site-packages/pydal/tools/tags.py", line 12, in __init__
    self.tag_table = db.define_table(
  File "/home/w3p/anaconda3/envs/set7-py39/lib/python3.9/site-packages/pydal/base.py", line 644, in define_table
    raise SyntaxError("table already defined: %s" % tablename)
SyntaxError: table already defined: auth_user_tag_grps
[FAILED] loading etag (table already defined: auth_user_tag_grps)

-----------------------------------------------------------------
can fix the file tags.py ?

vi "/home/w3p/anaconda3/envs/set7-py39/lib/python3.9/site-packages/pydal/tools/tags.py"

class Tags:
    def __init__(self, table, name="default"):
        self.table = table
        self.tagged_table = table._tablename + "_tag_" + name
        db = table._db
        if not self.tagged_table in db.tables:
            self.tag_table = db.define_table(
                self.tagged_table,
                Field("tagpath"),
                Field("record_id", table),
            )
            db.commit()

    def orig__init__(self, table, name="default"):
        self.table = table
        db = table._db
        self.tag_table = db.define_table(
            table._tablename + "_tag_" + name,
            Field("tagpath"),
            Field("record_id", table),
        )
        db.commit()

thanks in advance

Massimo DiPierro

unread,
Jul 29, 2022, 7:30:44 AM7/29/22
to Alexander Beskopilny, py4web
you must have deleted some .table file but the db is still there. create the db with fake_migrate=True and it should fix this.

--
You received this message because you are subscribed to the Google Groups "py4web" group.
To unsubscribe from this group and stop receiving emails from it, send an email to py4web+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/py4web/ae382f0e-965d-4b9d-b7cf-2101ef449f4bn%40googlegroups.com.

Alexander Beskopilny

unread,
Jul 29, 2022, 8:07:34 AM7/29/22
to py4web
# etag/setting.py
DB_FAKE_MIGRATE = True #False  # maybe?

------------
rm etag/databases/*

----------------------------
[ ] loading etag ...
[2022-07-29T15:05:34.751424]: Traceback (most recent call last):

  File "/home/w3p/set7-py39/py4web/py4web/core.py", line 1317, in import_app
    module = importlib.machinery.SourceFileLoader(
  File "<frozen importlib._bootstrap_external>", line 529, in _check_name_wrapper
  File "<frozen importlib._bootstrap_external>", line 1029, in load_module
  File "<frozen importlib._bootstrap_external>", line 854, in load_module
  File "<frozen importlib._bootstrap>", line 274, in _load_module_shim
  File "<frozen importlib._bootstrap>", line 711, in _load
  File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 850, in exec_module
  File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
  File "/home/w3p/set7-py39/py4web/apps/etag/__init__.py", line 7, in <module>
    from .models import db
  File "/home/w3p/set7-py39/py4web/apps/etag/models.py", line 6, in <module>
    if not db(db.auth_user).count():
  File "/home/w3p/anaconda3/envs/set7-py39/lib/python3.9/site-packages/pydal/objects.py", line 2674, in count
    return db._adapter.count(self.query, distinct)
  File "/home/w3p/anaconda3/envs/set7-py39/lib/python3.9/site-packages/pydal/adapters/base.py", line 913, in count
    self.execute(self._count(query, distinct))
  File "/home/w3p/anaconda3/envs/set7-py39/lib/python3.9/site-packages/pydal/adapters/__init__.py", line 70, in wrap
    return f(*args, **kwargs)
  File "/home/w3p/anaconda3/envs/set7-py39/lib/python3.9/site-packages/pydal/adapters/base.py", line 446, in execute
    rv = self.cursor.execute(command, *args[1:], **kwargs)
sqlite3.OperationalError: no such table: auth_user
[FAILED] loading etag (no such table: auth_user)

?

Massimo DiPierro

unread,
Jul 29, 2022, 10:13:05 AM7/29/22
to Alexander Beskopilny, py4web
fake migrate true tells py4web you have the tables in db but you deleted the metadata. you also deleted the databases folder so you no longer have the db. 

now you have no option. delete the databases folder again and set fake migrate false. 

Alexander Beskopilny

unread,
Jul 30, 2022, 1:27:30 AM7/30/22
to py4web
Hello Massimo!

Thank you for the answer
it's easy to check all key combinations

1
rm databases/* ; rm -rf __pycache__/

DB_MIGRATE = True
DB_FAKE_MIGRATE = False  # maybe?
.........

  File "/home/w3p/set7-py39/py4web/apps/etag/__init__.py", line 10, in <module>
    from . import controllers
  File "/home/w3p/set7-py39/py4web/apps/etag/controllers.py", line 9, in <module>

    grps2 = Tags(db.auth_user, 'grps')
  File "/home/w3p/anaconda3/envs/set7-py39/lib/python3.9/site-packages/pydal/tools/tags.py", line 12, in __init__
    self.tag_table = db.define_table(
  File "/home/w3p/anaconda3/envs/set7-py39/lib/python3.9/site-packages/pydal/base.py", line 644, in define_table
    raise SyntaxError("table already defined: %s" % tablename)
SyntaxError: table already defined: auth_user_tag_grps
[FAILED] loading etag (table already defined: auth_user_tag_grps)
[X] loaded _documentation
Ombott v0.0.14 server starting up (using <class 'py4web.server_adapters.rocketServer.<locals>.RocketServer'>(reloader=False))...
Listening on http://127.0.0.1:8000/
Hit Ctrl-C to quit.

Starting Rocket3 1.3.2
watching (lazy-mode) python file changes in: /home/w3p/set7-py39/py4web/apps
Listening on sockets: 127.0.0.1:8000

2
rm databases/* ; rm -rf __pycache__/
DB_MIGRATE = True
DB_FAKE_MIGRATE = True  # maybe?


sqlite3.OperationalError: no such table: auth_user
[FAILED] loading etag (no such table: auth_user)
3
rm databases/* ; rm -rf __pycache__/

DB_MIGRATE = False
DB_FAKE_MIGRATE = False  # maybe?
sqlite3.OperationalError: no such table: auth_user
[FAILED] loading etag (no such table: auth_user).
4
rm databases/* ; rm -rf __pycache__/

DB_MIGRATE = False
DB_FAKE_MIGRATE = True  # maybe?
....

sqlite3.OperationalError: no such table: auth_user
[FAILED] loading etag (no such table: auth_user)
....

probably the problem is in tags.py

Massimo DiPierro

unread,
Jul 30, 2022, 1:35:07 AM7/30/22
to Alexander Beskopilny, py4web
what database is this? is it possible there are two lines, maybe in different included files, trying to define the same etags?

Alexander Beskopilny

unread,
Jul 30, 2022, 2:17:41 AM7/30/22
to py4web
the problem is that this class Tag has no difference in creating a table and using a table

probably the Tag.use() constructor would solve the problem (and the program text would be clearer)

Massimo DiPierro

unread,
Jul 30, 2022, 2:24:04 AM7/30/22
to Alexander Beskopilny, py4web
sorry  i so not understand. 

Alexander Beskopilny

unread,
Jul 30, 2022, 3:06:17 AM7/30/22
to py4web
1

(sorry for my english)
in the file model.py we create a table
    grps = Tags(db.auth_user, )

    grps = Tags(db.auth_user, 'grps')

    grps.add(1, 'manager')
    grps.add(1, 'dancer' )
    grps.add(1, 'teacher')
    grps.add(1, 'teacher')
    grps.add(1, 'teacher')
    grps.add(1, 'teacher')
    db.commit()

it looks clear
2
in the file controllers.py we need access to grps2-table


grps2 = Tags(db.auth_user, 'grps')

@action('find_by_tag/{group_name}')
@action.uses(db)
def find(group_name):
    users = db(grps2.find([group_name])).select(orderby=db.auth_user.first_name | db.auth_user.last_name)
    return {'users': users}

looks not clear

If it were possible to write
grps2 = Tags.use (db.auth_user, 'grps')
it would be much clearer
and the problem  (table exist) would disappear
(in the controller we only need a reference to the table )

Massimo DiPierro

unread,
Jul 30, 2022, 3:12:03 AM7/30/22
to Alexander Beskopilny, py4web
ok. i see the problem. the solution is to place the definition of grps at the top level in models.py and import it in the controller. it is equivalent to a define_table so it should  ot be called more than once.

Alexander Beskopilny

unread,
Jul 30, 2022, 4:13:22 AM7/30/22
to py4web
thank you for your clear and patient explanation
Reply all
Reply to author
Forward
0 new messages