Skip to content
Snippets Groups Projects
Commit 23f648da authored by Josef Olsson's avatar Josef Olsson Committed by Victor Löfgren
Browse files

Resolve "Improve populate.py"

parent 15142bcd
No related branches found
No related tags found
1 merge request!46Resolve "Improve populate.py"
Pipeline #39122 passed
Showing with 148 additions and 161 deletions
......@@ -32,11 +32,12 @@ class AuthSignup(Resource):
password = args.get("password")
role_id = args.get("role_id")
city_id = args.get("city_id")
name = args.get("name")
if User.query.filter(User.email == email).count() > 0:
api.abort(codes.BAD_REQUEST, "User already exists")
item_user = dbc.add.default(User(email, password, role_id, city_id))
item_user = dbc.add.user(email, password, role_id, city_id, name)
if not item_user:
api.abort(codes.BAD_REQUEST, "User could not be created")
......
......@@ -24,13 +24,12 @@ class CompetitionsList(Resource):
name = args.get("name")
city_id = args.get("city_id")
year = args.get("year")
style_id = args.get("style_id")
# Add competition
item = dbc.add.default(Competition(name, year, style_id, city_id))
item = dbc.add.competition(name, year, city_id)
# Add default slide
item_slide = dbc.add.slide(item)
dbc.add.slide(item)
dbc.refresh(item)
return item_response(schema.dump(item))
......@@ -52,8 +51,7 @@ class Competitions(Resource):
name = args.get("name")
year = args.get("year")
city_id = args.get("city_id")
style_id = args.get("style_id")
item = dbc.edit.competition(item, name, year, city_id, style_id)
item = dbc.edit.competition(item, name, year, city_id)
return item_response(schema.dump(item))
@jwt_required
......@@ -71,11 +69,10 @@ class CompetitionSearch(Resource):
name = args.get("name")
year = args.get("year")
city_id = args.get("city_id")
style_id = args.get("style_id")
page = args.get("page", 0)
page_size = args.get("page_size", 15)
order = args.get("order", 1)
order_by = args.get("order_by")
items, total = dbc.get.search_competitions(name, year, city_id, style_id, page, page_size, order, order_by)
items, total = dbc.get.search_competitions(name, year, city_id, page, page_size, order, order_by)
return list_response(list_schema.dump(items), total)
......@@ -51,7 +51,7 @@ class CitiesList(Resource):
@jwt_required
def post(self):
args = name_parser.parse_args(strict=True)
dbc.add.default(City(args["name"]))
dbc.add.city(args["name"])
items = City.query.all()
return list_response(city_schema.dump(items))
......
import app.core.controller as dbc
import app.core.http_codes as codes
from app.apis import admin_required, item_response, list_response
from app.core import schemas
from app.core.dto import SlideDTO
from app.core.models import Competition, Slide
from app.core.parsers import slide_parser
from flask_jwt_extended import get_jwt_identity, jwt_required
from flask_restx import Namespace, Resource, reqparse
from flask_jwt_extended import jwt_required
from flask_restx import Resource
api = SlideDTO.api
schema = SlideDTO.schema
......
......@@ -29,8 +29,9 @@ class TeamsList(Resource):
parser.add_argument("name", type=str, location="json")
args = parser.parse_args(strict=True)
dbc.add.default(Team(args["name"], CID))
item_comp = get_comp(CID)
dbc.add.team(args["name"], item_comp)
dbc.refresh(item_comp)
return list_response(list_schema.dump(item_comp.teams))
......
from app.core import db
from app.core.models import Blacklist, City, Competition, Role, Slide, User
from app.core.models import Blacklist, City, Competition, MediaType, Question, QuestionType, Role, Slide, Team, User
def default(item):
db.session.add(item)
db.session.commit()
db.session.refresh(item)
return item
def db_add(func):
def wrapper(*args, **kwargs):
item = func(*args, **kwargs)
db.session.add(item)
db.session.commit()
db.session.refresh(item)
return item
return wrapper
@db_add
def blacklist(jti):
db.session.add(Blacklist(jti))
db.session.commit()
return Blacklist(jti)
@db_add
def slide(item_competition):
order = Slide.query.filter(Slide.competition_id == item_competition.id).count()
item = Slide(order, item_competition.id)
db.session.add(item)
db.session.commit()
db.session.refresh(item)
return item
order = Slide.query.filter(Slide.competition_id == item_competition.id).count() # first element has index 0
return Slide(order, item_competition.id)
@db_add
def user(email, plaintext_password, role_id, city_id, name=None):
return User(email, plaintext_password, role_id, city_id, name)
@db_add
def question(name, order, type_id, item_slide):
return Question(name, order, type_id, item_slide.id)
@db_add
def competition(name, year, city_id):
return Competition(name, year, city_id)
@db_add
def team(name, item_competition):
return Team(name, item_competition.id)
@db_add
def mediaType(name):
return MediaType(name)
@db_add
def questionType(name):
return QuestionType(name)
@db_add
def role(name):
return Role(name)
@db_add
def city(name):
return City(name)
......@@ -31,15 +31,13 @@ def slide(item, title=None, timer=None):
return item
def competition(item, name=None, year=None, city_id=None, style_id=None):
def competition(item, name=None, year=None, city_id=None):
if name:
item.name = name
if year:
item.year = year
if city_id:
item.city_id = city_id
if style_id:
item.style_id = style_id
db.session.commit()
db.session.refresh(item)
......
......@@ -43,9 +43,7 @@ def search_user(email=None, name=None, city_id=None, role_id=None, page=0, page_
return _search(query, order_column, page, page_size, order)
def search_competitions(
name=None, year=None, city_id=None, style_id=None, page=0, page_size=15, order=1, order_by=None
):
def search_competitions(name=None, year=None, city_id=None, page=0, page_size=15, order=1, order_by=None):
query = Competition.query
if name:
query = query.filter(Competition.name.like(f"%{name}%"))
......@@ -53,8 +51,6 @@ def search_competitions(
query = query.filter(Competition.year == year)
if city_id:
query = query.filter(Competition.city_id == city_id)
if style_id:
query = query.filter(Competition.style_id == style_id)
order_column = Competition.year # Default order_by
if order_by:
......
......@@ -51,12 +51,13 @@ class User(db.Model):
media = db.relationship("Media", backref="upload_by")
def __init__(self, email, plaintext_password, role_id, city_id):
def __init__(self, email, plaintext_password, role_id, city_id, name=None):
self._password = bcrypt.generate_password_hash(plaintext_password)
self.email = email
self.role_id = role_id
self.city_id = city_id
self.authenticated = False
self.name = name
@hybrid_property
def password(self):
......@@ -77,43 +78,25 @@ class Media(db.Model):
type_id = db.Column(db.Integer, db.ForeignKey("media_type.id"), nullable=False)
upload_by_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
styles = db.relationship("Style", backref="bg_image")
def __init__(self, filename, type_id, upload_by_id):
self.filename = filename
self.type_id = type_id
self.upload_by_id = upload_by_id
class Style(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(STRING_SIZE), unique=True)
css = db.Column(db.Text, nullable=False)
bg_image_id = db.Column(db.Integer, db.ForeignKey("media.id"), nullable=True)
competition = db.relationship("Competition", backref="style")
def __init__(self, name, css, bg_image_id=None):
self.name = name
self.css = css
self.bg_image_id = bg_image_id
class Competition(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(STRING_SIZE), unique=True)
year = db.Column(db.Integer, nullable=False, default=2020)
style_id = db.Column(db.Integer, db.ForeignKey("style.id"), nullable=False)
city_id = db.Column(db.Integer, db.ForeignKey("city.id"), nullable=False)
slides = db.relationship("Slide", backref="competition")
teams = db.relationship("Team", backref="competition")
def __init__(self, name, year, style_id, city_id):
def __init__(self, name, year, city_id):
self.name = name
self.year = year
self.style_id = style_id
self.city_id = city_id
......@@ -137,7 +120,7 @@ class Slide(db.Model):
title = db.Column(db.String(STRING_SIZE), nullable=False, default="")
body = db.Column(db.Text, nullable=False, default="")
timer = db.Column(db.Integer, nullable=False, default=0)
settings = db.Column(db.Text, nullable=False, default="{}") # Json object
settings = db.Column(db.Text, nullable=False, default="{}")
competition_id = db.Column(db.Integer, db.ForeignKey("competition.id"), nullable=False)
questions = db.relationship("Question", backref="slide")
......@@ -148,34 +131,32 @@ class Slide(db.Model):
class Question(db.Model):
__table_args__ = (db.UniqueConstraint("slide_id", "name"), db.UniqueConstraint("slide_id", "order"))
__table_args__ = (db.UniqueConstraint("slide_id", "name"),)
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(STRING_SIZE), nullable=False)
order = db.Column(db.Integer, nullable=False)
total_score = db.Column(db.Integer, nullable=False, default=1)
type_id = db.Column(db.Integer, db.ForeignKey("question_type.id"), nullable=False)
slide_id = db.Column(db.Integer, db.ForeignKey("slide.id"), nullable=False)
question_answers = db.relationship("QuestionAnswer", backref="question")
alternatives = db.relationship("QuestionAlternative", backref="question")
def __init__(self, name, order, type_id, slide_id):
def __init__(self, name, total_score, type_id, slide_id):
self.name = name
self.order = order
self.total_score = total_score
self.type_id = type_id
self.slide_id = slide_id
class QuestionAlternative(db.Model):
__table_args__ = (db.UniqueConstraint("question_id", "order"),)
id = db.Column(db.Integer, primary_key=True)
text = db.Column(db.String(STRING_SIZE), nullable=False)
value = db.Column(db.Boolean, nullable=False)
order = db.Column(db.Integer, nullable=False)
question_id = db.Column(db.Integer, db.ForeignKey("question.id"), nullable=False)
def __init__(self, text, value, order, question_id):
def __init__(self, text, value, question_id):
self.text = text
self.value = value
self.order = order
self.question_id = question_id
......@@ -183,7 +164,7 @@ class QuestionAnswer(db.Model):
__table_args__ = (db.UniqueConstraint("question_id", "team_id"),)
id = db.Column(db.Integer, primary_key=True)
data = db.Column(db.Text, nullable=False)
score = db.Column(db.Integer, nullable=False, default=0) # 0: False, 1: True
score = db.Column(db.Integer, nullable=False, default=0)
question_id = db.Column(db.Integer, db.ForeignKey("question.id"), nullable=False)
team_id = db.Column(db.Integer, db.ForeignKey("team.id"), nullable=False)
......
......@@ -38,7 +38,6 @@ competition_parser = reqparse.RequestParser()
competition_parser.add_argument("name", type=str)
competition_parser.add_argument("year", type=int)
competition_parser.add_argument("city_id", type=int)
competition_parser.add_argument("style_id", type=int)
###SEARCH_COMPETITOIN####
......@@ -46,7 +45,6 @@ competition_search_parser = search_parser.copy()
competition_search_parser.add_argument("name", type=str, default=None, location="args")
competition_search_parser.add_argument("year", type=str, default=None, location="args")
competition_search_parser.add_argument("city_id", type=int, default=None, location="args")
competition_search_parser.add_argument("style_id", type=int, default=None, location="args")
###SLIDER_PARSER####
......
......@@ -31,7 +31,6 @@ class CompetitionSchemaRich(RichSchema):
name = ma.auto_field()
year = ma.auto_field()
slides = fields.Nested(schemas.SlideSchema, many=True)
style = fields.Nested(schemas.RoleSchema, many=False)
city = fields.Nested(schemas.CitySchema, many=False)
......
......@@ -52,16 +52,6 @@ class MediaSchema(BaseSchema):
upload_by_id = ma.auto_field()
class StyleSchema(BaseSchema):
class Meta(BaseSchema.Meta):
model = models.Style
id = ma.auto_field()
name = ma.auto_field()
css = ma.auto_field()
bg_image = fields.Nested(MediaSchema, many=False)
class SlideSchema(BaseSchema):
class Meta(BaseSchema.Meta):
model = models.Slide
......
......@@ -11,6 +11,7 @@ class Config:
BUNDLE_ERRORS = True
JWT_ACCESS_TOKEN_EXPIRES = timedelta(days=2)
JWT_REFRESH_TOKEN_EXPIRES = timedelta(days=30)
SQLALCHEMY_TRACK_MODIFICATIONS = False
class DevelopmentConfig(Config):
......@@ -21,7 +22,6 @@ class DevelopmentConfig(Config):
class TestingConfig(Config):
TESTING = True
SQLALCHEMY_DATABASE_URI = "sqlite:///test.db"
SQLALCHEMY_TRACK_MODIFICATIONS = False
class ProductionConfig(Config):
......
from sqlalchemy.sql.expression import true
import app.core.controller as dbc
from app import create_app, db
from app.core.models import City, MediaType, QuestionType, Role, Style, User
from app.core.models import City, Competition, MediaType, QuestionType, Role
def _add_items():
media_types = ["Image", "Video"]
question_types = ["Boolean", "Multiple", "Text"]
roles = ["Admin", "Editor"]
cities = ["Linköping"]
cities = ["Linköping", "Stockholm", "Norrköping", "Örkelljunga"]
teams = ["Gymnasieskola A", "Gymnasieskola B", "Gymnasieskola C"]
for team_name in media_types:
dbc.add.mediaType(team_name)
for team_name in question_types:
dbc.add.questionType(team_name)
for team_name in roles:
dbc.add.role(team_name)
# Add media types
for item in media_types:
db.session.add(MediaType(item))
for team_name in cities:
dbc.add.city(team_name)
db.session.commit()
admin_id = Role.query.filter(Role.name == "Admin").one().id
editor_id = Role.query.filter(Role.name == "Editor").one().id
# Add question types
for item in question_types:
db.session.add(QuestionType(item))
db.session.commit()
city_id = City.query.filter(City.name == "Linköping").one().id
# Add roles
for item in roles:
db.session.add(Role(item))
db.session.commit()
text_id = QuestionType.query.filter(QuestionType.name == "Text").one().id
# Add cities
for item in cities:
db.session.add(City(item))
db.session.commit()
# Add users
dbc.add.user("admin@test.se", "password", admin_id, city_id)
dbc.add.user("test@test.se", "password", editor_id, city_id)
# Add deafult style
db.session.add(Style("Main Style", ""))
# Add competitions to db
for i in range(3):
dbc.add.competition(f"Test{i+1}", 1971, city_id)
# Commit changes to db
db.session.commit()
item_comps = Competition.query.all()
# Add
for item_comp in item_comps:
for i in range(3):
# Add slide to competition
item_slide = dbc.add.slide(item_comp)
# Add user with role and city
dbc.add.default(User("test@test.se", "password", 1, 1))
# Add question to competition
dbc.add.question(f"Q{i+1}", i + 1, text_id, item_slide)
db.session.flush()
# Add teams to competition
for team_name in teams:
dbc.add.team(team_name, item_comp)
app = create_app("configmodule.DevelopmentConfig")
if __name__ == "__main__":
app = create_app("configmodule.DevelopmentConfig")
with app.app_context():
db.create_all()
_add_items()
with app.app_context():
db.drop_all()
db.create_all()
_add_items()
......@@ -43,7 +43,7 @@ def test_competition(client):
headers = {"Authorization": "Bearer " + body["access_token"]}
# Create competition
data = {"name": "c1", "year": 2020, "city_id": 1, "style_id": 1}
data = {"name": "c1", "year": 2020, "city_id": 1}
response, body = post(client, "/api/competitions", data, headers=headers)
assert response.status_code == 200
assert body["name"] == "c1"
......
from app.core.models import City, Competition, Media, MediaType, Question, QuestionType, Role, Slide, Style, Team, User
import app.core.controller as dbc
from app.core.models import City, Competition, Media, MediaType, Question, QuestionType, Role, Slide, Team, User
from tests import app, client, db
from tests.test_helpers import add_default_values, assert_exists, assert_insert_fail
......@@ -21,7 +22,7 @@ def test_user(client):
assert len(item_city.users) == 1 and item_city.users[0].id == item_user.id
def test_media_style(client):
def test_media(client):
add_default_values()
item_user = User.query.filter_by(email="test@test.se").first()
......@@ -38,19 +39,6 @@ def test_media_style(client):
assert len(item_user.media) == 1
assert item_media.upload_by.email == "test@test.se"
# Add style
db.session.add(Style("template", "hej", item_media.id))
db.session.commit()
# Assert style
item_style = Style.query.filter_by(name="template").first()
assert item_style is not None
assert len(item_media.styles) == 1
assert item_style.bg_image.filename == "bild.png"
# Assert lazy loading
assert item_user.media[0].styles[0].name == "template"
def test_question(client):
add_default_values()
......@@ -64,33 +52,24 @@ def test_question(client):
db.session.commit()
item_media = Media.query.filter_by(filename="bild.png").first()
# Add style
db.session.add(Style("template", "hej", item_media.id))
db.session.commit()
item_style = Style.query.filter_by(name="template").first()
# Add competition
item_city = City.query.filter_by(name="Linköping").first()
db.session.add(Competition("teknik8", 2020, item_style.id, item_city.id))
db.session.add(Competition("teknik9", 2020, item_style.id, item_city.id))
db.session.commit()
dbc.add.competition("teknik8", 2020, item_city.id)
dbc.add.competition("teknik9", 2020, item_city.id)
item_competition = Competition.query.filter_by(name="teknik8").first()
item_competition_2 = Competition.query.filter_by(name="teknik9").first()
assert item_competition is not None
assert item_competition.id == 1
assert item_competition.style.name == "template"
assert item_competition.city.name == "Linköping"
# Add teams
db.session.add(Team("Lag1", item_competition.id))
db.session.add(Team("Lag2", item_competition.id))
db.session.commit()
dbc.add.team("Lag1", item_competition)
dbc.add.team("Lag2", item_competition)
assert_insert_fail(Team, "Lag1", item_competition.id)
db.session.add(Team("Lag1", item_competition_2.id))
db.session.commit()
dbc.add.team("Lag1", item_competition_2)
assert Team.query.filter((Team.competition_id == item_competition.id) & (Team.name == "Lag1")).count() == 1
assert Team.query.filter((Team.competition_id == item_competition.id) & (Team.name == "Lag2")).count() == 1
......@@ -100,18 +79,17 @@ def test_question(client):
assert Team.query.count() == 3
# Add slides
db.session.add(Slide(1, item_competition.id))
db.session.add(Slide(2, item_competition.id))
db.session.add(Slide(3, item_competition.id))
db.session.commit()
dbc.add.slide(item_competition)
dbc.add.slide(item_competition)
dbc.add.slide(item_competition)
# Try add slide with same order
assert_insert_fail(Slide, 1, item_competition.id)
assert_exists(Slide, 1, order=1)
item_slide1 = Slide.query.filter_by(order=1).first()
item_slide2 = Slide.query.filter_by(order=2).first()
item_slide3 = Slide.query.filter_by(order=3).first()
item_slide1 = Slide.query.filter_by(order=0).first()
item_slide2 = Slide.query.filter_by(order=1).first()
item_slide3 = Slide.query.filter_by(order=2).first()
assert item_slide1 is not None
assert item_slide2 is not None
......@@ -121,9 +99,8 @@ def test_question(client):
question_type_bool = QuestionType.query.filter_by(name="Boolean").first()
question_type_multiple = QuestionType.query.filter_by(name="Multiple").first()
db.session.add(Question("Fråga1", 0, question_type_bool.id, item_slide2.id))
db.session.add(Question("Fråga2", 1, question_type_multiple.id, item_slide3.id))
db.session.commit()
dbc.add.question("Fråga1", 10, question_type_bool.id, item_slide2)
dbc.add.question("Fråga2", 10, question_type_multiple.id, item_slide3)
assert question_type_bool is not None
assert question_type_multiple is not None
......
......@@ -2,7 +2,7 @@ import json
import app.core.controller as dbc
from app.core import db
from app.core.models import City, MediaType, QuestionType, Role, Style, User
from app.core.models import City, MediaType, QuestionType, Role, User
def add_default_values():
......@@ -13,28 +13,23 @@ def add_default_values():
# Add media types
for item in media_types:
db.session.add(MediaType(item))
dbc.add.mediaType(item)
# Add question types
for item in question_types:
db.session.add(QuestionType(item))
dbc.add.questionType(item)
# Add roles
for item in roles:
db.session.add(Role(item))
dbc.add.role(item)
# Add cities
for item in cities:
db.session.add(City(item))
# Add deafult style
db.session.add(Style("Main Style", ""))
# Commit changes to db
db.session.commit()
dbc.add.city(item)
item_admin = Role.query.filter(Role.name == "Admin").one()
item_city = City.query.filter(City.name == "Linköping").one()
# Add user with role and city
dbc.add.default(User("test@test.se", "password", 1, 1))
dbc.add.user("test@test.se", "password", item_admin.id, item_city.id)
def get_body(response):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment