Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Ross I Kinsey
where
Commits
ab690172
Unverified
Commit
ab690172
authored
Feb 19, 2020
by
Dylan Jones
Browse files
move where.model.sa -> where.model
parent
a19386b0
Changes
4
Hide whitespace changes
Inline
Side-by-side
where/alembic/env.py
View file @
ab690172
...
@@ -19,7 +19,8 @@ fileConfig(config.config_file_name)
...
@@ -19,7 +19,8 @@ fileConfig(config.config_file_name)
# target_metadata = mymodel.Base.metadata
# target_metadata = mymodel.Base.metadata
import
sys
,
os
import
sys
,
os
sys
.
path
.
append
(
os
.
getcwd
())
sys
.
path
.
append
(
os
.
getcwd
())
from
where.model.sa
import
Base
from
where.model
import
Base
target_metadata
=
Base
.
metadata
target_metadata
=
Base
.
metadata
# other values from the config, defined by the needs of env.py,
# other values from the config, defined by the needs of env.py,
...
...
where/app.py
View file @
ab690172
from
flask
import
Flask
,
redirect
,
jsonify
,
abort
,
request
,
url_for
,
Response
,
make_response
from
flask
import
Flask
,
redirect
,
jsonify
,
abort
,
request
,
url_for
,
make_response
from
werkzeug.datastructures
import
Headers
from
where.model
import
with_session
,
Point
,
Category
,
Field
from
where.model.field_types
import
FieldType
from
where.model.field_types
import
FieldType
from
where.model.sa
import
Category
,
Point
,
Field
,
with_session
app
=
Flask
(
__name__
)
app
=
Flask
(
__name__
)
...
@@ -23,7 +22,6 @@ def index():
...
@@ -23,7 +22,6 @@ def index():
@
app
.
route
(
'/test_data'
)
@
app
.
route
(
'/test_data'
)
@
with_session
@
with_session
def
test_data
(
session
):
def
test_data
(
session
):
# session = Session()
session
.
query
(
Point
).
delete
()
session
.
query
(
Point
).
delete
()
session
.
query
(
Field
).
delete
()
session
.
query
(
Field
).
delete
()
session
.
query
(
Category
).
delete
()
session
.
query
(
Category
).
delete
()
...
@@ -95,7 +93,6 @@ def test_data(session):
...
@@ -95,7 +93,6 @@ def test_data(session):
"value"
:
True
"value"
:
True
}
}
}
}
session
.
add
(
fn
)
session
.
add
(
fn
)
session
.
commit
()
session
.
commit
()
...
@@ -127,8 +124,8 @@ def get_point(session, id):
...
@@ -127,8 +124,8 @@ def get_point(session, id):
def
add_point
(
session
):
def
add_point
(
session
):
allowed_params
=
{
'name'
,
'lat'
,
'lon'
,
'attributes'
,
'category_id'
,
'parent_id'
}
allowed_params
=
{
'name'
,
'lat'
,
'lon'
,
'attributes'
,
'category_id'
,
'parent_id'
}
data
=
request
.
get_json
()
data
=
request
.
get_json
()
data
=
{
key
:
val
for
key
,
val
in
data
.
items
()
if
key
in
allowed_params
}
data
=
{
key
:
val
for
key
,
val
in
data
.
items
()
if
key
in
allowed_params
}
# TODO: For some reason point.category is NULL when we do validation, even though the category ID is present
# TODO: For some reason point.category is NULL when we do validation, even though the category ID is present
# this is causing an exception whenever a non-null attributes object is passed
# this is causing an exception whenever a non-null attributes object is passed
point
=
Point
(
category_id
=
data
.
pop
(
'category_id'
))
point
=
Point
(
category_id
=
data
.
pop
(
'category_id'
))
...
@@ -147,7 +144,7 @@ def add_point(session):
...
@@ -147,7 +144,7 @@ def add_point(session):
@
with_session
@
with_session
def
search_points
(
session
):
def
search_points
(
session
):
q
=
session
.
query
(
Point
)
q
=
session
.
query
(
Point
)
if
'category_id'
in
request
.
args
:
if
'category_id'
in
request
.
args
:
q
=
q
.
filter
(
Point
.
category_id
==
request
.
args
.
get
(
'category_id'
))
q
=
q
.
filter
(
Point
.
category_id
==
request
.
args
.
get
(
'category_id'
))
...
@@ -158,4 +155,4 @@ def search_points(session):
...
@@ -158,4 +155,4 @@ def search_points(session):
if
__name__
==
'__main__'
:
if
__name__
==
'__main__'
:
app
.
run
()
app
.
run
()
\ No newline at end of file
where/model/__init__.py
View file @
ab690172
from
contextlib
import
contextmanager
from
sqlalchemy
import
Column
,
Integer
,
String
,
Float
,
JSON
,
ForeignKey
,
Enum
from
sqlalchemy.ext.declarative
import
as_declarative
from
sqlalchemy.orm
import
relationship
,
validates
from
.field_types
import
FieldType
from
.meta
import
Session
,
engine
@
contextmanager
def
session_context
():
session
=
Session
()
try
:
yield
session
session
.
commit
()
except
BaseException
:
session
.
rollback
()
raise
finally
:
session
.
close
()
def
with_session
(
func
):
"""
Decorator for convenience when building endpoints. The first argument to the
decorated function will be a safe-to-use, autocommitting Session instance.
:param func: the view function to wrap
:return: the wrapped function
"""
def
wrapper
(
*
args
,
**
kwargs
):
with
session_context
()
as
session
:
return
func
(
session
,
*
args
,
**
kwargs
)
# Flask identifies endpoint handlers based on their name
wrapper
.
__name__
=
func
.
__name__
return
wrapper
@
as_declarative
()
class
Base
(
object
):
pass
class
Point
(
Base
):
"""
Represents actual instances of any and all points on the map.
"""
__tablename__
=
'point'
id
=
Column
(
Integer
,
primary_key
=
True
,
autoincrement
=
True
)
name
=
Column
(
String
,
nullable
=
True
)
lat
=
Column
(
Float
,
nullable
=
False
)
lon
=
Column
(
Float
,
nullable
=
False
)
attributes
=
Column
(
JSON
,
nullable
=
False
)
# Relationships
category_id
=
Column
(
Integer
,
ForeignKey
(
'category.id'
),
nullable
=
False
)
category
=
relationship
(
'Category'
)
parent_id
=
Column
(
Integer
,
ForeignKey
(
'point.id'
),
nullable
=
True
)
parent
=
relationship
(
'Point'
,
remote_side
=
[
id
])
children
=
relationship
(
'Point'
)
@
validates
(
'attributes'
)
def
validate_data
(
self
,
_
,
data
):
if
data
is
None
:
return
fields
=
self
.
category
.
fields
for
key
in
data
:
# Find Field object that corresponds to this key
for
field
in
fields
:
if
field
.
slug
==
key
:
break
else
:
raise
ValueError
(
f
'extra data "
{
key
}
" must be a registered field'
)
field
.
validate_data
(
data
[
key
])
return
data
def
as_json
(
self
,
children
=
True
):
if
children
:
children
=
[
child
.
as_json
(
children
=
False
)
for
child
in
self
.
children
]
return
{
"name"
:
self
.
name
,
"lat"
:
self
.
lat
,
"lon"
:
self
.
lon
,
"category"
:
self
.
category
.
id
,
"attributes"
:
self
.
attributes
,
"children"
:
children
}
class
Category
(
Base
):
"""
Represent a schema for a single category of objects (e.g. water fountain or bathroom)
"""
__tablename__
=
'category'
id
=
Column
(
Integer
,
primary_key
=
True
,
autoincrement
=
True
)
name
=
Column
(
String
,
nullable
=
False
,
unique
=
True
)
icon
=
Column
(
String
,
nullable
=
True
)
fields
=
relationship
(
"Field"
)
def
as_json
(
self
):
return
{
"id"
:
self
.
id
,
"name"
:
self
.
name
,
"icon"
:
self
.
icon
,
"attributes"
:
{
attr
.
slug
:
attr
.
as_json
()
for
attr
in
self
.
fields
}
}
class
Field
(
Base
):
"""
Represents a single field in the Category schema.
"""
__tablename__
=
'field'
id
=
Column
(
Integer
,
primary_key
=
True
,
autoincrement
=
True
)
slug
=
Column
(
String
,
nullable
=
False
)
name
=
Column
(
String
,
nullable
=
False
)
type
=
Column
(
Enum
(
FieldType
),
nullable
=
False
)
# Relationship
category_id
=
Column
(
Integer
,
ForeignKey
(
'category.id'
))
def
validate_data
(
self
,
data
):
"""
Verify that data is the correct type for this Field.
"""
self
.
type
.
validate
(
data
)
def
as_json
(
self
):
return
{
"slug"
:
self
.
slug
,
"name"
:
self
.
name
,
"type"
:
self
.
type
.
name
}
# uh putting this here doesn't feel right but there's not anything *too* wrong with it
Base
.
metadata
.
create_all
(
engine
)
where/model/sa.py
deleted
100644 → 0
View file @
a19386b0
from
contextlib
import
contextmanager
from
sqlalchemy
import
String
,
ForeignKey
,
Enum
,
Integer
,
Float
,
JSON
from
sqlalchemy.ext.declarative
import
as_declarative
from
sqlalchemy.orm
import
relationship
,
validates
from
sqlalchemy.schema
import
Column
from
.field_types
import
FieldType
from
.meta
import
Session
,
engine
@
contextmanager
def
session_context
():
session
=
Session
()
try
:
yield
session
session
.
commit
()
except
BaseException
:
session
.
rollback
()
raise
finally
:
session
.
close
()
# Decorator for convenience when building endpoints
def
with_session
(
func
):
def
wrapper
(
*
args
,
**
kwargs
):
with
session_context
()
as
session
:
return
func
(
session
,
*
args
,
**
kwargs
)
# Flask identifies endpoint handlers based on their name
wrapper
.
__name__
=
func
.
__name__
return
wrapper
@
as_declarative
()
class
Base
(
object
):
pass
class
Point
(
Base
):
"""
Represents actual instances of any and all points on the map.
"""
__tablename__
=
'point'
id
=
Column
(
Integer
,
primary_key
=
True
,
autoincrement
=
True
)
name
=
Column
(
String
,
nullable
=
True
)
lat
=
Column
(
Float
,
nullable
=
False
)
lon
=
Column
(
Float
,
nullable
=
False
)
attributes
=
Column
(
JSON
,
nullable
=
False
)
# Relationships
category_id
=
Column
(
Integer
,
ForeignKey
(
'category.id'
),
nullable
=
False
)
category
=
relationship
(
'Category'
)
parent_id
=
Column
(
Integer
,
ForeignKey
(
'point.id'
),
nullable
=
True
)
parent
=
relationship
(
'Point'
,
remote_side
=
[
id
])
children
=
relationship
(
'Point'
)
@
validates
(
'attributes'
)
def
validate_data
(
self
,
_
,
data
):
if
data
is
None
:
return
fields
=
self
.
category
.
fields
for
key
in
data
:
# Find Field object that corresponds to this key
for
field
in
fields
:
if
field
.
slug
==
key
:
break
else
:
raise
ValueError
(
f
'extra data "
{
key
}
" must be a registered field'
)
field
.
validate_data
(
data
[
key
])
return
data
def
as_json
(
self
,
children
=
True
):
if
children
:
children
=
[
child
.
as_json
(
children
=
False
)
for
child
in
self
.
children
]
return
{
"name"
:
self
.
name
,
"lat"
:
self
.
lat
,
"lon"
:
self
.
lon
,
"category"
:
self
.
category
.
id
,
"attributes"
:
self
.
attributes
,
"children"
:
children
}
class
Category
(
Base
):
"""
Represent a schema for a single category of objects (e.g. water fountain or bathroom)
"""
__tablename__
=
'category'
id
=
Column
(
Integer
,
primary_key
=
True
,
autoincrement
=
True
)
name
=
Column
(
String
,
nullable
=
False
,
unique
=
True
)
icon
=
Column
(
String
,
nullable
=
True
)
fields
=
relationship
(
"Field"
)
def
as_json
(
self
):
return
{
"id"
:
self
.
id
,
"name"
:
self
.
name
,
"icon"
:
self
.
icon
,
"attributes"
:
{
attr
.
slug
:
attr
.
as_json
()
for
attr
in
self
.
fields
}
}
class
Field
(
Base
):
"""
Represents a single field in the Category schema.
"""
__tablename__
=
'field'
id
=
Column
(
Integer
,
primary_key
=
True
,
autoincrement
=
True
)
slug
=
Column
(
String
,
nullable
=
False
)
name
=
Column
(
String
,
nullable
=
False
)
type
=
Column
(
Enum
(
FieldType
),
nullable
=
False
)
# Relationship
category_id
=
Column
(
Integer
,
ForeignKey
(
'category.id'
))
def
validate_data
(
self
,
data
):
"""
Verify that data is the correct type for this Field.
"""
self
.
type
.
validate
(
data
)
def
as_json
(
self
):
return
{
"slug"
:
self
.
slug
,
"name"
:
self
.
name
,
"type"
:
self
.
type
.
name
}
# uh putting this here doesn't feel right but there's not anything *too* wrong with it
Base
.
metadata
.
create_all
(
engine
)
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment