mirror of
https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
synced 2024-11-14 16:55:42 +00:00
Add m2m corpus-follower table
This commit is contained in:
parent
62bd21ad84
commit
97bba2498b
164
app/models.py
164
app/models.py
@ -3,6 +3,7 @@ from enum import Enum, IntEnum
|
|||||||
from flask import current_app, url_for
|
from flask import current_app, url_for
|
||||||
from flask_hashids import HashidMixin
|
from flask_hashids import HashidMixin
|
||||||
from flask_login import UserMixin
|
from flask_login import UserMixin
|
||||||
|
from sqlalchemy.ext.associationproxy import association_proxy
|
||||||
from time import sleep
|
from time import sleep
|
||||||
from tqdm import tqdm
|
from tqdm import tqdm
|
||||||
from werkzeug.security import generate_password_hash, check_password_hash
|
from werkzeug.security import generate_password_hash, check_password_hash
|
||||||
@ -169,7 +170,7 @@ class Role(HashidMixin, db.Model):
|
|||||||
default = db.Column(db.Boolean, default=False, index=True)
|
default = db.Column(db.Boolean, default=False, index=True)
|
||||||
permissions = db.Column(db.Integer, default=0)
|
permissions = db.Column(db.Integer, default=0)
|
||||||
# Relationships
|
# Relationships
|
||||||
users = db.relationship('User', backref='role', lazy='dynamic')
|
users = db.relationship('User', back_populates='role', lazy='dynamic')
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f'<Role {self.name}>'
|
return f'<Role {self.name}>'
|
||||||
@ -239,7 +240,8 @@ class Token(db.Model):
|
|||||||
access_expiration = db.Column(db.DateTime)
|
access_expiration = db.Column(db.DateTime)
|
||||||
refresh_token = db.Column(db.String(64), index=True)
|
refresh_token = db.Column(db.String(64), index=True)
|
||||||
refresh_expiration = db.Column(db.DateTime)
|
refresh_expiration = db.Column(db.DateTime)
|
||||||
# Backrefs: user: User
|
# Relationships
|
||||||
|
user = db.relationship('User', back_populates='tokens')
|
||||||
|
|
||||||
def expire(self):
|
def expire(self):
|
||||||
self.access_expiration = datetime.utcnow()
|
self.access_expiration = datetime.utcnow()
|
||||||
@ -258,7 +260,9 @@ class Avatar(HashidMixin, FileMixin, db.Model):
|
|||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
# Foreign keys
|
# Foreign keys
|
||||||
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
|
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
|
||||||
|
# Relationships
|
||||||
|
user = db.relationship('User', back_populates='avatar')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def path(self):
|
def path(self):
|
||||||
return os.path.join(self.user.path, 'avatar')
|
return os.path.join(self.user.path, 'avatar')
|
||||||
@ -278,19 +282,22 @@ class Avatar(HashidMixin, FileMixin, db.Model):
|
|||||||
return json_serializeable
|
return json_serializeable
|
||||||
|
|
||||||
|
|
||||||
corpus_followers = db.Table(
|
class CorpusFollowerAssociation(db.Model):
|
||||||
'corpus_followers',
|
__tablename__ = 'corpus_follower_associations'
|
||||||
db.Model.metadata,
|
# Primary key
|
||||||
db.Column('user_id', db.ForeignKey('users.id'), primary_key=True),
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
db.Column('corpus_id', db.ForeignKey('corpora.id'), primary_key=True)
|
# Foreign keys
|
||||||
)
|
following_user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
|
||||||
|
followed_corpus_id = db.Column(db.Integer, db.ForeignKey('corpora.id'))
|
||||||
|
# Fields
|
||||||
|
permissions = db.Column(db.Integer, default=0, nullable=False)
|
||||||
|
# Relationships
|
||||||
|
followed_corpus = db.relationship('Corpus', back_populates='following_user_associations')
|
||||||
|
following_user = db.relationship('User', back_populates='followed_corpus_associations')
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f'<CorpusFollowerAssociation {self.following_user.__repr__()} ~ {self.followed_corpus.__repr__()}>'
|
||||||
|
|
||||||
user_followers = db.Table(
|
|
||||||
'user_followers',
|
|
||||||
db.Model.metadata,
|
|
||||||
db.Column('follower_user_id', db.ForeignKey('users.id'), primary_key=True),
|
|
||||||
db.Column('followed_user_id', db.ForeignKey('users.id'), primary_key=True)
|
|
||||||
)
|
|
||||||
|
|
||||||
class User(HashidMixin, UserMixin, db.Model):
|
class User(HashidMixin, UserMixin, db.Model):
|
||||||
__tablename__ = 'users'
|
__tablename__ = 'users'
|
||||||
@ -316,56 +323,53 @@ class User(HashidMixin, UserMixin, db.Model):
|
|||||||
organization = db.Column(db.String(128))
|
organization = db.Column(db.String(128))
|
||||||
is_public = db.Column(db.Boolean, default=False)
|
is_public = db.Column(db.Boolean, default=False)
|
||||||
profile_privacy_settings = db.Column(db.Integer(), default=0)
|
profile_privacy_settings = db.Column(db.Integer(), default=0)
|
||||||
# Backrefs: role: Role
|
|
||||||
# Relationships
|
# Relationships
|
||||||
avatar = db.relationship(
|
avatar = db.relationship(
|
||||||
'Avatar',
|
'Avatar',
|
||||||
backref='user',
|
back_populates='user',
|
||||||
cascade='all, delete-orphan',
|
cascade='all, delete-orphan',
|
||||||
uselist=False
|
uselist=False
|
||||||
)
|
)
|
||||||
tesseract_ocr_pipeline_models = db.relationship(
|
|
||||||
'TesseractOCRPipelineModel',
|
|
||||||
backref='user',
|
|
||||||
cascade='all, delete-orphan',
|
|
||||||
lazy='dynamic'
|
|
||||||
)
|
|
||||||
spacy_nlp_pipeline_models = db.relationship(
|
|
||||||
'SpaCyNLPPipelineModel',
|
|
||||||
backref='user',
|
|
||||||
cascade='all, delete-orphan',
|
|
||||||
lazy='dynamic'
|
|
||||||
)
|
|
||||||
corpora = db.relationship(
|
corpora = db.relationship(
|
||||||
'Corpus',
|
'Corpus',
|
||||||
backref='user',
|
back_populates='user',
|
||||||
cascade='all, delete-orphan',
|
cascade='all, delete-orphan',
|
||||||
lazy='dynamic'
|
lazy='dynamic'
|
||||||
)
|
)
|
||||||
followed_corpora = db.relationship(
|
followed_corpus_associations = db.relationship(
|
||||||
'Corpus',
|
'CorpusFollowerAssociation',
|
||||||
secondary=corpus_followers,
|
back_populates='following_user'
|
||||||
primaryjoin=(corpus_followers.c.user_id == id),
|
|
||||||
backref=db.backref('followers', lazy='dynamic'),
|
|
||||||
lazy='dynamic'
|
|
||||||
)
|
)
|
||||||
followed_users = db.relationship(
|
followed_corpora = association_proxy(
|
||||||
'User',
|
'followed_corpus_associations',
|
||||||
secondary=user_followers,
|
'followed_corpus',
|
||||||
primaryjoin=(user_followers.c.follower_user_id == id),
|
creator=lambda c: CorpusFollowerAssociation(followed_corpus=c)
|
||||||
secondaryjoin=(user_followers.c.followed_user_id == id),
|
|
||||||
backref=db.backref('followers', lazy='dynamic'),
|
|
||||||
lazy='dynamic'
|
|
||||||
)
|
)
|
||||||
jobs = db.relationship(
|
jobs = db.relationship(
|
||||||
'Job',
|
'Job',
|
||||||
backref='user',
|
back_populates='user',
|
||||||
|
cascade='all, delete-orphan',
|
||||||
|
lazy='dynamic'
|
||||||
|
)
|
||||||
|
role = db.relationship(
|
||||||
|
'Role',
|
||||||
|
back_populates='users'
|
||||||
|
)
|
||||||
|
spacy_nlp_pipeline_models = db.relationship(
|
||||||
|
'SpaCyNLPPipelineModel',
|
||||||
|
back_populates='user',
|
||||||
|
cascade='all, delete-orphan',
|
||||||
|
lazy='dynamic'
|
||||||
|
)
|
||||||
|
tesseract_ocr_pipeline_models = db.relationship(
|
||||||
|
'TesseractOCRPipelineModel',
|
||||||
|
back_populates='user',
|
||||||
cascade='all, delete-orphan',
|
cascade='all, delete-orphan',
|
||||||
lazy='dynamic'
|
lazy='dynamic'
|
||||||
)
|
)
|
||||||
tokens = db.relationship(
|
tokens = db.relationship(
|
||||||
'Token',
|
'Token',
|
||||||
backref='user',
|
back_populates='user',
|
||||||
cascade='all, delete-orphan',
|
cascade='all, delete-orphan',
|
||||||
lazy='dynamic'
|
lazy='dynamic'
|
||||||
)
|
)
|
||||||
@ -572,30 +576,6 @@ class User(HashidMixin, UserMixin, db.Model):
|
|||||||
self.profile_privacy_settings = 0
|
self.profile_privacy_settings = 0
|
||||||
#endregion Profile Privacy settings
|
#endregion Profile Privacy settings
|
||||||
|
|
||||||
def follow_corpus(self, corpus):
|
|
||||||
if not self.is_following_corpus(corpus):
|
|
||||||
self.followed_corpora.append(corpus)
|
|
||||||
|
|
||||||
def unfollow_corpus(self, corpus):
|
|
||||||
if self.is_following_corpus(corpus):
|
|
||||||
self.followed_corpora.remove(corpus)
|
|
||||||
|
|
||||||
def is_following_corpus(self, corpus):
|
|
||||||
return self.followed_corpora.filter(
|
|
||||||
corpus_followers.c.corpus_id == corpus.id).count() > 0
|
|
||||||
|
|
||||||
def follow_user(self, user):
|
|
||||||
if not self.is_following_user(user):
|
|
||||||
self.followed_users.append(user)
|
|
||||||
|
|
||||||
def unfollow_user(self, user):
|
|
||||||
if self.is_following_user(user):
|
|
||||||
self.followed_users.remove(user)
|
|
||||||
|
|
||||||
def is_following_user(self, user):
|
|
||||||
return self.followed_users.filter(
|
|
||||||
user_followers.c.followed_user_id == user.id).count() > 0
|
|
||||||
|
|
||||||
def to_json_serializeable(self, backrefs=False, relationships=False, filter_by_privacy_settings=False):
|
def to_json_serializeable(self, backrefs=False, relationships=False, filter_by_privacy_settings=False):
|
||||||
json_serializeable = {
|
json_serializeable = {
|
||||||
'id': self.hashid,
|
'id': self.hashid,
|
||||||
@ -670,7 +650,8 @@ class TesseractOCRPipelineModel(FileMixin, HashidMixin, db.Model):
|
|||||||
publishing_url = db.Column(db.String(512))
|
publishing_url = db.Column(db.String(512))
|
||||||
publishing_year = db.Column(db.Integer)
|
publishing_year = db.Column(db.Integer)
|
||||||
is_public = db.Column(db.Boolean, default=False)
|
is_public = db.Column(db.Boolean, default=False)
|
||||||
# Backrefs: user: User
|
# Relationships
|
||||||
|
user = db.relationship('User', back_populates='tesseract_ocr_pipeline_models')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def path(self):
|
def path(self):
|
||||||
@ -794,7 +775,8 @@ class SpaCyNLPPipelineModel(FileMixin, HashidMixin, db.Model):
|
|||||||
publishing_year = db.Column(db.Integer)
|
publishing_year = db.Column(db.Integer)
|
||||||
pipeline_name = db.Column(db.String(64))
|
pipeline_name = db.Column(db.String(64))
|
||||||
is_public = db.Column(db.Boolean, default=False)
|
is_public = db.Column(db.Boolean, default=False)
|
||||||
# Backrefs: user: User
|
# Relationships
|
||||||
|
user = db.relationship('User', back_populates='spacy_nlp_pipeline_models')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def path(self):
|
def path(self):
|
||||||
@ -909,7 +891,11 @@ class JobInput(FileMixin, HashidMixin, db.Model):
|
|||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
# Foreign keys
|
# Foreign keys
|
||||||
job_id = db.Column(db.Integer, db.ForeignKey('jobs.id'))
|
job_id = db.Column(db.Integer, db.ForeignKey('jobs.id'))
|
||||||
# Backrefs: job: Job
|
# Relationships
|
||||||
|
job = db.relationship(
|
||||||
|
'Job',
|
||||||
|
back_populates='inputs'
|
||||||
|
)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f'<JobInput {self.filename}>'
|
return f'<JobInput {self.filename}>'
|
||||||
@ -965,7 +951,11 @@ class JobResult(FileMixin, HashidMixin, db.Model):
|
|||||||
job_id = db.Column(db.Integer, db.ForeignKey('jobs.id'))
|
job_id = db.Column(db.Integer, db.ForeignKey('jobs.id'))
|
||||||
# Fields
|
# Fields
|
||||||
description = db.Column(db.String(255))
|
description = db.Column(db.String(255))
|
||||||
# Backrefs: job: Job
|
# Relationships
|
||||||
|
job = db.relationship(
|
||||||
|
'Job',
|
||||||
|
back_populates='results'
|
||||||
|
)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f'<JobResult {self.filename}>'
|
return f'<JobResult {self.filename}>'
|
||||||
@ -1039,20 +1029,23 @@ class Job(HashidMixin, db.Model):
|
|||||||
default=JobStatus.INITIALIZING
|
default=JobStatus.INITIALIZING
|
||||||
)
|
)
|
||||||
title = db.Column(db.String(32))
|
title = db.Column(db.String(32))
|
||||||
# Backrefs: user: User
|
|
||||||
# Relationships
|
# Relationships
|
||||||
inputs = db.relationship(
|
inputs = db.relationship(
|
||||||
'JobInput',
|
'JobInput',
|
||||||
backref='job',
|
back_populates='job',
|
||||||
cascade='all, delete-orphan',
|
cascade='all, delete-orphan',
|
||||||
lazy='dynamic'
|
lazy='dynamic'
|
||||||
)
|
)
|
||||||
results = db.relationship(
|
results = db.relationship(
|
||||||
'JobResult',
|
'JobResult',
|
||||||
backref='job',
|
back_populates='job',
|
||||||
cascade='all, delete-orphan',
|
cascade='all, delete-orphan',
|
||||||
lazy='dynamic'
|
lazy='dynamic'
|
||||||
)
|
)
|
||||||
|
user = db.relationship(
|
||||||
|
'User',
|
||||||
|
back_populates='jobs'
|
||||||
|
)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f'<Job {self.title}>'
|
return f'<Job {self.title}>'
|
||||||
@ -1173,7 +1166,11 @@ class CorpusFile(FileMixin, HashidMixin, db.Model):
|
|||||||
pages = db.Column(db.String(255))
|
pages = db.Column(db.String(255))
|
||||||
publisher = db.Column(db.String(255))
|
publisher = db.Column(db.String(255))
|
||||||
school = db.Column(db.String(255))
|
school = db.Column(db.String(255))
|
||||||
# Backrefs: corpus: Corpus
|
# Relationships
|
||||||
|
corpus = db.relationship(
|
||||||
|
'Corpus',
|
||||||
|
back_populates='files'
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def download_url(self):
|
def download_url(self):
|
||||||
@ -1262,14 +1259,23 @@ class Corpus(HashidMixin, db.Model):
|
|||||||
num_analysis_sessions = db.Column(db.Integer, default=0)
|
num_analysis_sessions = db.Column(db.Integer, default=0)
|
||||||
num_tokens = db.Column(db.Integer, default=0)
|
num_tokens = db.Column(db.Integer, default=0)
|
||||||
is_public = db.Column(db.Boolean, default=False)
|
is_public = db.Column(db.Boolean, default=False)
|
||||||
# Backrefs: user: User
|
|
||||||
# Relationships
|
# Relationships
|
||||||
files = db.relationship(
|
files = db.relationship(
|
||||||
'CorpusFile',
|
'CorpusFile',
|
||||||
backref='corpus',
|
back_populates='corpus',
|
||||||
lazy='dynamic',
|
lazy='dynamic',
|
||||||
cascade='all, delete-orphan'
|
cascade='all, delete-orphan'
|
||||||
)
|
)
|
||||||
|
following_user_associations = db.relationship(
|
||||||
|
'CorpusFollowerAssociation',
|
||||||
|
back_populates='followed_corpus'
|
||||||
|
)
|
||||||
|
following_users = association_proxy(
|
||||||
|
'following_user_associations',
|
||||||
|
'following_user',
|
||||||
|
creator=lambda u: CorpusFollowerAssociation(following_user=u)
|
||||||
|
)
|
||||||
|
user = db.relationship('User', back_populates='corpora')
|
||||||
# "static" attributes
|
# "static" attributes
|
||||||
max_num_tokens = 2_147_483_647
|
max_num_tokens = 2_147_483_647
|
||||||
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
"""Add corpus_followers table
|
|
||||||
|
|
||||||
Revision ID: 4aa88f253dab
|
|
||||||
Revises: 5b2a6e590166
|
|
||||||
Create Date: 2023-01-12 14:47:39.492875
|
|
||||||
|
|
||||||
"""
|
|
||||||
from alembic import op
|
|
||||||
import sqlalchemy as sa
|
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
|
||||||
revision = '4aa88f253dab'
|
|
||||||
down_revision = '5b2a6e590166'
|
|
||||||
branch_labels = None
|
|
||||||
depends_on = None
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade():
|
|
||||||
op.create_table(
|
|
||||||
'corpus_followers',
|
|
||||||
sa.Column('user_id', sa.Integer(), nullable=False),
|
|
||||||
sa.Column('corpus_id', sa.Integer(), nullable=False),
|
|
||||||
sa.ForeignKeyConstraint(['corpus_id'], ['corpora.id'], ),
|
|
||||||
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
|
|
||||||
sa.PrimaryKeyConstraint('user_id', 'corpus_id')
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def downgrade():
|
|
||||||
op.drop_table('corpus_followers')
|
|
36
migrations/versions/5fe6a6c7870c_.py
Normal file
36
migrations/versions/5fe6a6c7870c_.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: 5fe6a6c7870c
|
||||||
|
Revises: 5b2a6e590166
|
||||||
|
Create Date: 2023-01-23 08:27:10.169454
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '5fe6a6c7870c'
|
||||||
|
down_revision = '5b2a6e590166'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table('corpus_follower_associations',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('following_user_id', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('followed_corpus_id', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('permissions', sa.Integer(), nullable=False),
|
||||||
|
sa.ForeignKeyConstraint(['followed_corpus_id'], ['corpora.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['following_user_id'], ['users.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_table('corpus_follower_associations')
|
||||||
|
# ### end Alembic commands ###
|
@ -1,31 +0,0 @@
|
|||||||
"""Add user_followers table
|
|
||||||
|
|
||||||
Revision ID: 7d51bc4b6079
|
|
||||||
Revises: 4aa88f253dab
|
|
||||||
Create Date: 2023-01-17 12:48:33.261942
|
|
||||||
|
|
||||||
"""
|
|
||||||
from alembic import op
|
|
||||||
import sqlalchemy as sa
|
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
|
||||||
revision = '7d51bc4b6079'
|
|
||||||
down_revision = '4aa88f253dab'
|
|
||||||
branch_labels = None
|
|
||||||
depends_on = None
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade():
|
|
||||||
op.create_table(
|
|
||||||
'user_followers',
|
|
||||||
sa.Column('follower_user_id', sa.Integer(), nullable=False),
|
|
||||||
sa.Column('followed_user_id', sa.Integer(), nullable=False),
|
|
||||||
sa.ForeignKeyConstraint(['followed_user_id'], ['users.id'], ),
|
|
||||||
sa.ForeignKeyConstraint(['follower_user_id'], ['users.id'], ),
|
|
||||||
sa.PrimaryKeyConstraint('follower_user_id', 'followed_user_id')
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def downgrade():
|
|
||||||
op.drop_table('user_followers')
|
|
@ -8,6 +8,7 @@ from app.models import (
|
|||||||
Avatar,
|
Avatar,
|
||||||
Corpus,
|
Corpus,
|
||||||
CorpusFile,
|
CorpusFile,
|
||||||
|
CorpusFollowerAssociation,
|
||||||
Job,
|
Job,
|
||||||
JobInput,
|
JobInput,
|
||||||
JobResult,
|
JobResult,
|
||||||
@ -38,6 +39,7 @@ def make_shell_context() -> Dict[str, Any]:
|
|||||||
'Avatar': Avatar,
|
'Avatar': Avatar,
|
||||||
'Corpus': Corpus,
|
'Corpus': Corpus,
|
||||||
'CorpusFile': CorpusFile,
|
'CorpusFile': CorpusFile,
|
||||||
|
'CorpusFollowerAssociation': CorpusFollowerAssociation,
|
||||||
'db': db,
|
'db': db,
|
||||||
'Job': Job,
|
'Job': Job,
|
||||||
'JobInput': JobInput,
|
'JobInput': JobInput,
|
||||||
|
Loading…
Reference in New Issue
Block a user