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

Phone book app #2

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
14 changes: 1 addition & 13 deletions README.md
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.
1 change: 1 addition & 0 deletions phoneBook/README.md
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.
Binary file added phoneBook/__pycache__/app.cpython-36.pyc
Binary file not shown.
90 changes: 90 additions & 0 deletions phoneBook/app.py
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)
Copy link

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.


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)
19 changes: 19 additions & 0 deletions phoneBook/templates/add_contact.html
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 %}
18 changes: 18 additions & 0 deletions phoneBook/templates/edit_contact.html
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 %}
60 changes: 60 additions & 0 deletions phoneBook/templates/home.html
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>












24 changes: 24 additions & 0 deletions phoneBook/templates/layout.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 %}
&copy; 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>
43 changes: 43 additions & 0 deletions phoneBook/test_app.py
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'
Copy link

Choose a reason for hiding this comment

The 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()