-
Notifications
You must be signed in to change notification settings - Fork 0
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
Phone book app #2
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1 @@ | ||
Volume in drive C has no label. | ||
Volume Serial Number is 6A28-DEF7 | ||
|
||
Directory of C:\Users\yegon\Desktop\WeConnect | ||
|
||
26-Feb-18 03:56 PM <DIR> . | ||
26-Feb-18 03:56 PM <DIR> .. | ||
25-Feb-18 07:06 PM 641 app.py | ||
26-Feb-18 07:31 AM <DIR> Designs | ||
26-Feb-18 03:56 PM 0 README.md | ||
25-Feb-18 07:02 PM <DIR> templates | ||
2 File(s) 641 bytes | ||
4 Dir(s) 2,639,093,760 bytes free | ||
A phone book app that allows one to add, update, delete and view contacts. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
A phone book app that allows one to add, update, delete and view contacts. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
from flask import Flask, render_template, request, redirect, url_for, session, flash, logging | ||
from wtforms import Form, StringField, PasswordField, validators, TextField, BooleanField,DateField | ||
import os | ||
|
||
app = Flask(__name__) | ||
|
||
# Load default config and override config from an environment variable | ||
app.config.update(dict( | ||
DATABASE=os.path.join(app.root_path, 'app.db'), | ||
SECRET_KEY='development key', | ||
USERNAME='admin', | ||
PASSWORD='default' | ||
)) | ||
|
||
phone_book = [{'name':'James', 'phone':'00007777'}, | ||
{'name':'John', 'phone':'07333333'}, | ||
{'name':'Bill', 'phone':'07444444'}] | ||
store = {} | ||
#home | ||
@app.route('/') | ||
def home(): | ||
Lists = phone_book | ||
for item in Lists: | ||
return render_template("home.html", Lists=Lists) | ||
else: | ||
msg = 'No List Found' | ||
return render_template("home.html", msg=msg) | ||
|
||
|
||
#Contact Form class | ||
class addForm(Form): | ||
name = StringField('name', [validators.Length(min = 1, max = 1000)]) | ||
phone = StringField('phone', [validators.Length(min = 3, max = 10)]) | ||
|
||
#Add details | ||
@app.route('/add_contact', methods=['GET', 'POST']) | ||
def add_contact(): | ||
form = addForm(request.form) | ||
if request.method == 'POST' and form.validate(): | ||
name = request.form['name'] | ||
phone = request.form['phone'] | ||
store['name'] = name | ||
store['phone'] = phone | ||
phone_book.insert(0,store) | ||
|
||
flash('contact created', 'success') | ||
return redirect(url_for('home')) | ||
|
||
return render_template("add_contact.html", form=form) | ||
|
||
@app.route('/delete_contact/<string:Id>', methods=['POST']) | ||
def delete_contact(Id): | ||
for item in store: | ||
del store['name'] | ||
del store['phone'] | ||
flash('contact Removed', 'success') | ||
return redirect(url_for('home')) | ||
else: | ||
msg = 'No contacts Found' | ||
return render_template("home.html", msg=msg) | ||
|
||
@app.route('/edit_contact/<string:Id>', methods=['GET', 'POST']) | ||
def edit_contact(Id): | ||
form = addForm(request.form) | ||
if store == {}: | ||
msg = 'No List Found' | ||
return render_template("home.html", msg=msg) | ||
else: | ||
#get item by title | ||
for item in store: | ||
#populate form fields | ||
request.form['name']= store['name'] | ||
request.form['phone'] = store['phone'] | ||
if request.method == 'POST' and form.validate(): | ||
name = request.form['name'] | ||
phone = request.form['phone'] | ||
store['name'] = name | ||
store['phone'] = phone | ||
phone_book.append(store) | ||
|
||
flash('List edited', 'success') | ||
return redirect(url_for('home')) | ||
|
||
return render_template("edit_contact.html", form=form) | ||
|
||
|
||
if __name__ == "__main__": | ||
app.secret_key='ThisIsSecret' | ||
port = int(os.environ.get("PORT", 5000)) | ||
app.run(host="0.0.0.0", port=port, debug=True) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{% extends 'layout.html' %} | ||
|
||
{% block body %} | ||
<div class="jumbotron text-center"> | ||
<h3>Add Contact</h3> | ||
<form method="POST"> | ||
<div class="form.group"> | ||
<label for="username">Name</label> | ||
<input type="text" name="name" class="form-control" id="name" value={{request.form.name}}> | ||
</div> | ||
<div class="form-group"> | ||
<label for="phone">Phone</label> | ||
<input type="text" name="phone" class="form-control" id="phone" value={{request.form.phone}}> | ||
<input type="submit" class="btn btn-primary" value="Submit" ></th> | ||
<th><h4><a href="/index" class="btn btn-danger">Cancel</a></h4></th> | ||
|
||
</form> | ||
</div> | ||
{% endblock %} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
{% extends 'layout.html' %} | ||
|
||
{% block body %} | ||
<div class="jumbotron text-center"> | ||
<h3>Edit contact</h3> | ||
<div class="form.group"> | ||
<label for="username">Name</label> | ||
<input type="text" name="username" class="form-control" id="username" value={{request.form.name}}> | ||
</div> | ||
<div class="form-group"> | ||
<label for="phone">Phone</label> | ||
<input type="text" name="text" class="form-control" id="password" value={{request.form.phone}}> | ||
<input type="submit" class="btn btn-primary" value="Submit" ></th> | ||
<th><h4><a href="index.html" class="btn btn-danger">Cancel</a></h4></th> | ||
|
||
</form> | ||
</div> | ||
{% endblock %} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
<html> | ||
<head> | ||
<meta charset="utf -8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> | ||
<title>PhoneBook</title> | ||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" | ||
integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous"> | ||
<link rel="stylesheet" href="style.css"> | ||
|
||
</head> | ||
<body> | ||
<div class="container text-center"> | ||
<h3><span class="glyphicon glyphicon-cog" aria-hidden="true"></span> Dashboard <small>Add phone number</small></h3> | ||
<a class="btn btn-success" href="/add_contact">Create a New Contact</a> | ||
<p><div class="text-left"><h5> Available Contacts</h5></div></p> | ||
<hr> | ||
<table class="table table-striped"> | ||
<tr> | ||
|
||
<th>Name</th> | ||
<th>Phone Number</th> | ||
<th>Edit Contact</th> | ||
<th>Remove Contact</th> | ||
|
||
|
||
</tr> | ||
|
||
{% for item in Lists %} | ||
<tr> | ||
<td>{{item.name}}</td> | ||
<td>{{item.phone}}</td> | ||
<td><a href="edit_contact/{{item.name}}" class="btn btn-default pullright">Edit Contact</a></td> | ||
<td> | ||
<form action="{{url_for('delete_contact', Id=item.name)}}" method="POST"> | ||
<input type="hidden" name="_method" value="DELETE"> | ||
<input type="submit" value="Delete Contact" class="btn btn-danger"> | ||
</form> | ||
</td> | ||
</tr> | ||
{% endfor %} | ||
</table> | ||
</div> | ||
|
||
|
||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js" | ||
integrity="sha384-h0AbiXch4ZDo7tp9hKZ4TsHbi047NrKGLO3SEJAg45jXxnGIfYzk4Si90RDIqNm1" crossorigin="anonymous"></script> | ||
</body> | ||
</html> | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<html> | ||
<head> | ||
<meta charset="utf -8"> | ||
<title>PhoneBook</title> | ||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" | ||
integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous"> | ||
|
||
</head> | ||
<body> | ||
<div class="container"> | ||
{% block body %}{% endblock %} | ||
|
||
<div id="footer" class="container text-center"> | ||
{% block footer %} | ||
© Copyright 2018 by <a href="https://plus.google.com/u/0/110292840337102395926">Bonifase Otieno</a>. | ||
{% endblock %} | ||
</div> | ||
|
||
</div> | ||
|
||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js" | ||
integrity="sha384-h0AbiXch4ZDo7tp9hKZ4TsHbi047NrKGLO3SEJAg45jXxnGIfYzk4Si90RDIqNm1" crossorigin="anonymous"></script> | ||
</body> | ||
</html> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import os | ||
import app | ||
import unittest | ||
import tempfile | ||
|
||
class AppTestCase(unittest.TestCase): | ||
|
||
def setUp(self): | ||
self.db_fd, app.app.config['DATABASE'] = tempfile.mkstemp() | ||
app.app.testing = True | ||
self.app = app.app.test_client() | ||
with app.app.app_context(): | ||
app.phone_book | ||
|
||
def tearDown(self): | ||
os.close(self.db_fd) | ||
os.unlink(app.app.config['DATABASE']) | ||
#test home page | ||
def test_empty_db(self): | ||
rv = self.app.get('/') | ||
assert 'No entries here so far' | ||
|
||
|
||
#test add contact method | ||
def test_add_contact(self): | ||
rv = self.app.post('/add_contact', data=dict(name='<anything>', phone='<anything>'), follow_redirects=True) | ||
assert 'anything' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like your naming convention, keep it up. On the other hand, what do you think about including the expected results? The expected result tells the tester what they should experience as a result of the test steps. This is how the tester determines if the test case is a “pass” or “fail”. |
||
assert 'anything' | ||
#test delete contact | ||
def test_delete_contact(self): | ||
rv = self.app.post('/delete_contact', data=dict(name='<anything>', phone='<anything>'), follow_redirects=True) | ||
assert 'anything' | ||
assert 'anything' | ||
|
||
#test delete contact method | ||
def test_edit_contact(self): | ||
rv = self.app.post('/test_edit_contact', data=dict(name='<anything>', phone='<anything>'), follow_redirects=True) | ||
assert 'anything' | ||
assert 'anything' | ||
|
||
|
||
if __name__ == '__main__': | ||
unittest.main() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the flow of execution. What do you think about making your code DRY and applying MVC?This will enable other developers to easily understand your code and do maintenance. DRY will also allow some codes to be reusable.