Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backend #23

Open
wants to merge 3 commits into
base: Backend
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
19 changes: 19 additions & 0 deletions core/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,20 @@
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
from flask import Flask


app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db'
# should be hidden in environment variable
app.config['SECRET_KEY'] = 'lc\xf6\xa5\x90LJ\x17=68\x9eK\x9dtM?%\x8b\xb8\xb0cvo'

db = SQLAlchemy(app)
login_manager = LoginManager(app)

from core.main import main
from core.user import user
from core.writer import writer

app.register_blueprint(main)
app.register_blueprint(user,url_prefix='/user')
app.register_blueprint(writer,url_prefix='/writer')
Binary file added core/__pycache__/__init__.cpython-38.pyc
Binary file not shown.
Binary file added core/__pycache__/__init__.cpython-39.pyc
Binary file not shown.
Binary file added core/__pycache__/forms.cpython-39.pyc
Binary file not shown.
Binary file added core/__pycache__/models.cpython-39.pyc
Binary file not shown.
Binary file added core/__pycache__/routes.cpython-39.pyc
Binary file not shown.
36 changes: 36 additions & 0 deletions core/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from flask_wtf import FlaskForm
from wtforms import (StringField, PasswordField, BooleanField, SubmitField, TextAreaField,
SelectField, DateField, RadioField)
from wtforms.validators import DataRequired, EqualTo, Length, Email
from wtforms.widgets.html5 import DateInput



class SignUpForm(FlaskForm):
username = StringField('Username', validators=[DataRequired(), Length(min=3, max=40)])
email = StringField('Email', validators=[DataRequired(), Email()])
gender = SelectField('Gender',choices=['Male','Female'])
date_of_birth = DateField('Date of Birth', validators=[DataRequired()], widget=DateInput())
password = PasswordField('Password', validators=[DataRequired()])
confirm_password = PasswordField('Confirm Password', validators=[DataRequired(), EqualTo('password')])
is_writer = RadioField('Are you a writer?',choices=['Yes','No'])
submit = SubmitField('Sign Up')


class LoginForm(FlaskForm):
email = StringField('Email', validators=[DataRequired(), Email()])
password = PasswordField('Password', validators=[DataRequired()])
submit = SubmitField('Log in')

class PostForm(FlaskForm):
title = StringField('Title', validators=[DataRequired()])
content = TextAreaField('Content', validators=[DataRequired(), Length(min=10)])
submit = SubmitField('Submit')


class UpdateProfileForm(FlaskForm):
username = StringField('Username', validators=[DataRequired()])
email = StringField('Email', validators=[DataRequired(), Email()])
gender = SelectField('Gender', choices=['Male', 'Female'])
date_of_birth = DateField('Date of Birth', validators=[DataRequired()], widget=DateInput())
submit = SubmitField('Update')
5 changes: 5 additions & 0 deletions core/main/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from flask import Blueprint

main = Blueprint('main', __name__)

from core.main import views
Binary file added core/main/__pycache__/__init__.cpython-39.pyc
Binary file not shown.
Binary file added core/main/__pycache__/routes.cpython-39.pyc
Binary file not shown.
Binary file added core/main/__pycache__/views.cpython-39.pyc
Binary file not shown.
85 changes: 85 additions & 0 deletions core/main/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
from flask import Flask, render_template, request, redirect, url_for, flash
from flask_login import login_user, logout_user, current_user, login_required
from core import login_manager,db
from core.models import User,Post
from core.forms import LoginForm, SignUpForm, UpdateProfileForm


from core.main import main


@login_manager.user_loader
def load_user(user_id):
return User.query.get(user_id)


@main.route('/', methods=['GET'])
@main.route('/home', methods=['GET'])
def index():
posts = Post.query.all()
return render_template('index.html', title='Home Page',posts=posts)

@main.route('/about')
def about():
return render_template('about.html')


@main.route('/login', methods=['GET', 'POST'])
def login():
if current_user.is_authenticated:
return redirect(url_for('main.index'))
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(email=form.email.data).first()
if user and form.password.data == user.password:
login_user(user)
next_page = request.args.get('next')
flash(f'Login successful! Welcome {user.username}', 'success')
# When the login view is redirected to, it will have a next variable in the query string,
# which is the page that the user was trying to access.
return redirect(next_page) if next_page else redirect(url_for('main.index'))
else:
flash('Please check login details or signup to continue!', 'danger')
return redirect(url_for('main.signup'))
return render_template('login.html', form=form)


@main.route('/signup', methods=['GET', 'POST'])
def signup():
form = SignUpForm()
if form.validate_on_submit():
user = User(username=form.username.data, email=form.email.data,
gender=form.gender.data, date_of_birth=form.date_of_birth.data,
password=form.password.data, is_writer=form.is_writer.data)
db.session.add(user)
db.session.commit()
flash('Account created successfully! Proceed to login with the credentials you just provided.', 'success')
return redirect(url_for('main.login'))
return render_template('signup.html', title='Sign Up', form=form)


@main.route('/<username>', methods=['GET', 'POST'])
@login_required
def profile(username):
user = User.query.filter_by(username=username).first()
return render_template('profile.html', title='Profile Page',user=user)


@main.route('/<username>/edit', methods=['GET', 'POST'])
@login_required
def edit_profile(username):
form = UpdateProfileForm()
if request.method == 'GET':
form.username.data = current_user.username
form.email.data = current_user.email
form.gender.data = current_user.gender
form.date_of_birth.data = current_user.date_of_birth
elif form.validate_on_submit():
current_user.username = form.username.data
current_user.email = form.email.data
current_user.gender = form.gender.data
current_user.date_of_birth = form.date_of_birth.data
db.session.commit()
flash('Account successfully updated!','success')
return redirect(url_for('main.profile',username=current_user.username))
return render_template('updateprofile.html',form=form)
28 changes: 28 additions & 0 deletions core/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from typing import Collection
from flask_login import UserMixin
from core import db
from datetime import datetime

class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), nullable=False)
email = db.Column(db.String(120), nullable=False, unique=True)
gender = db.Column(db.String(10),nullable=False)
date_of_birth = db.Column(db.Date,nullable=False)
password = db.Column(db.String(20), nullable=False)
is_writer = db.Column(db.String(10),nullable=False)
posts = db.relationship('Post',backref='author',lazy=True)

def __repr__(self):
return f'User {self.id}'


class Post(db.Model):
id = db.Column(db.Integer,primary_key=True)
title = db.Column(db.String(100),nullable=False)
date_created = db.Column(db.DateTime,nullable=False,default=datetime.utcnow)
content = db.Column(db.Text,nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))

def __repr__(self):
return f"Post ({self.title},{self.date_created })"
Binary file added core/site.db
Binary file not shown.
7 changes: 7 additions & 0 deletions core/static/main.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
body {
padding-top: 5rem;
}
.starter-template {
padding: 3rem 1.5rem;
text-align: center;
}
5 changes: 5 additions & 0 deletions core/templates/about.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{% extends 'base.html' %}

{% block body %}
<h3>ABOUT PAGE</h3>
{% endblock %}
47 changes: 47 additions & 0 deletions core/templates/base.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MTC FLASK</title>

<link rel="canonical" href="https://getbootstrap.com/docs/4.0/examples/starter-template/">

<!-- Bootstrap core CSS -->
<link href="https://getbootstrap.com/docs/4.0/dist/css/bootstrap.min.css" rel="stylesheet">

<!-- Custom styles for this template -->
<link href="{{ url_for('static',filename='main.css') }}" rel="stylesheet">

</head>
<body>
{% include 'includes/_navbar.html' %}
<main role="main" class="container">
<div class="col-md-8">
{% with messages = get_flashed_messages(with_categories=True) %}
{% if messages %}
{% for category,message in messages %}
<div class="alert alert-{{ category }}">
<!-- the value of catrgory is the success we passed to flash in app.py -->
{{ message }}
</div>
{% endfor %}
{% endif %}
{% endwith %}
{% block body %}{% endblock %}
</div>

