示例#1
0
class MessageModel(db.Model):
    __tablename__ = 'message'

    id = db.Column(db.Integer, primary_key=True)
    from_user_id = db.Column(db.Integer(), nullable=False, index=True)
    to_user_id = db.Column(db.Integer(), nullable=False, index=True)
    title = db.Column(db.String(512), nullable=False)
    content = db.Column(db.UnicodeText(), nullable=False)
    is_read = db.Column(db.Boolean(),
                        server_default=sql.false(),
                        nullable=False,
                        index=True)
    date_created = db.Column(db.DateTime,
                             nullable=False,
                             index=True,
                             server_default=db.func.current_timestamp())

    @staticmethod
    def get_unread_count(user_id):
        return MessageModel.query.filter(
            MessageModel.to_user_id == user_id,
            MessageModel.is_read.is_(False),
        ).count()

    def as_dict(self):
        return {
            'id': self.id,
            'title': self.title,
        }

    def __repr__(self):
        return '<Message %r>' % self.title
示例#2
0
class NewsModel(db.Model):
    __tablename__ = 'news'

    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer(), nullable=False, index=True)
    title = db.Column(db.String(512), nullable=False)
    content = db.Column(db.UnicodeText(), nullable=False)
    is_display = db.Column(db.Boolean,
                           default=True,
                           server_default=sql.true(),
                           nullable=False,
                           index=True)
    date_created = db.Column(db.DateTime,
                             nullable=False,
                             index=True,
                             server_default=db.func.current_timestamp())

    @property
    def url(self):
        return url_for('news.detail', news_id=self.id)

    def as_dict(self):
        return {
            'id': self.id,
            'title': self.title,
        }

    @staticmethod
    def generate_fake(count=100):
        from sqlalchemy.exc import IntegrityError
        from random import seed, randint
        import forgery_py

        seed()
        user_count = UserModel.query.count()
        if user_count == 0:
            UserModel.generate_fake()
            user_count = UserModel.query.count()
        for i in range(count):
            u = UserModel.query.offset(randint(0, user_count - 1)).first()
            n = NewsModel(user_id=u.id,
                          title=forgery_py.lorem_ipsum.title(),
                          content=forgery_py.lorem_ipsum.paragraphs())
            db.session.add(n)
            try:
                db.session.commit()
            except IntegrityError:
                db.session.rollback()

    def __repr__(self):
        return '<News %r>' % self.title
示例#3
0
class RegistryModel(db.Model):
    __tablename__ = 'registry'

    key = db.Column(db.String(100), nullable=False, primary_key=True)
    name = db.Column(db.Unicode(1024), nullable=False)
    meta = db.Column(JSON, nullable=False, default=[])
    value = db.Column(JSON, default=[])

    def as_dict(self):
        return {'key': self.key, 'name': self.name, 'value': self.value}

    def save_to_cache(self):
        if app.config['TESTING']:
            return
        redis.set(self.redis_key(self.key), json.dumps(self.value))

    @classmethod
    def get_from_cache(cls, key):
        if app.config['TESTING']:
            return
        raw = redis.get(cls.redis_key(key))
        if raw:
            return json.loads(raw)

    @classmethod
    def fetch(cls, key):
        value = cls.get_from_cache(key)
        if value is not None:
            return value
        registry = cls.query.get(key)
        if registry:
            registry.save_to_cache()
            return registry.value
        return []

    @classmethod
    def redis_key(cls, key):
        return 'admin-registry::%s' % key
示例#4
0
class RoleModel(db.Model):
    __tablename__ = 'role'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True, index=True)
    default = db.Column(db.Boolean,
                        default=False,
                        index=True,
                        server_default=sql.false())
    permissions = db.Column(db.Integer)
    date_created = db.Column(db.DateTime,
                             nullable=False,
                             server_default=db.func.current_timestamp())

    @staticmethod
    def insert_roles():
        roles = {
            'User': (Permission.SUBMIT, True),
            'Teacher': (Permission.SUBMIT | Permission.VIEW_CODE, False),
            'Administrator': (0xff, False)
        }
        for r in roles:
            role = RoleModel.query.filter_by(name=r).first()
            if role is None:
                role = RoleModel(name=r)
            role.permissions = roles[r][0]
            role.default = roles[r][1]
            db.session.add(role)
        db.session.commit()

    def __repr__(self):
        return '<Role %r>' % self.name

    def as_dict(self):
        return {
            'id': self.id,
            'name': self.name,
            'permissions': self.permissions,
        }
示例#5
0
class ProblemModel(db.Model):
    __tablename__ = 'problem'

    id = db.Column(db.Integer,
                   Sequence('problem_id_seq', start=1000, increment=1),
                   primary_key=True)
    title = db.Column(db.String(512), nullable=False)
    time_limit = db.Column(db.Integer, nullable=False)
    memory_limit = db.Column(db.Integer, nullable=False)
    description = db.Column(db.UnicodeText())
    input = db.Column(db.UnicodeText())
    output = db.Column(db.UnicodeText())
    sample_input = db.Column(db.UnicodeText())
    sample_output = db.Column(db.UnicodeText())
    sample_code = db.Column(db.UnicodeText())
    hint = db.Column(db.UnicodeText())
    source = db.Column(db.String(512))
    author = db.Column(db.String(128))
    is_display = db.Column(db.Boolean,
                           default=True,
                           server_default=sql.true(),
                           nullable=True,
                           index=True)
    is_special_judge = db.Column(db.Boolean,
                                 default=False,
                                 server_default=sql.false(),
                                 nullable=True,
                                 index=True)
    date_modified = db.Column(db.DateTime,
                              nullable=False,
                              index=True,
                              server_default=db.func.current_timestamp())
    date_created = db.Column(db.DateTime,
                             nullable=False,
                             index=True,
                             server_default=db.func.current_timestamp())

    _statistics = db.relationship(
        'ProblemStatisticsModel',
        primaryjoin='ProblemModel.id==ProblemStatisticsModel.id',
        foreign_keys='[ProblemStatisticsModel.id]',
        backref='problem',
        uselist=False,
        passive_deletes='all')

    solutions = db.relationship(
        'SolutionModel',
        primaryjoin='SolutionModel.problem_id==ProblemModel.id',
        foreign_keys='[SolutionModel.problem_id]',
        backref=db.backref('problem', uselist=False, lazy=True),
        order_by='SolutionModel.date_created.desc()',
        passive_deletes='all',
        lazy='dynamic')

    accepts = db.relationship(
        'SolutionModel',
        primaryjoin=
        'and_(SolutionModel.problem_id==ProblemModel.id, SolutionModel.result==1)',
        foreign_keys='[SolutionModel.problem_id]',
        order_by='SolutionModel.date_created.desc()',
        passive_deletes='all',
        lazy='dynamic')

    solution_users = db.relationship(
        'UserModel',
        secondary=lambda: SolutionModel.__table__,
        primaryjoin='ProblemModel.id==SolutionModel.problem_id',
        secondaryjoin='UserModel.id==SolutionModel.user_id',
        order_by='SolutionModel.date_created.desc()',
        foreign_keys='[SolutionModel.user_id, SolutionModel.problem_id]',
        lazy='dynamic')

    accept_users = db.relationship(
        'UserModel',
        secondary=lambda: SolutionModel.__table__,
        primaryjoin=
        'and_(SolutionModel.problem_id==ProblemModel.id, SolutionModel.result==1)',
        secondaryjoin='UserModel.id==SolutionModel.user_id',
        order_by='SolutionModel.date_created.desc()',
        foreign_keys='[SolutionModel.user_id, SolutionModel.problem_id]',
        lazy='dynamic')

    def __init__(self, **kwargs):
        super(ProblemModel, self).__init__(**kwargs)
        self._statistics = ProblemStatisticsModel()

    @staticmethod
    def generate_fake(count=100):
        from sqlalchemy.exc import IntegrityError
        from random import seed, randint, choice
        import forgery_py

        seed()
        for i in range(count):
            p = ProblemModel(title=forgery_py.lorem_ipsum.title(),
                             time_limit=randint(1, 5) * 1000,
                             memory_limit=choice([2 << 14, 2 << 15]),
                             description=forgery_py.lorem_ipsum.paragraphs(),
                             input=forgery_py.lorem_ipsum.paragraphs(),
                             output=forgery_py.lorem_ipsum.paragraphs(),
                             sample_input=forgery_py.lorem_ipsum.paragraphs(),
                             sample_output=forgery_py.lorem_ipsum.paragraphs(),
                             sample_code=forgery_py.lorem_ipsum.paragraphs(),
                             hint=forgery_py.lorem_ipsum.paragraphs(),
                             source=forgery_py.internet.domain_name(),
                             author=forgery_py.internet.user_name(True),
                             is_display=choice([True, False]),
                             is_special_judge=choice([True, False]))
            db.session.add(p)
            try:
                db.session.commit()
            except IntegrityError:
                db.session.rollback()

    @hybrid_property
    def solutions_count(self):
        if self._statistics:
            return self._statistics.solutions_count
        else:
            return 0

    @solutions_count.setter
    def solutions_count_setter(self, value):
        if not self._statistics:
            self._statistics = ProblemStatisticsModel()
        self._statistics.solutions_count = value

    @solutions_count.expression
    def solutions_count_expr(cls):
        return ProblemStatisticsModel.solutions_count

    @hybrid_property
    def accepts_count(self):
        if self._statistics:
            return self._statistics.accepts_count
        else:
            return 0

    @accepts_count.setter
    def accepts_count_setter(self, value):
        if not self._statistics:
            self._statistics = ProblemStatisticsModel()
        self._statistics.accepts_count = value

    @accepts_count.expression
    def accepts_count_expr(cls):
        return ProblemStatisticsModel.accepts_count

    @hybrid_property
    def solution_users_count(self):
        if self._statistics:
            return self._statistics.solution_users_count
        else:
            return 0

    @solution_users_count.setter
    def solution_users_count_setter(self, value):
        if not self._statistics:
            self._statistics = ProblemStatisticsModel()
        self._statistics.solution_users_count = value

    @solution_users_count.expression
    def solution_users_count_expr(cls):
        return ProblemStatisticsModel.solution_users_count

    @hybrid_property
    def accept_users_count(self):
        if self._statistics:
            return self._statistics.accept_users_count
        else:
            return 0

    @accept_users_count.setter
    def accept_users_count_setter(self, value):
        if not self._statistics:
            self._statistics = ProblemStatisticsModel()
        self._statistics.accept_users_count = value

    @accept_users_count.expression
    def accept_users_count_expr(cls):
        return ProblemStatisticsModel.accept_users_count

    @property
    def url(self):
        return url_for('problem.detail', problem_id=self.id)

    @property
    def ratio(self):
        return '%.f%%' % round(
            self.accepts_count * 100.0 /
            self.solutions_count if self.solutions_count else 0)

    @classmethod
    def __declare_last__(cls):
        cls.current_user_has_solved = db.column_property(db.and_(
            db.current_user_id().isnot(None),
            db.exists().where(SolutionModel.user_id == db.current_user_id()).
            where(SolutionModel.problem_id == cls.id).where(
                SolutionModel.result == 1).correlate_except(SolutionModel)),
                                                         deferred=True)
        cls.current_user_has_submitted = db.column_property(db.and_(
            db.current_user_id().isnot(None),
            db.exists().where(
                SolutionModel.user_id == db.current_user_id()).where(
                    SolutionModel.problem_id == cls.id).correlate_except(
                        SolutionModel)),
                                                            deferred=True)

    def as_dict(self):
        return {
            'id': self.id,
            'title': self.title,
            'time_limit': self.time_limit,
            'memory_limit': self.memory_limit,
            'description': self.description,
            'input': self.input,
            'output': self.output,
            'sample_input': self.sample_input,
            'sample_output': self.sample_output,
            'sample_code': self.sample_code,
            'hint': self.hint,
            'source': self.source,
            'author': self.author,
            'is_display': self.is_display,
            'is_special_judge': self.is_special_judge,
            'date_modified': self.date_modified,
            'date_created': self.date_created,
            'solutions_count': self.solutions_count,
            'accepts_count': self.accepts_count,
            'ratio': self.ratio,
            'url': self.url,
            'current_user_has_solved': self.current_user_has_solved,
            'current_user_has_submitted': self.current_user_has_submitted,
        }

    def __repr__(self):
        return '<Problem %r>' % self.title
示例#6
0
class UserModel(UserMixin, db.Model):
    __tablename__ = 'user'

    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(256),
                         unique=True,
                         index=True,
                         nullable=False)
    nickname = db.Column(db.String(256),
                         unique=True,
                         index=True,
                         nullable=False)
    email = db.Column(db.String(256), unique=True, index=True, nullable=False)
    password_hash = db.Column(db.String(128), nullable=False)
    gender = db.Column(db.Enum('male', 'female', name='user_gender'))
    school = db.Column(db.String(256))
    college = db.Column(db.String(256))
    major = db.Column(db.String(256))
    grade = db.Column(db.String(64))
    clazz = db.Column(db.String(64))
    program_language = db.Column(
        db.Enum('gcc', 'g++', 'java', name='user_program_language_enum'))
    avatar = db.Column(db.String(256))
    qq = db.Column(db.String(64))
    phone = db.Column(db.String(64))
    address = db.Column(db.String(256))
    role_id = db.Column(db.Integer)
    is_bulk_registration = db.Column(db.Boolean,
                                     default=False,
                                     server_default=sql.false(),
                                     nullable=True)
    confirmed = db.Column(db.Boolean,
                          default=False,
                          server_default=sql.false(),
                          nullable=False)
    last_login_ip = db.Column(db.String(64))
    current_login_ip = db.Column(db.String(64))
    login_count = db.Column(db.Integer())
    date_last_login = db.Column(db.DateTime,
                                nullable=False,
                                server_default=db.func.current_timestamp())
    date_current_login = db.Column(db.DateTime,
                                   nullable=False,
                                   server_default=db.func.current_timestamp())
    date_created = db.Column(db.DateTime,
                             nullable=False,
                             index=True,
                             server_default=db.func.current_timestamp())

    _statistics = db.relationship(
        'UserStatisticsModel',
        primaryjoin='UserModel.id==UserStatisticsModel.id',
        foreign_keys='[UserStatisticsModel.id]',
        backref='user',
        uselist=False,
        cascade="all, delete-orphan",
    )

    favorites = db.relationship(
        'ProblemModel',
        secondary=lambda: UserFavoritesModel.__table__,
        primaryjoin='UserModel.id==UserFavoritesModel.user_id',
        secondaryjoin='ProblemModel.id==UserFavoritesModel.problem_id',
        order_by='UserFavoritesModel.date_created.desc()',
        foreign_keys=
        '[UserFavoritesModel.problem_id, UserFavoritesModel.user_id]',
        lazy='dynamic')

    message_sent = db.relationship(
        'MessageModel',
        primaryjoin='MessageModel.from_user_id==UserModel.id',
        foreign_keys='[MessageModel.from_user_id]',
        backref=db.backref('user', lazy=True, uselist=False),
        order_by='MessageModel.date_created.desc()',
        lazy='dynamic')

    message_received = db.relationship(
        'MessageModel',
        primaryjoin='MessageModel.to_user_id==UserModel.id',
        foreign_keys='[MessageModel.to_user_id]',
        order_by='MessageModel.date_created.desc()',
        lazy='dynamic')

    news = db.relationship('NewsModel',
                           primaryjoin='NewsModel.user_id==UserModel.id',
                           foreign_keys='[NewsModel.user_id]',
                           backref=db.backref('user', lazy=True,
                                              uselist=False),
                           order_by='NewsModel.date_created.desc()',
                           lazy='dynamic')

    headlines = db.relationship(
        'HeadlineModel',
        primaryjoin='HeadlineModel.user_id==UserModel.id',
        foreign_keys='[HeadlineModel.user_id]',
        backref=db.backref('user', lazy=True, uselist=False),
        order_by='HeadlineModel.date_created.desc()',
        lazy='dynamic')

    solutions = db.relationship(
        'SolutionModel',
        primaryjoin='SolutionModel.user_id==UserModel.id',
        foreign_keys='[SolutionModel.user_id]',
        backref=db.backref('user', lazy=True, uselist=False),
        order_by='SolutionModel.date_created.desc()',
        passive_deletes='all',
        lazy='dynamic')

    accepts = db.relationship(
        'SolutionModel',
        primaryjoin=
        'and_(SolutionModel.user_id==UserModel.id, SolutionModel.result==1)',
        foreign_keys='[SolutionModel.user_id]',
        order_by='SolutionModel.date_created.desc()',
        passive_deletes='all',
        lazy='dynamic')

    role = db.relationship('RoleModel',
                           primaryjoin='UserModel.role_id==RoleModel.id',
                           foreign_keys='[UserModel.role_id]',
                           backref=db.backref('user', lazy='dynamic'),
                           lazy=True)

    def __init__(self, **kwargs):
        super(UserModel, self).__init__(**kwargs)
        self._statistics = UserStatisticsModel()

    @property
    def email_md5(self):
        email = self.email.strip()
        if isinstance(email, unicode):
            email = email.encode('utf-8')
        return md5(email).hexdigest()

    def g_avatar(self, size=48, default='retro', rating='g'):
        return "{url}{hash}?d={default}&s={size}".format(
            url=current_app.config['GRAVATAR_BASE_URL'],
            hash=self.email_md5,
            default=default,
            size=size,
            rating=rating)

    @staticmethod
    def generate_fake(count=100):
        from sqlalchemy.exc import IntegrityError
        from random import seed
        import forgery_py

        seed()
        for i in range(count):
            u = UserModel(username=forgery_py.internet.user_name(True),
                          nickname=forgery_py.internet.user_name(True),
                          email=forgery_py.internet.email_address(),
                          password='******')
            db.session.add(u)
            try:
                db.session.commit()
            except IntegrityError:
                db.session.rollback()

    @property
    def url(self):
        return url_for('profile.profile', user_id=self.id)

    @property
    def password(self):
        raise AttributeError('password is not a readable attribute')

    @password.setter
    def password(self, password):
        self.password_hash = generate_password_hash(password)

    def verify_password(self, password):
        return check_password_hash(self.password_hash, password)

    def generate_reset_token(self, expiration=3600):
        s = Serializer(current_app.config['SECRET_KEY'], expiration)
        return s.dumps({'reset': self.id})

    def reset_password(self, token, new_password):
        s = Serializer(current_app.config['SECRET_KEY'])
        try:
            data = s.loads(token)
        except:
            return False
        if data.get('reset') != self.id:
            return False
        self.password = new_password
        db.session.add(self)
        db.session.commit()
        return True

    def generate_confirmation_token(self, expiration=3600):
        s = Serializer(current_app.config['SECRET_KEY'], expiration)
        return s.dumps({'confirm': self.id})

    def confirm(self, token):
        s = Serializer(current_app.config['SECRET_KEY'])
        try:
            data = s.loads(token)
        except:
            return False
        if data.get('confirm') != self.id:
            return False
        self.confirmed = True
        db.session.add(self)
        db.session.commit()
        return True

    def generate_email_change_token(self, new_email, expiration=3600):
        s = Serializer(current_app.config['SECRET_KEY'], expiration)
        return s.dumps({'change_email': self.id, 'new_email': new_email})

    def change_email(self, token):
        s = Serializer(current_app.config['SECRET_KEY'])
        try:
            data = s.loads(token)
        except:
            return False
        if data.get('change_email') != self.id:
            return False
        new_email = data.get('new_email')
        if new_email is None:
            return False
        self.email = new_email
        db.session.add(self)
        db.session.commit()
        return True

    @hybrid_property
    def solutions_count(self):
        if self._statistics:
            return self._statistics.solutions_count
        else:
            return 0

    @solutions_count.setter
    def solutions_count_setter(self, value):
        if not self._statistics:
            self._statistics = UserStatisticsModel()
        self._statistics.solutions_count = value

    @solutions_count.expression
    def solutions_count_expr(cls):
        return UserStatisticsModel.solutions_count

    @hybrid_property
    def accepts_count(self):
        if self._statistics:
            return self._statistics.accepts_count
        else:
            return 0

    @accepts_count.setter
    def accepts_count_setter(self, value):
        if not self._statistics:
            self._statistics = UserStatisticsModel()
        self._statistics.accepts_count = value

    @accepts_count.expression
    def accepts_count_expr(cls):
        return UserStatisticsModel.accepts_count

    @property
    def ratio(self):
        return '%.f%%' % round(
            self.accepts_count * 100.0 /
            self.solutions_count if self.solutions_count else 0)

    def can(self, permissions):
        return (self.role is not None
                and (self.role.permissions & permissions) == permissions)

    def is_administrator(self):
        return self.can(Permission.ADMINISTER)

    def as_dict(self):
        return {
            'id': self.id,
            'username': self.username,
        }

    def __repr__(self):
        return '<User %r>' % self.username
示例#7
0
class ContestUserModel(db.Model):
    __tablename__ = 'contest_user'

    id = db.Column(db.Integer, primary_key=True)
    contest_id = db.Column(db.Integer(), nullable=False, index=True)
    team_name = db.Column(db.Unicode(256), nullable=False)
    status = db.Column(db.Enum('accept',
                               'waiting',
                               'reject',
                               'again',
                               name='contest_user_status_enum'),
                       server_default='waiting',
                       nullable=False,
                       index=True)
    seat_number = db.Column(db.Unicode(128))
    reason = db.Column(db.Unicode(256))
    user_id = db.Column(db.Integer(), nullable=False, index=True)

    student_id = db.Column(db.String(32))
    name = db.Column(db.Unicode(256))
    school = db.Column(db.Unicode(256))
    college = db.Column(db.Unicode(256))
    major = db.Column(db.Unicode(256))
    clazz = db.Column(db.Unicode(256))
    phone = db.Column(db.String(32))
    email = db.Column(db.String(256))
    student_id1 = db.Column(db.String(32))
    name1 = db.Column(db.Unicode(256))
    school1 = db.Column(db.Unicode(256))
    college1 = db.Column(db.Unicode(256))
    major1 = db.Column(db.Unicode(256))
    clazz1 = db.Column(db.Unicode(256))
    phone1 = db.Column(db.String(32))
    email1 = db.Column(db.String(256))
    student_id2 = db.Column(db.String(32))
    name2 = db.Column(db.Unicode(256))
    school2 = db.Column(db.Unicode(256))
    college2 = db.Column(db.Unicode(256))
    major2 = db.Column(db.Unicode(256))
    clazz2 = db.Column(db.Unicode(256))
    phone2 = db.Column(db.String(32))
    email2 = db.Column(db.String(256))
    date_created = db.Column(db.DateTime,
                             nullable=False,
                             index=True,
                             server_default=db.func.current_timestamp())

    solutions = db.relationship(
        'SolutionModel',
        primaryjoin=
        'and_(SolutionModel.user_id==ContestUserModel.user_id, SolutionModel.contest_id==ContestUserModel.contest_id)',
        foreign_keys='[SolutionModel.user_id, SolutionModel.contest_id]',
        backref=db.backref('contest_user', lazy=True),
        order_by='SolutionModel.date_created.desc()',
        passive_deletes='all',
        lazy='dynamic')

    accepts = db.relationship(
        'SolutionModel',
        primaryjoin=
        'and_(SolutionModel.user_id==ContestUserModel.user_id, SolutionModel.contest_id==ContestUserModel.contest_id, SolutionModel.result==1)',
        foreign_keys='[SolutionModel.user_id, SolutionModel.contest_id]',
        order_by='SolutionModel.date_created.desc()',
        passive_deletes='all',
        lazy='dynamic')

    def as_dict(self):
        return {
            'id': self.id,
        }

    def __repr__(self):
        return '<ContestUser %r>' % self.id
示例#8
0
class ContestModel(db.Model):
    __tablename__ = 'contest'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.Unicode(512), nullable=False)
    date_start = db.Column(db.DateTime, nullable=False)
    date_end = db.Column(db.DateTime, nullable=False)
    description = db.Column(db.UnicodeText)
    type = db.Column(db.Enum('public',
                             'private',
                             'register',
                             'diy',
                             name='contest_type_enum'),
                     server_default='public',
                     nullable=False)
    user_id = db.Column(db.Integer(), nullable=False, index=True)
    password_hash = db.Column(db.String(128))
    date_start_register = db.Column(db.DateTime)
    date_end_register = db.Column(db.DateTime)
    is_hidden = db.Column(db.Boolean,
                          default=False,
                          server_default=sql.false(),
                          nullable=True)
    date_created = db.Column(db.DateTime,
                             nullable=False,
                             index=True,
                             server_default=db.func.current_timestamp())

    user = db.relationship('UserModel',
                           primaryjoin='UserModel.id==ContestModel.user_id',
                           foreign_keys='[ContestModel.user_id]',
                           lazy=True)

    contest_users = db.relationship(
        'ContestUserModel',
        primaryjoin=
        'and_(ContestUserModel.contest_id==ContestModel.id, ContestModel.type=="register")',
        foreign_keys='[ContestUserModel.contest_id]',
        backref=db.backref('contest', lazy=True),
        passive_deletes='all',
        lazy='dynamic')

    solutions = db.relationship(
        'SolutionModel',
        primaryjoin='SolutionModel.contest_id==ContestModel.id',
        foreign_keys='[SolutionModel.contest_id]',
        backref=db.backref('contest', lazy=True, uselist=False),
        order_by='SolutionModel.date_created.desc()',
        passive_deletes='all',
        lazy='dynamic')

    problems = db.relationship(
        'ContestProblemModel',
        primaryjoin='ContestProblemModel.contest_id==ContestModel.id',
        foreign_keys='[ContestProblemModel.contest_id]',
        backref=db.backref('contest', lazy=True),
        order_by='(ContestProblemModel.ordinal, ContestProblemModel.id)',
        passive_deletes='all',
        lazy='dynamic')

    @staticmethod
    def generate_fake(count=100):
        from sqlalchemy.exc import IntegrityError
        from random import seed, randint, choice
        import forgery_py

        seed()
        now = datetime.datetime.now()
        user_count = UserModel.query.count()
        if user_count == 0:
            UserModel.generate_fake()
            user_count = UserModel.query.count()
        for i in range(count):
            date_start = now + datetime.timedelta(randint(-100, 100))
            date_end = date_start + datetime.timedelta(hours=randint(2, 10))
            date_end_register = date_start - datetime.timedelta(randint(1, 5))
            date_start_register = date_end_register - datetime.timedelta(
                randint(1, 10))
            u = UserModel.query.offset(randint(0, user_count - 1)).first()
            c = ContestModel(
                name=forgery_py.lorem_ipsum.title(),
                date_start=date_start,
                date_end=date_end,
                description=forgery_py.lorem_ipsum.paragraph(),
                type=choice(['public', 'private', 'register', 'diy']),
                user_id=u.id,
                password='******',
                date_start_register=date_start_register,
                date_end_register=date_end_register,
            )
            db.session.add(c)
            try:
                db.session.commit()
            except IntegrityError:
                db.session.rollback()

    @property
    def url(self):
        return url_for('contest.detail', contest_id=self.id)

    @property
    def status(self):
        now = datetime.datetime.now()
        if now < self.date_start:
            status = 'pending'
        elif now > self.date_end:
            status = 'ended'
        else:
            status = 'running'
        return status

    @property
    def password(self):
        raise AttributeError('password is not a readable attribute')

    @password.setter
    def password(self, password):
        self.password_hash = generate_password_hash(password)

    def verify_password(self, password):
        return check_password_hash(self.password_hash, password)

    def as_dict(self):
        return {
            'id': self.id,
            'name': self.name,
        }

    def __repr__(self):
        return '<Contest %r>' % self.name