Skip to content
This repository has been archived by the owner on Sep 27, 2022. It is now read-only.

commit all changes #24

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,10 @@ dev.db

# Vagrant machines
.vagrant/**

*.sqlite

# Virtual environment
venv/
__pycache__/
vscode/
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"python.pythonPath": "venv\\Scripts\\python.exe"
}
16 changes: 14 additions & 2 deletions autoapp.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
# -*- coding: utf-8 -*-
"""Create an application instance."""
from flask.helpers import get_debug_flag

from conduit.extensions import db
from flask_migrate import Migrate
from conduit.app import create_app
from conduit.settings import DevConfig, ProdConfig

CONFIG = DevConfig if get_debug_flag() else ProdConfig
from conduit.articles.views import create_category

app = create_app(DevConfig)
app_context = app.app_context()
app_context.push()
db.create_all()
migrate = Migrate(app, db)


<<<<<<< HEAD
=======
app = create_app(CONFIG)

>>>>>>> 609330574307173c44b32a96fb032c867b4e338f
53 changes: 53 additions & 0 deletions conduit/articles/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,41 @@
db.Column("tag", db.Integer, db.ForeignKey("tags.id")),
db.Column("article", db.Integer, db.ForeignKey("article.id")))

category_assoc = db.Table("category_assoc",
db.Column("category", db.Integer, db.ForeignKey("categories.id")),
db.Column("article", db.Integer, db.ForeignKey("article.id")))


category_tree =db.Table("category_tree",
db.Column("parent_id", db.Integer, db.ForeignKey("categories.id")),
db.Column("children_id", db.Integer, db.ForeignKey("categories.id")))


class Category(Model):
__tablename__ = 'categories'

id = db.Column(db.Integer, primary_key=True)
catname = db.Column(db.String(100))

parents = db.relationship('Category',
secondary = category_tree,
primaryjoin = (category_tree.c.parent_id==id),
secondaryjoin = (category_tree.c.children_id==id),
backref= db.backref('children_categories', lazy='dynamic'), lazy='dynamic'
)

def __init__(self, catname):
db.Model.__init__(self, catname=catname)

def __repr__(self):
return self.catname

def add_children(self, children):
if children not in self.parents:
self.parents.append(children)
return True
return False


class Tags(Model):
__tablename__ = 'tags'
Expand Down Expand Up @@ -64,6 +99,12 @@ class Article(SurrogatePK, Model):
backref='favorites',
lazy='dynamic')

categories = relationship(
'Category',
secondary=category_assoc,
backref='articles',
lazy='dynamic')

tagList = relationship(
'Tags', secondary=tag_assoc, backref='articles')

Expand Down Expand Up @@ -100,6 +141,18 @@ def remove_tag(self, tag):
return True
return False

def add_category(self, category):
if category not in self.categories:
self.categories.append(category)
return True
return False

def remove_tag(self, category):
if category in self.categories:
self.categories.remove(category)
return True
return False

@property
def favoritesCount(self):
return len(self.favoriters.all())
Expand Down
33 changes: 32 additions & 1 deletion conduit/articles/serializers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# coding: utf-8

from marshmallow import Schema, fields, pre_load, post_dump
from marshmallow import Schema, fields, pre_load, post_dump, post_load
import json
from .models import Category

from conduit.profile.serializers import ProfileSchema

Expand All @@ -18,6 +20,7 @@ class ArticleSchema(Schema):
updatedAt = fields.DateTime(dump_only=True)
author = fields.Nested(ProfileSchema)
article = fields.Nested('self', exclude=('article',), default=True, load_only=True)
categories = fields.List(fields.Str())
tagList = fields.List(fields.Str())
favoritesCount = fields.Int(dump_only=True)
favorited = fields.Bool(dump_only=True)
Expand Down Expand Up @@ -82,6 +85,34 @@ def make_comment(self, data, many):
return {'comments': data}



class CategorySchema(Schema):
catname = fields.Str()
id = fields.Int()


# for the envelope
category = fields.Nested('self', exclude=('category',), default=True, load_only=True)

@pre_load
def make_category(self, data):
if not data:
return None
return data['category']

@post_dump(pass_many=True)
def dump_category(self, data, many):
key = 'categories' if many else 'category'
return {
key : data
}


class Meta:
strict = True

category_schema = CategorySchema()
categories_schema = CategorySchema(many=True)
article_schema = ArticleSchema()
articles_schema = ArticleSchemas(many=True)
comment_schema = CommentSchema()
Expand Down
83 changes: 77 additions & 6 deletions conduit/articles/views.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
# coding: utf-8

import datetime as dt

from flask import Blueprint, jsonify
from pprint import pprint
from flask import Blueprint, jsonify, request
from flask_apispec import marshal_with, use_kwargs
from flask_jwt_extended import current_user, jwt_required, jwt_optional
from marshmallow import fields

from conduit.extensions import db
from conduit.exceptions import InvalidUsage
from conduit.user.models import User
from .models import Article, Tags, Comment
from .models import Article, Tags, Comment, Category
from .serializers import (article_schema, articles_schema, comment_schema,
comments_schema)
comments_schema, categories_schema, category_schema)

blueprint = Blueprint('articles', __name__)

Expand Down Expand Up @@ -40,9 +40,21 @@ def get_articles(tag=None, author=None, favorited=None, limit=20, offset=0):
@jwt_required
@use_kwargs(article_schema)
@marshal_with(article_schema)
def make_article(body, title, description, tagList=None):
def make_article(body, title, description, tagList=None, categories=None):
article = Article(title=title, description=description, body=body,
author=current_user.profile)
if categories is not None:
for category in categories:
mcategory = Category.query.filter_by(catname=category).first()
if not mcategory:
mcategory = Category(catname=category)
mcategory.save()
article.add_category(mcategory)
else:
mcategory = Category(catname='uncategorized')
mcategory.save()
article.add_category(mcategory)

if tagList is not None:
for tag in tagList:
mtag = Tags.query.filter_by(tagname=tag).first()
Expand Down Expand Up @@ -166,3 +178,62 @@ def delete_comment_on_article(slug, cid):
comment = article.comments.filter_by(id=cid, author=current_user.profile).first()
comment.delete()
return '', 200

##########
#category
#########

@blueprint.route('/api/categories', methods=['POST'])
@jwt_required
def create_category():
json_data = request.get_json()
if not request.json or not 'category' in json_data:
return jsonify({'message': 'field is empty, please cross check', 'status': 404}), 404
data, errors = category_schema.load(json_data)
category = Category.query.filter_by(catname=data['catname']).first()
if not category:
category_name = Category(catname=data['catname'])
db.session.add(category_name)
db.session.commit()
data, errors = category_schema.dump(category_name)
print(data)
return jsonify(data) ,201
return jsonify({'message': 'category already exixts'}), 404

@blueprint.route('/api/categories/<int:id>', methods=['DELETE'])
@jwt_required
def remove_category(id):
category = Category.query.filter_by(id=id).first()
if not category:
return jsonify({'message': 'not found', 'status': 404}), 404
db.session.delete(category)
return jsonify({'category':{'id': id , 'message': 'category has been deleted'}, 'status': 200}), 200


@blueprint.route('/api/categories/<int:id>/category', methods=['PATCH'])
@jwt_required
def edit_category(id):
json_data = request.get_json()
data, errors = category_schema.load(json_data)
category = Category.query.filter_by(id=id).first()
if not category:
return jsonify({'message': 'not found', 'status': 404}) ,404
else:
category.update(catname=data['catname'])
db.session.add(category)
db.session.commit()
return jsonify({'category': {'id':id, 'message': \
'has been updated'}, 'status': 200}), 200


@blueprint.route('/api/categories', methods=['GET'])
@jwt_required
def fetch_all_categories():
categories = Category.query.all()
if not categories :
return jsonify({'message': ' not found', 'status' : 404}) ,404
data, errors = categories_schema.dump(categories)
return jsonify(data), 200



45 changes: 45 additions & 0 deletions conduit/docs/create_category.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
conduit/docs/create_category.yml

create category
---
paths:
/categories:
post:
description: creates new category entity in the database table categories
parameters:
- in: header
name: Authorization
description: authorization header
required: true
schema:
type: string
id: Token
requestBody:
required: true
content:
application/json:
schema:
type: object
parameters:
catname:
type: string
example: Music

responses:
201:
description: Category successfully created.
400:
description: category was not in right format
security:
- JWT:
description: Pass in jwt token. i.e Token <jwt>
-in: header
name: Authorization
type: apiKey
scheme: bearer
bearerFormat: JWT
tags:
- Category



45 changes: 45 additions & 0 deletions conduit/docs/delete_category.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
conduit/docs/delete_category.yml

delete category
---
paths:
/categories/{id}:
delete:
description: deletes an existing category entity in the database
parameters:
- in: header
name: Authorization
description: authorization header
required: true
schema:
type: string
id: Token
responses:
200:
description: Category successfully deleted.
content:
application/json:
schema:
type: object
parameters:
id:
type: integer
example: 2
message:
type: string
example: category has been deleted
404:
description: category was not found
security:
- JWT:
description: Pass in jwt token. i.e Token <jwt>
-in: header
name: Authorization
type: apiKey
scheme: bearer
bearerFormat: JWT
tags:
- Category



Loading