</main><!-- /.container -->

<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
crossorigin="anonymous"></script>
<script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery-slim.min.js"><\/script>')</script>
<script src="../../assets/js/vendor/popper.min.js"></script>
<script src="../../dist/js/bootstrap.min.js"></script>
</body>
</html>
5 changes: 5 additions & 0 deletions core/templates/dashboard.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{% extends 'base.html' %}

{% block body %}
<p>Welcome {{ session.username }}</p>
{% endblock %}
42 changes: 42 additions & 0 deletions core/templates/includes/_navbar.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
<a class="navbar-brand" href="#">FLASK APP</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault"
aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>

<div class="collapse navbar-collapse" id="navbarsExampleDefault">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="{{ url_for('main.index') }}">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('main.about') }}">About</a>
</li>
</ul>

</form>
<div class="nav navbar-nav nabvar-right">
{% if current_user.is_authenticated %}
{% if current_user.is_writer == 'Yes' %}
<li class="nav-item">
<a href="{{ url_for('writer.new_post') }}" class="nav-link">New Post</a>
</li>
{% endif %}
<li class="nav-item">
<a href="{{ url_for('main.profile',username=current_user.username) }}" class="nav-link">Profile</a>
</li>
<li class="nav-item">
<a href="{{ url_for('user.logout') }}" class="nav-link">Log out</a>
</li>
{% else %}
<li class="nav_item">
<a href="{{ url_for('main.login') }}" class="nav-link">Log In</a>
</li>
<li class="nav_item">
<a href="{{ url_for('main.signup') }}" class="nav-link">Sign Up</a>
</li>
{% endif %}
</div>
</div>
</nav>
32 changes: 32 additions & 0 deletions core/templates/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{% extends 'base.html' %}

{% block body %}

{% for post in posts %}
{% if current_user.is_authenticated %}
<article class="media content-section">
<div class="media-body">
<div class="article-metadata">
<a class="mr-2" href="{{ url_for('main.profile',username=post.author.username) }}">{{
post.author.username}}</a>
<small class="text-muted">{{ post.date_created.date() }}</small>
</div>
<h2><a class="article-title" href="{{ url_for('writer.post',post_id=post.id) }}">{{ post.title }}</a></h2>
<p class="article-content">{{ post.content }}</p>
</div>
</article>
{% else %}
<article class="media content-section">
<div class="media-body">
<div class="article-metadata">
<p class="mr-2" style="display: inline;">{{post.author.username}}</p>
<small class="text-muted">{{ post.date_created.date() }}</small>
</div>
<h2 class="article-title">{{ post.title }}</h2>
<p class="article-content">{{ post.content }}</p>
</div>
</article>
{% endif %}
{% endfor %}

{% endblock %}
43 changes: 43 additions & 0 deletions core/templates/login.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{% extends 'base.html' %}

{% block body %}

<div class="content-section">
<form action="" method="POST">
{{ form.hidden_tag() }}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Sign In</legend>
<div class="form-group">
{{ form.email.label(class="form-control-label") }}
{% if form.email.errors %}
{{ form.email(class="form-control form-control-lg is-invalid") }}
{% for error in form.email.errors %}
<div class="invalid-feedback">
{{ error }}
</div>
{% endfor %}
{% else %}
{{ form.email(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class="form-group">
{{ form.password.label(class="form-control-label") }}
{% if form.password.errors %}
{{ form.password(class="form-control form-control-lg is-invalid") }}
{% for error in form.password.errors %}
<div class="invalid-feedback">
{{ error }}
</div>
{% endfor %}
{% else %}
{{ form.password(class="form-control form-control-lg") }}
{% endif %}
</div>
</fieldset>
<div class="form-group">
{{ form.submit(class="btn btn-outline-info") }}
</div>
</form>
</div>

{% endblock %}
Loading