Updated models, fixed commits, added env variable for DB connection

master
androiddrew 7 years ago
parent ea35decd36
commit 2c42d9f7f8

1
.gitignore vendored

@ -44,6 +44,7 @@ htmlcov/
nosetests.xml
coverage.xml
*,cover
.pytest_cache/
# Translations
*.mo

@ -3,4 +3,27 @@
A ReSTful api for storing and retrieving news articles
## Pip tools
This project uses pip-tools for developement. Reference the [project page](https://github.com/jazzband/pip-tools) for usage instructions.
This project uses pip-tools for developement. Reference the [project page](https://github.com/jazzband/pip-tools) for usage instructions.
## DB Connection
The database connection string must be set using the `NEWS_DB` environmental variable.
```
$ export NEWS_DB=postgresql://apistar:local@localhost/news
```
## Console Script
A console script os provided for testing via the Werkzueg development server.
```
$(env)wsgi_serve
```
## Deployment
```
$(env) gunicorn -w 2 -b 0.0.0.0:8080 --chdir scripts/ wsgi_app:app
```

@ -1,3 +1,4 @@
import os
from apistar import Route, http, App
from sqlalchemy import create_engine
from .models import NewsArticle, NewsSource
@ -9,11 +10,13 @@ news_article_schema = NewsArticleSchema()
def get_sources(session: Session):
"""Retrieves all News Sources"""
sources = session.query(NewsSource).all()
return http.JSONResponse(news_source_schema.dump(sources, many=True).data, status_code=200)
def add_source(session: Session, request_data: http.RequestData, app: App):
"""Adds a single source to the News Source collection"""
news_source_data, errors = news_source_schema.load(request_data)
if errors:
msg = {"message": "400 Bad Request", "error": errors}
@ -23,23 +26,26 @@ def add_source(session: Session, request_data: http.RequestData, app: App):
session.add(news_source)
session.flush()
headers = {"Location": app.reverse_url('get_source', {"id": news_source.id})}
headers = {"Location": app.reverse_url('get_source', id=news_source.id)}
session.commit()
return http.JSONResponse(news_source_schema.dump(news_source).data, status_code=201, headers=headers)
def delete_source(session: Session, id: int):
"""Delete a single News Sources from the collection by id"""
"""Delete a single News Source from the collection by id"""
news_source = session.query(NewsSource).filter_by(id=id).one_or_none()
if news_source is None:
msg = {"message": "404 Not Found"}
return http.JSONResponse(msg, status_code=404)
session.delete(news_source)
session.commit()
msg = {"message": "200 OK"}
return http.JSONResponse(msg, status_code=200)
def get_source(session: Session, id: int):
"""Retrieves a single News Source by id"""
news_source = session.query(NewsSource).filter_by(id=id).one_or_none()
if news_source is None:
msg = {"message": "404 Not Found"}
@ -49,11 +55,22 @@ def get_source(session: Session, id: int):
def get_articles(session: Session):
"""Retrieves all articles"""
articles = session.query(NewsArticle).all()
return http.JSONResponse(news_article_schema.dump(articles, many=True).data, status_code=200)
def get_article(session: Session, id: int):
"""Retrieves a single article by id"""
news_article = session.query(NewsArticle).filter_by(id=id).one_or_none()
if news_article is None:
msg = {"message": "404 Not Found"}
return http.JSONResponse(msg, status_code=404)
return http.JSONResponse(news_article_schema.dump(news_article).data, status_code=200)
def add_article(session: Session, request_data: http.RequestData, app: App):
"""Adds a single article"""
news_article_data, errors = news_article_schema.load(request_data)
if errors:
msg = {"message": "400 Bad Request", "error": errors}
@ -63,17 +80,9 @@ def add_article(session: Session, request_data: http.RequestData, app: App):
session.add(news_article)
session.flush()
headers = {"Location": app.reverse_url('get_source', {"id": news_article.id})}
return http.JSONResponse(news_article_schema.dump(news_article), status_code=201, headers=headers)
def get_article(session: Session, id: int):
news_article = session.query(NewsArticle).filter_by(id=id).one_or_none()
if news_article is None:
msg = {"message": "404 Not Found"}
return http.JSONResponse(msg, status_code=404)
return http.JSONResponse(news_article_schema.dump(news_article), status_code=200)
headers = {"Location": app.reverse_url('get_article', id=news_article.id)}
session.commit()
return http.JSONResponse(news_article_schema.dump(news_article).data, status_code=201, headers=headers)
def delete_article(session: Session, id):
@ -83,6 +92,8 @@ def delete_article(session: Session, id):
msg = {"message": "404 Not Found"}
return http.JSONResponse(msg, status_code=404)
session.delete(news_article)
session.commit()
msg = {"message": "200 OK"}
return http.JSONResponse(msg, status_code=200)
@ -100,7 +111,9 @@ routes = [
routes = routes
components = [SQLAlchemySession(engine=create_engine('postgresql://apistar:local@localhost/news'))]
components = [
SQLAlchemySession(engine=create_engine(os.getenv('NEWS_DB', 'postgresql://apistar:local@localhost/news')))
]
hooks = [SQLAlchemyHook()]

@ -77,6 +77,9 @@ class NewsSource(DBMixin, Base):
source_type = Column(Text)
categories = relationship('Category', secondary=categories,
backref=backref('news_sources', lazy='dynamic'))
articles = relationship('NewsArticle',
backref=backref('news_source'),
cascade="all, delete, delete-orphan")
class NewsArticle(DBMixin, Base):
@ -87,5 +90,4 @@ class NewsArticle(DBMixin, Base):
authors = Column(ARRAY(Text))
published_date = Column(DateTime)
news_blob = Column(Text)
news_source = relationship('NewsSource', backref=backref('articles', lazy='dynamic'))
tags = relationship('Tag', secondary=tags, backref=backref('articles', lazy='dynamic'))

@ -64,7 +64,8 @@ class NewsArticleSchema(Schema):
title = fields.Str()
authors = fields.List(fields.Str())
published_date = UnixTimestamp(dump_only=True)
news_blob = fields.Str(required=True, error_messages={'required': 'NewsArticle must include news content'})
news_blob = fields.Str(required=True,
error_messages={'required': 'NewsArticle must include news content'})
# TODO add support for Tags

Loading…
Cancel
Save