Browse Source

Add stuff for FTS

master
Dashie der otter 4 years ago
parent
commit
dcbc546866
3 changed files with 103 additions and 188 deletions
  1. 30
    0
      migrations/versions/49f64ff8b271_.py
  2. 72
    188
      models.py
  3. 1
    0
      requirements.txt

+ 30
- 0
migrations/versions/49f64ff8b271_.py View File

@@ -0,0 +1,30 @@
"""Full Text Search support

Revision ID: 49f64ff8b271
Revises: 1ee3b258c782
Create Date: 2015-10-06 13:35:02.740430

"""

# revision identifiers, used by Alembic.
revision = '49f64ff8b271'
down_revision = '1ee3b258c782'

from alembic import op
import sqlalchemy as sa
from sqlalchemy_utils.types import TSVectorType



def upgrade():
### commands auto generated by Alembic - please adjust! ###
op.add_column('part', sa.Column('search_vector', TSVectorType(), nullable=True))
op.create_index('ix_part_search_vector', 'part', ['search_vector'], unique=False, postgresql_using='gin')
### end Alembic commands ###


def downgrade():
### commands auto generated by Alembic - please adjust! ###
op.drop_index('ix_part_search_vector', table_name='part')
op.drop_column('part', 'search_vector')
### end Alembic commands ###

+ 72
- 188
models.py View File

@@ -2,81 +2,55 @@ from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.security import SQLAlchemyUserDatastore, \
UserMixin, RoleMixin
from sqlalchemy_mptt.mixins import BaseNestedSets

from sqlalchemy import event
from barcode_utils import generate_ean13
from flask import current_app
from sqlalchemy_utils.types import TSVectorType
from sqlalchemy_searchable import make_searchable


import os.path

db = SQLAlchemy()
make_searchable()


roles_users = db.Table('roles_users',
db.Column('user_id', db.Integer(),
db.ForeignKey('user.id')),
db.Column('role_id', db.Integer(),
db.ForeignKey('role.id')))
db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
db.Column('role_id', db.Integer(), db.ForeignKey('role.id')))


class Role(db.Model, RoleMixin):
id = db.Column(db.Integer(), primary_key=True)
name = db.Column(
db.String(80),
unique=True,
nullable=False,
info={'label': 'Name'})
description = db.Column(
db.String(255),
info={'label': 'Description'})
__mapper_args__ = {
"order_by": name
}
name = db.Column(db.String(80), unique=True, nullable=False, info={'label': 'Name'})
description = db.Column(db.String(255), info={'label': 'Description'})

__mapper_args__ = {"order_by": name}


class User(db.Model, UserMixin):
BARCODE_TYPE = 10
id = db.Column(db.Integer, primary_key=True)
email = db.Column(
db.String(255),
unique=True,
nullable=False,
info={'label': 'Email'}
)
name = db.Column(
db.String(255),
unique=True,
nullable=False,
info={'label': 'Name'}
)
password = db.Column(
db.String(255),
nullable=False,
info={'label': 'Password'}
)
email = db.Column(db.String(255), unique=True, nullable=False, info={'label': 'Email'})
name = db.Column(db.String(255), unique=True, nullable=False, info={'label': 'Name'})
password = db.Column(db.String(255), nullable=False, info={'label': 'Password'})
active = db.Column(db.Boolean())
confirmed_at = db.Column(db.DateTime())
barcode_str = db.Column(db.String(13), nullable=True, info={'label': 'Barcode string'}, default="0000000000000")

roles = db.relationship('Role', secondary=roles_users,
backref=db.backref('users', lazy='dynamic'))
roles = db.relationship('Role', secondary=roles_users, backref=db.backref('users', lazy='dynamic'))
parts = db.relationship('Part', backref='user', lazy='dynamic')
apitokens = db.relationship('Apitoken', backref='user', lazy='dynamic')
__mapper_args__ = {
"order_by": name
}

__mapper_args__ = {"order_by": name}


class Apitoken(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer(), db.ForeignKey('user.id'), nullable=False)
token = db.Column(db.String(),
unique=True,
nullable=False,
info={'label': 'Token'}
)
secret = db.Column(db.String(),
unique=True,
nullable=False,
info={'label': 'Secret'}
)
token = db.Column(db.String(), unique=True, nullable=False, info={'label': 'Token'})
secret = db.Column(db.String(), unique=True, nullable=False, info={'label': 'Secret'})


user_datastore = SQLAlchemyUserDatastore(db, User, Role)
@@ -90,16 +64,11 @@ class PartCategory(db.Model, BaseNestedSets):
parent = db.Column(db.Integer, nullable=True, default=None)
parts = db.relationship('Part', backref='part_category', lazy='dynamic')

__mapper_args__ = {
"order_by": name
}
__mapper_args__ = {"order_by": name}

def __repr__(self):
# return u"<Node (%s)>" % self.id
if self.parent:
return u"{0} - {1}".format(self.parent.name, self.name)
else:
return self.name
return u"{0} - {1}".format(self.parent.name, self.name) if self.parent else self.name


class Unit(db.Model):
@@ -113,9 +82,7 @@ class Unit(db.Model):
description = db.Column(db.String(255), unique=False, nullable=True)
parameters = db.relationship('PartParameter', backref='unit', lazy='dynamic')

__mapper_args__ = {
"order_by": name
}
__mapper_args__ = {"order_by": name}

def __repr__(self):
return u"{1}{2} ({0})".format(self.name, self.prefix, self.symbol)
@@ -128,9 +95,7 @@ class PartMeasurementUnit(db.Model):
description = db.Column(db.String(255), unique=False, nullable=True)
parts = db.relationship('Part', backref='part_measurement_unit', lazy='dynamic')

__mapper_args__ = {
"order_by": name
}
__mapper_args__ = {"order_by": name}

def __repr__(self):
return u"{0} ({1})".format(self.name, self.short_name)
@@ -139,145 +104,67 @@ class PartMeasurementUnit(db.Model):
class Manufacturer(db.Model):
BARCODE_TYPE = 15
id = db.Column(db.Integer, primary_key=True)
name = db.Column(
db.String(255),
unique=True,
nullable=False,
info={'label': 'Name'}
)
address = db.Column(
db.String(255),
nullable=True,
info={'label': 'Address'}
)
url = db.Column(
db.String(255),
nullable=True,
info={'label': 'URL'}
)
email = db.Column(
db.String(255),
nullable=True,
info={'label': 'Email'}
)
comment = db.Column(
db.String(255),
nullable=True,
info={'label': 'Comment'}
)
phone = db.Column(
db.String(255),
nullable=True,
info={'label': 'Phone'}
)
fax = db.Column(
db.String(255),
nullable=True,
info={'label': 'FAX'}
)
name = db.Column(db.String(255), unique=True, nullable=False, info={'label': 'Name'})
address = db.Column(db.String(255), nullable=True, info={'label': 'Address'})
url = db.Column(db.String(255), nullable=True, info={'label': 'URL'})
email = db.Column(db.String(255), nullable=True, info={'label': 'Email'})
comment = db.Column(db.String(255), nullable=True, info={'label': 'Comment'})
phone = db.Column(db.String(255), nullable=True, info={'label': 'Phone'})
fax = db.Column(db.String(255), nullable=True, info={'label': 'FAX'})
barcode_str = db.Column(db.String(13), nullable=True, info={'label': 'Barcode string'}, default="0000000000000")
# ICs Logos
__mapper_args__ = {
"order_by": name
}

part_manufacturers = db.relationship('PartManufacturer', backref='manufacturer', lazy='dynamic')

__mapper_args__ = {"order_by": name}


class Distributor(db.Model):
BARCODE_TYPE = 20
id = db.Column(db.Integer, primary_key=True)
name = db.Column(
db.String(255),
unique=True,
nullable=False,
info={'label': 'Name'}
)
address = db.Column(
db.String(255),
nullable=True,
info={'label': 'Address'}
)
url = db.Column(
db.String(255),
nullable=True,
info={'label': 'URL'}
)
email = db.Column(
db.String(255),
nullable=True,
info={'label': 'Email'}
)
comment = db.Column(
db.String(255),
nullable=True,
info={'label': 'Comment'}
)
phone = db.Column(
db.String(255),
nullable=True,
info={'label': 'Phone'}
)
fax = db.Column(
db.String(255),
nullable=True,
info={'label': 'FAX'}
)
skuurl = db.Column(
db.String(255),
nullable=True,
info={'label': 'SKU Url'}
)
name = db.Column(db.String(255), unique=True, nullable=False, info={'label': 'Name'})
address = db.Column(db.String(255), nullable=True, info={'label': 'Address'})
url = db.Column(db.String(255), nullable=True, info={'label': 'URL'})
email = db.Column(db.String(255), nullable=True, info={'label': 'Email'})
comment = db.Column(db.String(255), nullable=True, info={'label': 'Comment'})
phone = db.Column(db.String(255), nullable=True, info={'label': 'Phone'})
fax = db.Column(db.String(255), nullable=True, info={'label': 'FAX'})
skuurl = db.Column(db.String(255), nullable=True, info={'label': 'SKU Url'})
barcode_str = db.Column(db.String(13), nullable=True, info={'label': 'Barcode string'}, default="0000000000000")

part_distributors = db.relationship('PartDistributor', backref='distributor', lazy='dynamic')

__mapper_args__ = {
"order_by": name
}
__mapper_args__ = {"order_by": name}


class Project(db.Model):
BARCODE_TYPE = 25
id = db.Column(db.Integer, primary_key=True)
name = db.Column(
db.String(255),
unique=True,
nullable=False,
info={'label': 'Name'}
)
description = db.Column(
db.String(255),
nullable=True,
info={'label': 'Description'}
)
name = db.Column(db.String(255), unique=True, nullable=False, info={'label': 'Name'})
description = db.Column(db.String(255), nullable=True, info={'label': 'Description'})
barcode_str = db.Column(db.String(13), nullable=True, info={'label': 'Barcode string'}, default="0000000000000")

__mapper_args__ = {
"order_by": name
}
__mapper_args__ = {"order_by": name}


class FootprintCategory(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(255), unique=False, nullable=True)
description = db.Column(db.String(255), unique=False, nullable=True)

footprints = db.relationship('Footprint', backref='footprint_category', cascade="all, delete-orphan")

__mapper_args__ = {
"order_by": name
}
__mapper_args__ = {"order_by": name}


class Footprint(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), unique=True)
description = db.Column(db.String(255), nullable=True)

footprint_category_id = db.Column(db.Integer, db.ForeignKey('footprint_category.id'), nullable=True)
parts = db.relationship('Part', backref='footprint', lazy='dynamic')
# footprint attachments (includes images?)

__mapper_args__ = {
"order_by": name
}
__mapper_args__ = {"order_by": name}

def __repr__(self):
return u"{0} - {1}".format(self.footprint_category.name, self.name)
@@ -292,9 +179,7 @@ class StorageCategory(db.Model):

storages = db.relationship('Storage', backref='storage_category', cascade="all, delete-orphan")

__mapper_args__ = {
"order_by": name
}
__mapper_args__ = {"order_by": name}


class Storage(db.Model):
@@ -307,11 +192,7 @@ class Storage(db.Model):
storage_category_id = db.Column(db.Integer, db.ForeignKey('storage_category.id'), nullable=True)
parts = db.relationship('Part', backref='storage', lazy='dynamic')

# storage image

__mapper_args__ = {
"order_by": name
}
__mapper_args__ = {"order_by": name}

def __repr__(self):
return u"{0} - {1}".format(self.storage_category.name, self.name)
@@ -322,30 +203,33 @@ class PartParameter(db.Model):
name = db.Column(db.String(64), unique=True)
description = db.Column(db.String(255), nullable=True)
unit_value = db.Column(db.String(255), nullable=True)

unit_id = db.Column(db.Integer(), db.ForeignKey('unit.id'), nullable=True)
part_id = db.Column(db.Integer(), db.ForeignKey('part.id'), nullable=False)
__mapper_args__ = {
"order_by": name
}

__mapper_args__ = {"order_by": name}


# links #
class PartManufacturer(db.Model):
id = db.Column(db.Integer, primary_key=True)
sku = db.Column(db.String(255), nullable=True)

part_id = db.Column(db.Integer(), db.ForeignKey('part.id'), nullable=False)
manufacturer_id = db.Column(db.Integer(), db.ForeignKey('manufacturer.id'), nullable=False)
sku = db.Column(db.String(255), nullable=True)


class PartDistributor(db.Model):
id = db.Column(db.Integer, primary_key=True)
sku = db.Column(db.String(255), nullable=True)

part_id = db.Column(db.Integer(), db.ForeignKey('part.id'), nullable=False)
distributor_id = db.Column(db.Integer(), db.ForeignKey('distributor.id'), nullable=False)
sku = db.Column(db.String(255), nullable=True)


class PartProject(db.Model):
id = db.Column(db.Integer, primary_key=True)

part_id = db.Column(db.Integer(), db.ForeignKey('part.id'), nullable=False)
project_id = db.Column(db.Integer(), db.ForeignKey('project.id'), nullable=False)

@@ -440,14 +324,14 @@ class Part(db.Model):

user_id = db.Column(db.Integer(), db.ForeignKey('user.id'), nullable=False)

__mapper_args__ = {
"order_by": name
}
search_vector = db.Column(TSVectorType('name', 'description', 'comment', 'status', 'condition', 'barcode_str'))
__mapper_args__ = {"order_by": name}


# Events for barcodes generation
@event.listens_for(Part, 'after_insert')
def part_event_after_create(mapper, connection, target):
def gen_part_barcode(mapper, connection, target):
out_dir = current_app.config.get('UPLOADS_DEFAULT_DEST')
barcode = generate_ean13(Part.BARCODE_TYPE, target.id, out_dir)
part_table = Part.__table__
@@ -458,7 +342,7 @@ def part_event_after_create(mapper, connection, target):


@event.listens_for(Storage, 'after_insert')
def storage_event_after_create(mapper, connection, target):
def gen_storage_barcode(mapper, connection, target):
out_dir = current_app.config.get('UPLOADS_DEFAULT_DEST')
barcode = generate_ean13(Storage.BARCODE_TYPE, target.id, out_dir)
_table = Part.__table__
@@ -469,7 +353,7 @@ def storage_event_after_create(mapper, connection, target):


@event.listens_for(StorageCategory, 'after_insert')
def part_event_after_create(mapper, connection, target):
def gen_storage_category_barcode(mapper, connection, target):
out_dir = current_app.config.get('UPLOADS_DEFAULT_DEST')
barcode = generate_ean13(StorageCategory.BARCODE_TYPE, target.id, out_dir)
_table = StorageCategory.__table__
@@ -480,7 +364,7 @@ def part_event_after_create(mapper, connection, target):


@event.listens_for(Project, 'after_insert')
def part_event_after_create(mapper, connection, target):
def gen_project_barcode(mapper, connection, target):
out_dir = current_app.config.get('UPLOADS_DEFAULT_DEST')
barcode = generate_ean13(Project.BARCODE_TYPE, target.id, out_dir)
_table = Project.__table__
@@ -491,7 +375,7 @@ def part_event_after_create(mapper, connection, target):


@event.listens_for(Distributor, 'after_insert')
def part_event_after_create(mapper, connection, target):
def gen_distributor_barcode(mapper, connection, target):
out_dir = current_app.config.get('UPLOADS_DEFAULT_DEST')
barcode = generate_ean13(Distributor.BARCODE_TYPE, target.id, out_dir)
_table = Distributor.__table__
@@ -502,7 +386,7 @@ def part_event_after_create(mapper, connection, target):


@event.listens_for(Manufacturer, 'after_insert')
def part_event_after_create(mapper, connection, target):
def gen_manufacturer_barcode(mapper, connection, target):
out_dir = current_app.config.get('UPLOADS_DEFAULT_DEST')
barcode = generate_ean13(Manufacturer.BARCODE_TYPE, target.id, out_dir)
_table = Manufacturer.__table__
@@ -513,7 +397,7 @@ def part_event_after_create(mapper, connection, target):


@event.listens_for(User, 'after_insert')
def part_event_after_create(mapper, connection, target):
def gen_user_barcode(mapper, connection, target):
out_dir = current_app.config.get('UPLOADS_DEFAULT_DEST')
barcode = generate_ean13(User.BARCODE_TYPE, target.id, out_dir)
_table = User.__table__

+ 1
- 0
requirements.txt View File

@@ -41,3 +41,4 @@ wheel==0.24.0
WTForms==2.0.2
WTForms-Alchemy==0.13.3
WTForms-Components==0.9.8
SQLAlchemy-Searchable==0.9.3