import other kontor repos into directories

This commit is contained in:
Thomas Peetz
2025-01-09 19:28:50 +01:00
parent 8120c92b32
commit 9b329c0ac4
319 changed files with 17211 additions and 0 deletions
+12
View File
@@ -0,0 +1,12 @@
.idea/
__pycache__/
bin/
include/
lib/
lib64
pip-selfcheck.json
*.pyc
kontor.properties
*.nja
dist/
kontor_bottle.egg-info/
+13
View File
@@ -0,0 +1,13 @@
node {
stage("Checkout") {
checkout scm
}
stage("setup virualenv") {
sh "virtualenv ."
sh "source bin/activate; pip install bottle pymongo"
}
stage("build") {
sh "source bin/activate; python setup.py sdist"
}
}
+2
View File
@@ -0,0 +1,2 @@
# Kontor Bottle
+196
View File
@@ -0,0 +1,196 @@
# -*- coding:utf-8 -*-
import pymongo
import publisherDAO
import artistDAO
import comicDAO
import storyArcDAO
import bottle
import cgi
__author__ = 'tpeetz'
class Plugin:
def __init__(self, app, database, sessions):
self.app = app
self.db = database
self.sessions = sessions
self.publishers = publisherDAO.PublisherDAO(database)
self.artists = artistDAO.ArtistDAO(database)
self.comics = comicDAO.ComicDAO(database)
self.storyarcs = storyArcDAO.StoryArcDAO(database)
self.routing()
def routing(self):
self.app.route('/comics', 'GET', self.comic_index)
self.app.route('/comics/', 'GET', self.comic_index)
self.app.route('/comics/comic', 'GET', self.comic_list)
self.app.route('/comics/comic/<id>', 'GET', self.comic_details)
self.app.route('/comics/comic/create', 'GET', self.get_comic_create)
self.app.route('/comics/comic/create', 'POST', self.post_create_comic)
self.app.route('/comics/publisher', 'GET', self.publisher_list)
self.app.route('/comics/publisher/<id>', 'GET', self.publisher_details)
self.app.route('/comics/publisher/create', 'GET', self.get_publisher_create)
self.app.route('/comics/publisher/create', 'POST', self.post_create_publisher)
self.app.route('/comics/artist', 'GET', self.artist_list)
self.app.route('/comics/artist/<id>', 'GET', self.artist_details)
self.app.route('/comics/artist/create', 'GET', self.get_artist_create)
self.app.route('/comics/artist/create', 'POST', self.post_create_artist)
self.app.route('/comics/storyarc', 'GET', self.storyarc_list)
self.app.route('/comics/storyarc/<id>', 'GET', self.storyarc_details)
self.app.route('/comics/storyarc/create', 'GET', self.get_storyarc_create)
self.app.route('/comics/storyarc/create', 'POST', self.post_create_storyarc)
def comic_index(self):
cookie = bottle.request.get_cookie("session")
username = self.sessions.get_username(cookie)
return bottle.template('comic_index', dict(username=username))
def comic_list(self):
cookie = bottle.request.get_cookie("session")
username = self.sessions.get_username(cookie)
l = self.comics.get_comics()
return bottle.template('comic_list', dict(comics=l, username=username))
def comic_details(self, id):
cookie = bottle.request.get_cookie("session")
username = self.sessions.get_username(cookie)
comic = self.comics.get_comic(id)
errors = ""
if comic == None:
errors = "Entry not found"
return bottle.template('comic_template', dict(title=comic['title'],
id=comic['_id'],
current_order=comic['current_order'],
completed=comic['completed'],
errors="",
username=username))
def get_comic_create(self):
cookie = bottle.request.get_cookie("session")
username = self.sessions.get_username(cookie)
return bottle.template("comic_template", dict(title="",
id='newentry',
current_order=False,
completed=False,
errors="",
username=username))
def post_create_comic(self):
comic_id = bottle.request.forms.get("id")
comic_title = bottle.request.forms.get("title")
comic_order = bottle.request.forms.get("current_order")
comic_completed = bottle.request.forms.get("completed")
if comic_id == "newentry":
self.comics.insert_entry(comic_title, None, comic_order, comic_completed)
else:
self.comics.update_entry(comic_id, comic_title, None, comic_order, comic_completed)
bottle.redirect("/comics/comic")
def publisher_list(self):
cookie = bottle.request.get_cookie("session")
username = self.sessions.get_username(cookie)
l = self.publishers.get_publishers()
return bottle.template('publisher_list', dict(publishers=l, username=username))
def publisher_details(self, id):
cookie = bottle.request.get_cookie("session")
username = self.sessions.get_username(cookie)
publisher = self.publishers.get_publisher(id)
errors = ""
if publisher == None:
errors= "Entry not found"
return bottle.template('publisher_template', dict(name=publisher['name'], id=publisher['_id'], errors="", username=username))
def get_publisher_create(self):
cookie = bottle.request.get_cookie("session")
username = self.sessions.get_username(cookie)
return bottle.template("publisher_template", dict(name="", id='newentry', errors="", username=username))
def post_create_publisher(self):
cookie = bottle.request.get_cookie("session")
username = self.sessions.get_username(cookie)
publisher_id = bottle.request.forms.get("id")
publisher_name = bottle.request.forms.get("name")
if publisher_id == "newentry":
self.publishers.insert_entry(publisher_name)
else:
self.publishers.update_entry(publisher_id, publisher_name)
bottle.redirect("/comics/publisher")
def artist_list(self):
cookie = bottle.request.get_cookie("session")
username = self.sessions.get_username(cookie)
l = self.artists.get_artists()
return bottle.template('artist_list', dict(artists=l, username=username))
def artist_details(self, id):
cookie = bottle.request.get_cookie("session")
username = self.sessions.get_username(cookie)
artist = self.artists.get_artist(id)
errors = ""
if artist == None:
errors= "Entry not found"
return bottle.template('artist_template', dict(name=artist['name'], id=artist['_id'], errors="", username=username))
def get_artist_create(self):
cookie = bottle.request.get_cookie("session")
username = self.sessions.get_username(cookie)
return bottle.template("artist_template", dict(name="", id='newentry', errors="", username=username))
def post_create_artist(self):
artist_id = bottle.request.forms.get("id")
artist_name = bottle.request.forms.get("name")
if artist_id == "newentry":
self.artists.insert_entry(artist_name)
else:
self.artists.update_entry(artist_id, artist_name)
bottle.redirect("/comics/artist")
def storyarc_list(self):
cookie = bottle.request.get_cookie("session")
username = self.sessions.get_username(cookie)
l = self.storyarcs.get_storyarcs()
return bottle.template('storyarc_list', dict(storyarcs=l, username=username))
def storyarc_details(self, id):
cookie = bottle.request.get_cookie("session")
username = self.sessions.get_username(cookie)
storyarc = self.storyarcs.get_storyarc(id)
errors = ""
if storyarc == None:
errors = "Entry not found"
return bottle.template('storyarc_template', dict(title=storyarc['title'], id=storyarc['_id'], errors="", username=username))
def get_storyarc_create(self):
cookie = bottle.request.get_cookie("session")
username = self.sessions.get_username(cookie)
return bottle.template("storyarc_template", dict(title="", id='newentry', errors="", username=username))
def post_create_storyarc(self):
storyarc_id = bottle.request.forms.get("id")
storyarc_title = bottle.request.forms.get("title")
if storyarc_id == "newentry":
self.storyarcs.insert_entry(storyarc_title)
else:
self.storyarcs.update_entry(storyarc_id, storyarc_title)
bottle.redirect("/comics/storyarc")
+50
View File
@@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
from bson.objectid import ObjectId
import sys
class ArtistDAO:
# constructor for the class
def __init__(self, database):
self.db = database
self.artists = database.artists
def get_artists(self):
cursor = self.artists.find()
l = []
for artist in cursor:
l.append({'name':artist['name'], '_id':artist['_id']})
return l
def get_artist(self, artist_id):
artist = self.artists.find_one({"_id": ObjectId(artist_id)})
return artist
def insert_entry(self, artist_name):
print "inserting artist entry", artist_name
artist = {"name": artist_name}
# now insert the post
try:
result = self.artists.insert_one(artist)
print "Matching artist: ", result.matched_count
print "Modified artist: ", result.modified_count
except:
print "Error inserting artist"
print "Unexpected error:", sys.exc_info()
def update_entry(self, artist_id, artist_name):
print "upserting artist entry", artist_name
filter_doc = {"_id": ObjectId(artist_id)}
artist = { "$set": {"name": artist_name}}
# now insert the post
try:
result = self.artists.update_one(filter_doc, artist)
print "Modified artist: ", result.modified_count
except:
print "Error inserting artist"
print "Unexpected error:", sys.exc_info()
+53
View File
@@ -0,0 +1,53 @@
# -*- coding: utf-8 -*-
from bson.objectid import ObjectId
import sys
class ComicDAO:
# constructor for the class
def __init__(self, database):
self.db = database
self.comics = database.comics
def get_comics(self):
cursor = self.comics.find()
l = []
for comic in cursor:
l.append({'title':comic['title'],
'_id':comic['_id'],
'current_order':comic['current_order'],
'completed':comic['completed']})
return l
def get_comic(self, comic_id):
comic = self.comics.find_one({"_id": ObjectId(comic_id)})
return comic
def insert_entry(self, comic_title, comic_publisher=None, comic_order=False, comic_completed=False):
print "inserting comic entry", comic_title
comic = {"title": comic_title, "current_order": comic_order, "completed": comic_completed}
# now insert the comic
try:
result = self.comics.insert_one(comic)
print "Modified comic: ", result.modified_count
except:
print "Error inserting comic"
print "Unexpected error:", sys.exc_info()
def update_entry(self, comic_id, comic_title, comic_publisher=None, comic_order=False, comic_completed=False):
print "upserting comic entry", comic_title
filter_doc = {"_id": ObjectId(comic_id)}
comic = { "$set": {"title": comic_title, 'current_order': comic_order, 'completed': comic_completed}}
# now insert the post
try:
result = self.comics.update_one(filter_doc, comic)
print "Matching comic: ", result.matched_count
print "Modified comic: ", result.modified_count
except:
print "Error inserting comic"
print "Unexpected error:", sys.exc_info()
+121
View File
@@ -0,0 +1,121 @@
# -*- coding: utf-8 -*-
from mongoengine import connect, Document
from mongoengine import StringField, BooleanField
from mongoengine import ListField, ReferenceField, GenericReferenceField
import pprint
class Publisher(Document):
name = StringField(required=True)
def __str__(self):
s = "Publisher(%s)" % self.name
return s
class Artist(Document):
name = StringField(required=True)
className = StringField()
def __str__(self):
s = "Artist(%s)" % self.name
return s
class Issue(Document):
number = StringField()
comic = GenericReferenceField()
is_read = BooleanField(default=False)
is_stock = BooleanField(default=False)
def __str__(self):
s = "Issue(%s # %s, %s)" % (self.comic.title, self.number, self.is_read)
return s
class StoryArc(Document):
name = StringField(required=True)
comic = GenericReferenceField()
issues = ListField(ReferenceField(Issue))
def __str__(self):
s = "StoryArc(%s, %s)" % (self.name, self.comic.title)
return s
class Volume(Document):
name = StringField(required=True)
comic = GenericReferenceField()
issues = ListField(ReferenceField(Issue))
def __str__(self):
s = "Volume(%s, %s, %s)" % (self.id, self.name, self.comic.title)
return s
class Comic(Document):
title = StringField(required=True)
publisher = ReferenceField(Publisher)
current_order = BooleanField()
completed = BooleanField()
issues = ListField(ReferenceField(Issue))
stories = ListField(ReferenceField(StoryArc))
def __str__(self):
if self.publisher is None:
s = "Comic(%s, %s, %s, %s)" % (self.title, self.publisher, self.current_order, self.completed)
return s
else:
s = "Comic(%s, %s, %s, %s)" % (
self.title, self.publisher.name, self.current_order, self.completed)
return s
class TradePaperback(Document):
comic = ReferenceField(Comic)
issue_start = StringField()
issue_end = StringField()
def __str__(self):
s = "TPB(%s)" % self.comic.title
return s
def get_publisher(name):
publisher = Publisher.objects(name=name)
if publisher.count() > 0:
return publisher[0]
else:
return None
def get_comic(title):
comic = Comic.objects(title=title)
if comic.count() > 0:
return comic[0]
else:
return None
def get_issue(title, number):
comic = get_comic(title)
issues = Issue.objects(number=number, comic=comic)
if issues.count() > 0:
return issues[0]
else:
return None
if __name__ == '__main__':
connect('comics')
for publisher in Publisher.objects:
pprint.pprint(publisher)
for artist in Artist.objects:
pprint.pprint(artist)
for comic in Comic.objects:
pprint.pprint(comic)
for issue in Issue.objects:
pprint.pprint(issue)
for story in StoryArc.objects:
pprint.pprint(story)
for tpb in TradePaperback.objects:
pprint.pprint(tpb)
+50
View File
@@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
from bson.objectid import ObjectId
import sys
class PublisherDAO:
# constructor for the class
def __init__(self, database):
self.db = database
self.publishers = database.publishers
def get_publishers(self):
cursor = self.publishers.find()
l = []
for publisher in cursor:
l.append({'name':publisher['name'], '_id':publisher['_id']})
return l
def get_publisher(self, publisher_id):
publisher = self.publishers.find_one({"_id": ObjectId(publisher_id)})
return publisher
def insert_entry(self, publisher_name):
print "inserting publisher entry", publisher_name
publisher = {"name": publisher_name}
# now insert the post
try:
result = self.publishers.insert_one(publisher)
print "Matching publisher: ", result.matched_count
print "Modified publisher: ", result.modified_count
except:
print "Error inserting publisher"
print "Unexpected error:", sys.exc_info()
def update_entry(self, publisher_id, publisher_name):
print "upserting publisher entry", publisher_name
filter_doc = {"_id": ObjectId(publisher_id)}
publisher = { "$set": {"name": publisher_name}}
# now insert the post
try:
result = self.publishers.update_one(filter_doc, publisher)
print "Modified publisher: ", result.modified_count
except:
print "Error inserting publisher"
print "Unexpected error:", sys.exc_info()
+49
View File
@@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
from bson.objectid import ObjectId
import sys
class StoryArcDAO:
# constructor for the class
def __init__(self, database):
self.db = database
self.storyarcs = database.storyarcs
def get_storyarcs(self):
cursor = self.storyarcs.find()
l = []
for storyarc in cursor:
l.append({'title': storyarc['title'], '_id': storyarc['_id']})
return l
def get_storyarc(self, storyarc_id):
storyarc = self.storyarcs.find_one({"_id": ObjectId(storyarc_id)})
return storyarc
def insert_entry(self, storyarc_title):
print "inserting publisher entry", storyarc_title
storyarc = {"name": storyarc_title}
# now insert the post
try:
result = self.storyarcs.insert_one(storyarc)
print "Matching storyarc: ", result.matched_count
print "Modified storyarc: ", result.modified_count
except:
print "Error inserting storyarc"
print "Unexpected error:", sys.exc_info()
def update_entry(self, storyarc_id, storyarc_title):
print "upserting storyarc entry", storyarc_title
filter_doc = {"_id": ObjectId(storyarc_id)}
storyarc = {"$set": {"name": storyarc_title}}
# now insert the post
try:
result = self.storyarcs.update_one(filter_doc, storyarc)
print "Modified storyarc: ", result.modified_count
except:
print "Error inserting storyarc"
print "Unexpected error:", sys.exc_info()
+28
View File
@@ -0,0 +1,28 @@
# -*- coding:utf-8 -*-
import pymongo
import bottle
import cgi
__author__ = 'tpeetz'
class Plugin:
def __init__(self, app, database, sessions):
self.app = app
self.db = database
self.sessions = sessions
self.routing()
def routing(self):
self.app.route('/office', 'GET', self.office_index)
self.app.route('/office/travel', 'GET', self.office_index)
def office_index(self):
cookie = bottle.request.get_cookie("session")
username = self.sessions.get_username(cookie)
return bottle.template('office_index', dict(username=username))
+109
View File
@@ -0,0 +1,109 @@
body {
font-family: sans-serif;
color: #333333;
padding: 3em 0 4em;
}
body,
.wrapper {
margin: 10px auto;
/*max-width: 60em;*/
}
header, main, section, footer {
border-radius: 0px 0.5em 0.5em;
border: 1px solid;
padding: 10px;
margin: 10px;
}
header {
position:fixed;
top:0px;
left:0px;
right:0px;
text-align:center;
padding: 10px;
background: lightgrey;
/*border-bottom: 1px solid #d5d5d5;*/
}
nav {
/*position: fixed;*/
/*padding-top: 10em; */
border-radius: 0px 0.5em 0.5em;
border: 1px solid;
padding: 0;
margin: 10px;
font-size: 0.91em;
float: left;
width: 15em;
background: lightskyblue;
border-color: skyblue;
}
nav ul {
padding: 0;
}
nav li {
list-style: none;
margin: 0.4em;
padding: 0;
}
nav ul ul {
margin: 0 0 0 2em;
padding: 0;
border: none;
}
nav ul ul li {
margin: 0.3em 0;
}
nav a {
display: block;
padding: 0.4em;
text-decoration: none;
font-weight: bold;
border: 1px solid blue;
border-radius: 10px;
box-shadow: 0px 5px 10px white inset;
background-color: skyblue;
color: #333;
}
nav a:focus,
nav a:hover {
color: royalblue;
background-color: gold;
}
main {
display: block;
background: lightblue;
border-color: #8a9da8;
margin-left: 15em;
min-width: 16em; /* Mindestbreite (der Überschrift) verhindert Anzeigefehler in modernen Browsern */
}
footer {
position:fixed;
padding: 10px;
margin-top: 10px;
bottom:0;
left: 0;
right:0;
background: lightgrey;
border-color: grey;
}
footer p {
float:right;
margin: 0;
}
+177
View File
@@ -0,0 +1,177 @@
# -*- coding: utf-8 -*-
import pymongo
import sessionDAO
import userDAO
import homeoffice
import comics
import library
import medien
import tradingcards
import ConfigParser
import bottle
import cgi
import re
__author__ = 'tpeetz'
app = bottle.Bottle()
def index():
cookie = bottle.request.get_cookie("session")
username = sessions.get_username(cookie)
return bottle.template('kontor', dict(username=username))
def show_signup():
return bottle.template("signup", dict(username="",
password="",
password_error="",
email="",
username_error="",
email_error="",
verify_error =""))
def process_signup():
email = bottle.request.forms.get("email")
username = bottle.request.forms.get("username")
password = bottle.request.forms.get("password")
verify = bottle.request.forms.get("verify")
# set these up in case we have an error case
errors = {'username': cgi.escape(username), 'email': cgi.escape(email)}
if validate_signup(username, password, verify, email, errors):
if not users.add_user(username, password, email):
# this was a duplicate
errors['username_error'] = "Username already in use. Please choose another"
return bottle.template("signup", errors)
session_id = sessions.start_session(username)
print session_id
bottle.response.set_cookie("session", session_id)
bottle.redirect("/welcome")
else:
print "user did not validate"
return bottle.template("signup", errors)
def show_login():
return bottle.template('login', dict(username="", password="", login_error=""))
def process_login():
username = bottle.request.forms.get("username")
password = bottle.request.forms.get("password")
print "user submitted ", username, "pass ", password
user_record = users.validate_login(username, password)
if user_record:
# username is stored in the user collection in the _id key
session_id = sessions.start_session(user_record['_id'])
if session_id is None:
bottle.redirect("/internal_error")
cookie = session_id
# Warning, if you are running into a problem whereby the cookie being set here is
# not getting set on the redirect, you are probably using the experimental version of bottle (.12).
# revert to .11 to solve the problem.
bottle.response.set_cookie("session", cookie)
bottle.redirect("/")
else:
return bottle.template("login", dict(username=cgi.escape(username), password="", login_error="Invalid Login"))
def process_logout():
cookie = bottle.request.get_cookie("session")
sessions.end_session(cookie)
bottle.response.set_cookie("session", "")
bottle.redirect("/")
def send_stylesheet(filename):
return bottle.static_file(filename, root='.', mimetype='text/css')
def setup_routing(app):
app.route('/', 'GET', index)
app.route('/signup', 'GET', show_signup)
app.route('/signup', 'POST', process_signup)
app.route('/login', 'GET', show_login)
app.route('/login', 'POST', process_login)
app.route('/logout', 'GET', process_logout)
app.route('/css/<filename:re:.*\.css>', 'GET', send_stylesheet)
# validates that the user information is valid for new signup, return True of False
# and fills in the error string if there is an issue
def validate_signup(username, password, verify, email, errors):
USER_RE = re.compile(r"^[a-zA-Z0-9_-]{3,20}$")
PASS_RE = re.compile(r"^.{3,20}$")
EMAIL_RE = re.compile(r"^[\S]+@[\S]+\.[\S]+$")
errors['username_error'] = ""
errors['password_error'] = ""
errors['verify_error'] = ""
errors['email_error'] = ""
if not USER_RE.match(username):
errors['username_error'] = "invalid username. try just letters and numbers"
return False
if not PASS_RE.match(password):
errors['password_error'] = "invalid password."
return False
if password != verify:
errors['verify_error'] = "password must match"
return False
if email != "":
if not EMAIL_RE.match(email):
errors['email_error'] = "invalid email address"
return False
return True
setup_routing(app)
config = ConfigParser.ConfigParser()
config.read('kontor.properties')
server = config.get('host', 'server')
port = config.get('host', 'port')
db_server = config.get('database', 'server')
db_port = config.get('database', 'port')
db_admin = config.get('database', 'adminDB')
db_user = config.get('database', 'user')
db_password = config.get('database', 'password')
connection_string = "mongodb://"
if db_admin:
connection_string += db_user
connection_string += ':'
connection_string += db_password
connection_string += '@'
connection_string += db_server
connection_string += '?/authsource='
connection_string += db_admin
else:
connection_string += db_server
connection = pymongo.MongoClient(connection_string)
database = connection.kontor
users = userDAO.UserDAO(database)
sessions = sessionDAO.SessionDAO(database)
office_plugin = homeoffice.Plugin(app, database, sessions)
comics_plugin = comics.Plugin(app, database, sessions)
library_plugin = library.Plugin(app, database, sessions)
medien_plugin = medien.Plugin(app, database, sessions)
tradingcards_plugin = tradingcards.Plugin(app, database, sessions)
bottle.run(app, host=server, port=port, debug=True, reloader=True)
+66
View File
@@ -0,0 +1,66 @@
# -*- coding:utf-8 -*-
import pymongo
import bookDAO
import bottle
import cgi
__author__ = 'tpeetz'
class Plugin:
def __init__(self, app, database, sessions):
self.app = app
self.db = database
self.sessions = sessions
self.books = bookDAO.BookDAO(database)
self.routing()
def routing(self):
self.app.route('/library', 'GET', self.book_list)
self.app.route('/library/book', 'GET', self.book_list)
self.app.route('/library/book/<id>', 'GET', self.book_details)
self.app.route('/library/book/create', 'GET', self.get_book_create)
self.app.route('/library/book/create', 'POST', self.post_create_book)
def book_list(self):
cookie = bottle.request.get_cookie("session")
username = self.sessions.get_username(cookie)
l = self.books.get_books()
return bottle.template('book_list', dict(books=l, username=username))
def book_details(self, id):
cookie = bottle.request.get_cookie("session")
username = self.sessions.get_username(cookie)
book = self.books.get_book(id)
errors = ""
if book == None:
errors = "Entry not found"
return bottle.template('book_template', dict(title=book['title'],
id=book['_id'],
current_order=book['current_order'],
completed=book['completed'],
errors="",
username=username))
def get_book_create(self):
cookie = bottle.rddequest.get_cookie("session")
username = self.sessions.get_username(cookie)
return bottle.template("book_template", dict(title="",
id='newentry',
current_order=False,
completed=False,
errors="",
username=username))
def post_create_book(self):
book_id = bottle.request.forms.get("id")
book_title = bottle.request.forms.get("title")
book_order = bottle.request.forms.get("current_order")
book_completed = bottle.request.forms.get("completed")
if book_id == "newentry":
self.books.insert_entry(book_title, None, book_order, book_completed)
else:
self.comics.update_entry(book_id, book_title, None, book_order, book_completed)
bottle.redirect("/comics/comic")
+56
View File
@@ -0,0 +1,56 @@
# -*- coding: utf-8 -*-
from bson.objectid import ObjectId
import sys
class BookDAO:
# constructor for the class
def __init__(self, database):
self.db = database
self.books = database.books
def get_books(self):
cursor = self.books.find()
l = []
for book in cursor:
l.append(
{'title':book['title'],
'_id':book['_id'],
'publisher':book['publisher'],
'isbn':book['isbn'],
'author':book['author']}
)
return l
def get_book(self, book_id):
book = self.books.find_one({"_id": ObjectId(book_id)})
return book
def insert_entry(self, book_title):
print "inserting book entry", book_title
book = {"title": book_title}
# now insert the book
try:
result = self.books.insert_one(book)
print "Matching book: ", result.matched_count
print "Modified book: ", result.modified_count
except:
print "Error inserting book"
print "Unexpected error:", sys.exc_info()
def update_entry(self, book_id, book_title):
print "updating book entry", book_title
filter_doc = {"_id": ObjectId(book_id)}
book = { "$set": {"name": book_title}}
# now insert the book
try:
result = self.books.update_one(filter_doc, book)
print "Modified book: ", result.modified_count
except:
print "Error inserting book"
print "Unexpected error:", sys.exc_info()
+25
View File
@@ -0,0 +1,25 @@
# -*- coding:utf-8 -*-
import pymongo
import bottle
import cgi
__author__ = 'tpeetz'
class Plugin:
def __init__(self, app, database, sessions):
self.app = app
self.db = database
self.sessions = sessions
self.routing()
def routing(self):
self.app.route('/medien', 'GET', self.media_index)
def media_index(self):
cookie = bottle.request.get_cookie("session")
username = self.sessions.get_username(cookie)
return bottle.template('media_index', dict(username=username))
+64
View File
@@ -0,0 +1,64 @@
# -*- coding: utf-8 -*-
import sys
import random
import string
# The session Data Access Object handles interactions with the sessions collection
class SessionDAO:
def __init__(self, database):
self.db = database
self.sessions = database.sessions
# will start a new session id by adding a new document to the sessions collection
# returns the sessionID or None
def start_session(self, username):
session_id = self.get_random_str(32)
session = {'username': username, '_id': session_id}
try:
self.sessions.insert_one(session)
except:
print "Unexpected error on start_session:", sys.exc_info()[0]
return None
return str(session['_id'])
# will send a new user session by deleting from sessions table
def end_session(self, session_id):
if session_id is None:
return
self.sessions.delete_one({'_id': session_id})
return
# if there is a valid session, it is returned
def get_session(self, session_id):
if session_id is None:
return None
session = self.sessions.find_one({'_id': session_id})
return session
# get the username of the current session, or None if the session is not valid
def get_username(self, session_id):
session = self.get_session(session_id)
if session is None:
return None
else:
return session['username']
def get_random_str(self, num_chars):
random_string = ""
for i in range(num_chars):
random_string = random_string + random.choice(string.ascii_letters)
return random_string
+11
View File
@@ -0,0 +1,11 @@
from setuptools import setup
setup(
name='kontor-bottle',
packages=['comics', 'homeoffice', 'library', 'medien'],
include_package_data=True,
install_requires=[
'bottle',
'pymongo'
],
)
+25
View File
@@ -0,0 +1,25 @@
# -*- coding:utf-8 -*-
import pymongo
import bottle
import cgi
__author__ = 'tpeetz'
class Plugin:
def __init__(self, app, database, sessions):
self.app = app
self.db = database
self.sessions = sessions
self.routing()
def routing(self):
self.app.route('/tradingcards', 'GET', self.tradingcards_index)
def tradingcards_index(self):
cookie = bottle.request.get_cookie("session")
username = self.sessions.get_username(cookie)
return bottle.template('tradingcards_index', dict(username=username))
+77
View File
@@ -0,0 +1,77 @@
# -*- coding: utf-8 -*-
import hmac
import random
import string
import hashlib
import pymongo
# The User Data Access Object handles all interactions with the User collection.
class UserDAO:
def __init__(self, db):
self.db = db
self.users = self.db.users
self.SECRET = 'verysecret'
# makes a little salt
def make_salt(self):
salt = ""
for i in range(5):
salt = salt + random.choice(string.ascii_letters)
return salt
# implement the function make_pw_hash(name, pw) that returns a hashed password
# of the format:
# HASH(pw + salt),salt
# use sha256
def make_pw_hash(self, pw,salt=None):
if salt == None:
salt = self.make_salt();
return hashlib.sha256(pw + salt).hexdigest()+","+ salt
# Validates a user login. Returns user record or None
def validate_login(self, username, password):
user = None
try:
user = self.users.find_one({'_id': username})
except:
print "Unable to query database for user"
if user is None:
print "User not in database"
return None
salt = user['password'].split(',')[1]
if user['password'] != self.make_pw_hash(password, salt):
print "user password is not a match"
return None
# Looks good
return user
# creates a new user in the users collection
def add_user(self, username, password, email):
password_hash = self.make_pw_hash(password)
user = {'_id': username, 'password': password_hash}
if email != "":
user['email'] = email
try:
self.users.insert_one(user)
except pymongo.errors.OperationFailure:
print "oops, mongo error"
return False
except pymongo.errors.DuplicateKeyError as e:
print "oops, username is already taken"
return False
return True
+39
View File
@@ -0,0 +1,39 @@
<!DOCTYPE html>
<html>
<head>
<title>Kontor</title>
<link rel="stylesheet" href="/css/kontor.css">
</head>
<body>
<header>Kontor</header>
<nav><ul>
<li><a href="/">Kontor</a></li>
<li><a href="/comics">Comics</a></li>
<ul>
<li><a href="/comics/artist">Artists</a></li>
<li><a href="/comics/publisher">Publishers</a></li>
</ul>
<li><a href="/library">B&uuml;cher</a></li>
<li><a href="/medien">Medien</a></li>
<li><a href="/tradingcards">Trading Cards</a></li>
</ul></nav>
<main role="main">
<details>
<ul>
%for artist in artists:
<li><a href="/comics/artist/{{artist['_id']}}">{{artist['name']}}</a></li>
%end
</ul>
</details>
</main>
<footer>
%if (username == None):
<a href="/login">Login</a>
%end
%if (username != None):
<a href="/logout">{{username}}</a>
%end
<p>Ingenieurb&uuml;ro Thomas Peetz</p>
</footer>
</body>
</html>
+43
View File
@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<head>
<title>Kontor</title>
<link rel="stylesheet" href="/css/kontor.css">
</head>
<body>
<header>Kontor</header>
<nav><ul>
<li><a href="/">Kontor</a></li>
<li><a href="/comics">Comics</a></li>
<ul>
<li><a href="/comics/artist">Artists</a></li>
<li><a href="/comics/publisher">Publishers</a></li>
</ul>
<li><a href="/library">B&uuml;cher</a></li>
<li><a href="/medien">Medien</a></li>
<li><a href="/tradingcards">Trading Cards</a></li>
</ul></nav>
<main role="main">
<details>
<form action="/comics/artist/create" method="POST">
{{errors}}
<h2>Title</h2>
<input type="hidden" name="id", value="{{id}}">
<input type="text" name="name" size="60" value="{{name}}"><br>
<p>
<input type="submit" value="Submit">
</form>
</details>
</main>
<footer>
%if (username == None):
<a href="/login">Login</a>
%end
%if (username != None):
<a href="/logout">{{username}}</a>
%end
<p>Ingenieurb&uuml;ro Thomas Peetz</p>
</footer>
</body>
</html>
+44
View File
@@ -0,0 +1,44 @@
<!DOCTYPE html>
<html>
<head>
<title>Kontor</title>
<link rel="stylesheet" href="/css/kontor.css">
</head>
<body>
<header>Kontor</header>
<nav><ul>
<li><a href="/">Kontor</a></li>
<li><a href="/comics">Comics</a></li>
<ul>
<li><a href="/comics/artist">Artists</a></li>
<li><a href="/comics/publisher">Publishers</a></li>
</ul>
<li><a href="/library">B&uuml;cher</a></li>
<li><a href="/medien">Medien</a></li>
<li><a href="/tradingcards">Trading Cards</a></li>
</ul></nav>
<main role="main">
<details>
<table border="1">
<tr><td>Title</td><td>Current Order</td><td>Completed</td></tr>
<tr>
%for book in books:
<td><a href="/library/book/{{book['_id']}}">{{book['title']}}</a></td>
<td>{{book['current_order']}}</td>
<td>{{book['completed']}}</td>
%end
</tr>
</table>
</details>
</main>
<footer>
%if (username == None):
<a href="/login">Login</a>
%end
%if (username != None):
<a href="/logout">{{username}}</a>
%end
<p>Ingenieurb&uuml;ro Thomas Peetz</p>
</footer>
</body>
</html>
+34
View File
@@ -0,0 +1,34 @@
<!DOCTYPE html>
<html>
<head>
<title>Kontor</title>
<link rel="stylesheet" href="/css/kontor.css">
</head>
<body>
<header>Kontor</header>
<nav><ul>
<li><a href="/">Kontor</a></li>
<li><a href="/comics">Comics</a></li>
<ul>
<li><a href="/comics/artist">Artists</a></li>
<li><a href="/comics/publisher">Publishers</a></li>
</ul>
<li><a href="/library">B&uuml;cher</a></li>
<li><a href="/medien">Medien</a></li>
<li><a href="/tradingcards">Trading Cards</a></li>
</ul></nav>
<main role="main">
<details>
</details>
</main>
<footer>
%if (username == None):
<a href="/login">Login</a>
%end
%if (username != None):
<a href="/logout">{{username}}</a>
%end
<p>Ingenieurb&uuml;ro Thomas Peetz</p>
</footer>
</body>
</html>
+44
View File
@@ -0,0 +1,44 @@
<!DOCTYPE html>
<html>
<head>
<title>Kontor</title>
<link rel="stylesheet" href="/css/kontor.css">
</head>
<body>
<header>Kontor</header>
<nav><ul>
<li><a href="/">Kontor</a></li>
<li><a href="/comics">Comics</a></li>
<ul>
<li><a href="/comics/artist">Artists</a></li>
<li><a href="/comics/publisher">Publishers</a></li>
</ul>
<li><a href="/library">B&uuml;cher</a></li>
<li><a href="/medien">Medien</a></li>
<li><a href="/tradingcards">Trading Cards</a></li>
</ul></nav>
<main role="main">
<details>
<table border="1">
<tr><td>Title</td><td>Current Order</td><td>Completed</td></tr>
<tr>
%for comic in comics:
<td><a href="/comics/comic/{{comic['_id']}}">{{comic['title']}}</a></td>
<td>{{comic['current_order']}}</td>
<td>{{comic['completed']}}</td>
%end
</tr>
</table>
</details>
</main>
<footer>
%if (username == None):
<a href="/login">Login</a>
%end
%if (username != None):
<a href="/logout">{{username}}</a>
%end
<p>Ingenieurb&uuml;ro Thomas Peetz</p>
</footer>
</body>
</html>
+51
View File
@@ -0,0 +1,51 @@
<!DOCTYPE html>
<html>
<head>
<title>Kontor</title>
<link rel="stylesheet" href="/css/kontor.css">
</head>
<body>
<header>Kontor</header>
<nav><ul>
<li><a href="/">Kontor</a></li>
<li><a href="/comics">Comics</a></li>
<ul>
<li><a href="/comics/artist">Artists</a></li>
<li><a href="/comics/publisher">Publishers</a></li>
</ul>
<li><a href="/library">B&uuml;cher</a></li>
<li><a href="/medien">Medien</a></li>
<li><a href="/tradingcards">Trading Cards</a></li>
</ul></nav>
<main role="main">
<details>
<form action="/comics/comic/create" method="POST">
{{errors}}
<h2>Title</h2>
<input type="hidden" name="id", value="{{id}}">
<input type="text" name="title" size="60" value="{{title}}"><br>
<p>
<label>
<input type="checkbox" name="current_order" size="60" value="{{current_order}}">
Current Order
</label>
<label>
<input type="checkbox" name="completed" size="60" value="{{completed}}">
Completed
</label>
<p>
<input type="submit" value="Submit">
</form>
</details>
</main>
<footer>
%if (username == None):
<a href="/login">Login</a>
%end
%if (username != None):
<a href="/logout">{{username}}</a>
%end
<p>Ingenieurb&uuml;ro Thomas Peetz</p>
</footer>
</body>
</html>
+28
View File
@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html>
<head>
<title>Kontor</title>
<link rel="stylesheet" href="css/kontor.css">
</head>
<body>
<header>Kontor</header>
<nav><ul>
<li><a href="/">Kontor</a></li>
<li><a href="/office">HomeOffice</a></li>
<li><a href="/comics">Comics</a></li>
<li><a href="/library">B&uuml;cher</a></li>
<li><a href="/medien">Medien</a></li>
<li><a href="/tradingcards">Trading Cards</a></li>
</ul></nav>
<main role="main">
<details>
</details>
</main>
%if (username == None):
<footer><a href="/login">Login</a><p>Ingenieurb&uuml;ro Thomas Peetz</p></footer>
%end
%if (username != None):
<footer><a href="/logout">{{username}}</a><p>Ingenieurb&uuml;ro Thomas Peetz</p></footer>
%end
</body>
</html>
+52
View File
@@ -0,0 +1,52 @@
<!DOCTYPE html>
<html>
<head>
<title>Kontor</title>
<link rel="stylesheet" href="/css/kontor.css">
</head>
<body>
<header>Kontor</header>
<nav><ul>
<li><a href="/">Kontor</a></li>
<li><a href="/comics">Comics</a></li>
<ul>
<li><a href="/comics/artist">Artists</a></li>
<li><a href="/comics/publisher">Publishers</a></li>
</ul>
<li><a href="/library">B&uuml;cher</a></li>
<li><a href="/medien">Medien</a></li>
<li><a href="/tradingcards">Trading Cards</a></li>
</ul></nav>
<main role="main">
<details>
<form method="POST">
<table>
<tr>
<td class="label">Username</td>
<td><input type="text" name="username" value="{{username}}"></td>
<td class="error"></td>
</tr>
<tr>
<td class="label">Password</td>
<td><input type="password" name="password" value=""></td>
<td class="error">{{login_error}}</td>
</tr>
</table>
<input type="submit" value="Submit">
</form>
</details>
</main>
<footer>
%if (username == None):
<a href="/login">Login</a>
%end
%if (username != None):
<a href="/logout">{{username}}</a>
%end
<p>Ingenieurb&uuml;ro Thomas Peetz</p>
</footer>
</body>
</html>
+32
View File
@@ -0,0 +1,32 @@
<!DOCTYPE html>
<html>
<head>
<title>Kontor</title>
<link rel="stylesheet" href="/css/kontor.css">
</head>
<body>
<header>Kontor</header>
<nav><ul>
<li><a href="/">Kontor</a></li>
<li><a href="/office">HomeOffice</a></li>
<li><a href="/comics">Comics</a></li>
<li><a href="/library">B&uuml;cher</a></li>
<li><a href="/medien">Medien</a></li>
<li><a href="/tradingcards">Trading Cards</a></li>
</ul></nav>
<main role="main">
<details>
<h2>Medien</h2>
</details>
</main>
<footer>
%if (username == None):
<a href="/login">Login</a>
%end
%if (username != None):
<a href="/logout">{{username}}</a>
%end
<p>Ingenieurb&uuml;ro Thomas Peetz</p>
</footer>
</body>
</html>
+35
View File
@@ -0,0 +1,35 @@
<!DOCTYPE html>
<html>
<head>
<title>Kontor</title>
<link rel="stylesheet" href="/css/kontor.css">
</head>
<body>
<header>Kontor</header>
<nav><ul>
<li><a href="/">Kontor</a></li>
<li><a href="/office">HomeOffice</a></li>
<ul>
<li><a href="/office/travel">Dienstreise</a></li>
</ul>
<li><a href="/comics">Comics</a></li>
<li><a href="/library">B&uuml;cher</a></li>
<li><a href="/medien">Medien</a></li>
<li><a href="/tradingcards">Trading Cards</a></li>
</ul></nav>
<main role="main">
<details>
<h2>HomeOffice</h2>
</details>
</main>
<footer>
%if (username == None):
<a href="/login">Login</a>
%end
%if (username != None):
<a href="/logout">{{username}}</a>
%end
<p>Ingenieurb&uuml;ro Thomas Peetz</p>
</footer>
</body>
</html>
+39
View File
@@ -0,0 +1,39 @@
<!DOCTYPE html>
<html>
<head>
<title>Kontor</title>
<link rel="stylesheet" href="/css/kontor.css">
</head>
<body>
<header>Kontor</header>
<nav><ul>
<li><a href="/">Kontor</a></li>
<li><a href="/comics">Comics</a></li>
<ul>
<li><a href="/comics/artist">Artists</a></li>
<li><a href="/comics/publisher">Publishers</a></li>
</ul>
<li><a href="/library">B&uuml;cher</a></li>
<li><a href="/medien">Medien</a></li>
<li><a href="/tradingcards">Trading Cards</a></li>
</ul></nav>
<main role="main">
<details>
<ul>
%for publisher in publishers:
<li><a href="/comics/publisher/{{publisher['_id']}}">{{publisher['name']}}</a></li>
%end
</ul>
</details>
</main>
<footer>
%if (username == None):
<a href="/login">Login</a>
%end
%if (username != None):
<a href="/logout">{{username}}</a>
%end
<p>Ingenieurb&uuml;ro Thomas Peetz</p>
</footer>
</body>
</html>
+42
View File
@@ -0,0 +1,42 @@
<!DOCTYPE html>
<html>
<head>
<title>Kontor</title>
<link rel="stylesheet" href="/css/kontor.css">
</head>
<body>
<header>Kontor</header>
<nav><ul>
<li><a href="/">Kontor</a></li>
<li><a href="/comics/comic">Comics</a></li>
<ul>
<li><a href="/comics/artist">Artists</a></li>
<li><a href="/comics/publisher">Publishers</a></li>
</ul>
<li><a href="/library">B&uuml;cher</a></li>
<li><a href="/medien">Medien</a></li>
<li><a href="/tradingcards">Trading Cards</a></li>
</ul></nav>
<main role="main">
<details>
<form action="/comics/publisher/create" method="POST">
{{errors}}
<h2>Title</h2>
<input type="hidden" name="id", value="{{id}}">
<input type="text" name="name" size="60" value="{{name}}"><br>
<p>
<input type="submit" value="Submit">
</form>
</details>
</main>
<footer>
%if (username == None):
<a href="/login">Login</a>
%end
%if (username != None):
<a href="/logout">{{username}}</a>
%end
<p>Ingenieurb&uuml;ro Thomas Peetz</p>
</footer>
</body>
</html>
+59
View File
@@ -0,0 +1,59 @@
<!DOCTYPE html>
<html>
<head>
<title>Kontor</title>
<link rel="stylesheet" href="/css/kontor.css">
</head>
<body>
<header>Kontor</header>
<nav><ul>
<li><a href="/">Kontor</a></li>
<li><a href="/comics">Comics</a></li>
<ul>
<li><a href="/comics/artist">Artists</a></li>
<li><a href="/comics/publisher">Publishers</a></li>
</ul>
<li><a href="/library">B&uuml;cher</a></li>
<li><a href="/medien">Medien</a></li>
<li><a href="/tradingcards">Trading Cards</a></li>
</ul></nav>
<main role="main">
<details>
<h2>Signup</h2>
<form method="post">
<table>
<tr><td class="label">Username</td>
<td><input type="text" name="username" value="{{username}}"></td>
<td class="error">{{username_error}}</td>
</tr>
<tr>
<td class="label">Password</td>
<td><input type="password" name="password" value=""></td>
<td class="error">{{password_error}}</td>
</tr>
<tr>
<td class="label">Verify Password</td>
<td><input type="password" name="verify" value=""></td>
<td class="error">{{verify_error}}</td>
</tr>
<tr>
<td class="label">Email (optional)</td>
<td><input type="text" name="email" value="{{email}}"></td>
<td class="error">{{email_error}}</td>
</tr>
</table>
<input type="submit">
</form>
</details>
</main>
<footer>
%if (username == None):
<a href="/login">Login</a>
%end
%if (username != None):
<a href="/logout">{{username}}</a>
%end
<p>Ingenieurb&uuml;ro Thomas Peetz</p>
</footer>
</body>
</html>
+40
View File
@@ -0,0 +1,40 @@
<!DOCTYPE html>
<html>
<head>
<title>Kontor</title>
<link rel="stylesheet" href="/css/kontor.css">
</head>
<body>
<header>Kontor</header>
<nav><ul>
<li><a href="/">Kontor</a></li>
<li><a href="/comics/comic">Comics</a></li>
<ul>
<li><a href="/comics/artist">Artists</a></li>
<li><a href="/comics/publisher">Publishers</a></li>
<li><a href="/comics/storyarc">StoryArcs</a></li>
</ul>
<li><a href="/library">B&uuml;cher</a></li>
<li><a href="/medien">Medien</a></li>
<li><a href="/tradingcards">Trading Cards</a></li>
</ul></nav>
<main role="main">
<details>
<ul>
%for storyarc in storyarcs:
<li><a href="/comics/storyarc/{{storyarc['_id']}}">{{storyarc['title']}}</a></li>
%end
</ul>
</details>
</main>
<footer>
%if (username == None):
<a href="/login">Login</a>
%end
%if (username != None):
<a href="/logout">{{username}}</a>
%end
<p>Ingenieurb&uuml;ro Thomas Peetz</p>
</footer>
</body>
</html>
+43
View File
@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<head>
<title>Kontor</title>
<link rel="stylesheet" href="/css/kontor.css">
</head>
<body>
<header>Kontor</header>
<nav><ul>
<li><a href="/">Kontor</a></li>
<li><a href="/comics">Comics</a></li>
<ul>
<li><a href="/comics/artist">Artists</a></li>
<li><a href="/comics/publisher">Publishers</a></li>
<li><a href="/comics/storyarc">StoryArcs</a></li>
</ul>
<li><a href="/library">B&uuml;cher</a></li>
<li><a href="/medien">Medien</a></li>
<li><a href="/tradingcards">Trading Cards</a></li>
</ul></nav>
<main role="main">
<details>
<form action="/comics/storyarc/create" method="POST">
{{errors}}
<h2>Title</h2>
<input type="hidden" name="id", value="{{id}}">
<input type="text" name="title" size="60" value="{{title}}"><br>
<p>
<input type="submit" value="Submit">
</form>
</details>
</main>
<footer>
%if (username == None):
<a href="/login">Login</a>
%end
%if (username != None):
<a href="/logout">{{username}}</a>
%end
<p>Ingenieurb&uuml;ro Thomas Peetz</p>
</footer>
</body>
</html>
+32
View File
@@ -0,0 +1,32 @@
<!DOCTYPE html>
<html>
<head>
<title>Kontor</title>
<link rel="stylesheet" href="/css/kontor.css">
</head>
<body>
<header>Kontor</header>
<nav><ul>
<li><a href="/">Kontor</a></li>
<li><a href="/office">HomeOffice</a></li>
<li><a href="/comics">Comics</a></li>
<li><a href="/library">B&uuml;cher</a></li>
<li><a href="/medien">Medien</a></li>
<li><a href="/tradingcards">Trading Cards</a></li>
</ul></nav>
<main role="main">
<details>
<h2>Trading Cards</h2>
</details>
</main>
<footer>
%if (username == None):
<a href="/login">Login</a>
%end
%if (username != None):
<a href="/logout">{{username}}</a>
%end
<p>Ingenieurb&uuml;ro Thomas Peetz</p>
</footer>
</body>
</html>
+16
View File
@@ -0,0 +1,16 @@
bin/
include/
lib/
lib64/
lib64
pip-selfcheck.json
<<<<<<< HEAD
<<<<<<< HEAD
*.pyc
kontor/db.sqlite3
.idea/
=======
>>>>>>> initial setup
=======
*.pyc
>>>>>>> ignore compiled scripts
+13
View File
@@ -0,0 +1,13 @@
node {
stage "Checkout"
checkout scm
stage "make migrations"
sh "python kontor/manage.py makemigrations"
stage "execute tests"
<<<<<<< HEAD
sh "python kontor/manage.py test comics library medien tradingcards homeoffice"
=======
sh "python kontor/manage.py test commics library medien tradingcards homeoffice"
>>>>>>> add tests
}
+2
View File
@@ -0,0 +1,2 @@
# Kontor Django
View File
+86
View File
@@ -0,0 +1,86 @@
from django.contrib import admin
<<<<<<< HEAD
<<<<<<< HEAD
=======
>>>>>>> add Comic models
from .models import Publisher
from .models import Artist
from .models import Issue
from .models import StoryArc
from .models import Comic
from .models import TradePaperback
from .models import Volume
<<<<<<< HEAD
# Register your models here.
class IssueInline(admin.StackedInline):
model = Issue
extra = 1
class IssueAdmin(admin.ModelAdmin):
fields = ['comic', 'number', 'is_read', 'in_stock']
class ComicAdmin(admin.ModelAdmin):
fields = ['title', 'publisher', 'writer', 'current_order', 'completed']
inlines = [IssueInline]
class ComicInline(admin.StackedInline):
model = Comic
extra = 1
class PublisherAdmin(admin.ModelAdmin):
inlines = [ComicInline]
admin.site.register(Publisher, PublisherAdmin)
admin.site.register(Artist)
admin.site.register(Issue, IssueAdmin)
admin.site.register(Volume)
admin.site.register(StoryArc)
admin.site.register(Comic, ComicAdmin)
admin.site.register(TradePaperback)
=======
# Register your models here.
>>>>>>> initial setup
=======
# Register your models here.
class IssueInline(admin.StackedInline):
model = Issue
extra = 1
class IssueAdmin(admin.ModelAdmin):
fields = ['comic', 'number', 'is_read', 'in_stock']
class ComicAdmin(admin.ModelAdmin):
fields = ['title', 'publisher', 'writer', 'artist', 'current_order', 'completed']
inlines = [IssueInline]
class ComicInline(admin.StackedInline):
model = Comic
extra = 1
class PublisherAdmin(admin.ModelAdmin):
inlines = [ComicInline]
admin.site.register(Publisher, PublisherAdmin)
admin.site.register(Artist)
admin.site.register(Issue, IssueAdmin)
admin.site.register(Volume)
admin.site.register(StoryArc)
admin.site.register(Comic, ComicAdmin)
admin.site.register(TradePaperback)
>>>>>>> add Comic models
+5
View File
@@ -0,0 +1,5 @@
from django.apps import AppConfig
class ComicsConfig(AppConfig):
name = 'comics'
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,105 @@
# -*- coding: utf-8 -*-
<<<<<<< HEAD
# Generated by Django 1.9.6 on 2016-06-13 15:33
=======
# Generated by Django 1.9.5 on 2016-04-10 20:23
>>>>>>> ignore compiled scripts
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Artist',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
],
),
migrations.CreateModel(
name='Comic',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=40)),
('current_order', models.BooleanField()),
('completed', models.BooleanField()),
<<<<<<< HEAD
('artist', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='artist', to='comics.Artist')),
=======
>>>>>>> ignore compiled scripts
],
),
migrations.CreateModel(
name='Issue',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('number', models.CharField(max_length=4)),
('is_read', models.BooleanField(default=False)),
('in_stock', models.BooleanField(default=False)),
('comic', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='comics.Comic')),
],
),
migrations.CreateModel(
name='Publisher',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
],
),
migrations.CreateModel(
name='StoryArc',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
('comic', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='comics.Comic')),
],
),
migrations.CreateModel(
name='TradePaperback',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=40)),
('issue_start', models.IntegerField()),
('issue_end', models.IntegerField()),
('comic', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='comics.Comic')),
],
),
migrations.CreateModel(
name='Volume',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=40)),
('comic', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='comics.Comic')),
],
),
migrations.AddField(
<<<<<<< HEAD
model_name='issue',
name='volume',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='comics.Volume'),
),
migrations.AddField(
=======
>>>>>>> ignore compiled scripts
model_name='comic',
name='publisher',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='comics.Publisher'),
),
<<<<<<< HEAD
migrations.AddField(
model_name='comic',
name='writer',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='writer', to='comics.Artist'),
),
=======
>>>>>>> ignore compiled scripts
]
@@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.6 on 2016-06-20 14:05
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('comics', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='comic',
name='artist',
field=models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, related_name='artist', to='comics.Artist'),
),
migrations.AlterField(
model_name='comic',
name='writer',
field=models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, related_name='writer', to='comics.Artist'),
),
]
@@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.6 on 2016-06-20 14:10
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('comics', '0002_auto_20160620_1405'),
]
operations = [
migrations.AlterField(
model_name='comic',
name='artist',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='artist', to='comics.Artist'),
),
migrations.AlterField(
model_name='comic',
name='writer',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='writer', to='comics.Artist'),
),
]
@@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.6 on 2016-06-22 11:22
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('comics', '0003_auto_20160620_1410'),
]
operations = [
migrations.AlterField(
model_name='issue',
name='volume',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='comics.Volume'),
),
]
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.6 on 2016-06-22 11:46
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('comics', '0004_auto_20160622_1122'),
]
operations = [
migrations.AlterField(
model_name='comic',
name='title',
field=models.CharField(max_length=60),
),
]
View File
+101
View File
@@ -0,0 +1,101 @@
from __future__ import unicode_literals
from django.db import models
# Create your models here.
<<<<<<< HEAD
<<<<<<< HEAD
=======
>>>>>>> add Comic models
class Publisher(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Artist(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Comic(models.Model):
<<<<<<< HEAD
title = models.CharField(max_length=60)
publisher = models.ForeignKey(Publisher)
current_order = models.BooleanField()
completed = models.BooleanField()
writer = models.ForeignKey(Artist, blank=True, null=True, related_name='writer')
artist = models.ForeignKey(Artist, blank=True, null=True, related_name='artist')
=======
title = models.CharField(max_length=40)
publisher = models.ForeignKey(Publisher)
current_order = models.BooleanField()
completed = models.BooleanField()
<<<<<<< HEAD
>>>>>>> add Comic models
=======
writer = models.ForeignKey(Artist, null=True, related_name='writer')
artist = models.ForeignKey(Artist, null=True, related_name='artist')
>>>>>>> backup
def __str__(self):
return self.title
class Volume(models.Model):
name = models.CharField(max_length=40)
comic = models.ForeignKey(Comic)
def __str__(self):
return self.comic.title + ' ' + self.name
class Issue(models.Model):
number = models.CharField(max_length=4)
is_read = models.BooleanField(default=False)
in_stock = models.BooleanField(default=False)
comic = models.ForeignKey(Comic, null=True)
<<<<<<< HEAD
<<<<<<< HEAD
volume = models.ForeignKey(Volume, blank=True, null=True)
=======
>>>>>>> add Comic models
=======
volume = models.ForeignKey(Volume, null=True)
>>>>>>> backup
def __str__(self):
return self.comic.title + ' #' + self.number
class StoryArc(models.Model):
name = models.CharField(max_length=100)
comic = models.ForeignKey(Comic, null=True)
def __str__(self):
return self.name
class TradePaperback(models.Model):
name = models.CharField(max_length=40)
comic = models.ForeignKey(Comic, null=True)
issue_start = models.IntegerField()
issue_end = models.IntegerField()
def __str__(self):
<<<<<<< HEAD
return self.comic.title + ' TP ' + self.name
<<<<<<< HEAD
=======
>>>>>>> initial setup
=======
>>>>>>> add Comic models
=======
return self.comic.title + ' TP ' + self.name
>>>>>>> backup
@@ -0,0 +1,6 @@
li a {
color: green;
}
td a {
color: green;
}
+28
View File
@@ -0,0 +1,28 @@
<<<<<<< HEAD
{% extends "kontor/base.html" %}
{% block title %}Comic Details{% endblock %}
{% block content %}
=======
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Comic Details</title>
</head>
<body>
>>>>>>> backup
<table>
<thead><td>Name</td><td>current Order</td><td>completed</td></thead>
<tr>
<td>{{ comic.title }}</td>
<td>{{ comic.current_order }}</td>
<td>{{ comic.completed }}</td>
</tr>
</table>
<<<<<<< HEAD
{% endblock %}
=======
</body>
</html>
>>>>>>> backup
+34
View File
@@ -0,0 +1,34 @@
<<<<<<< HEAD
{% extends "kontor/base.html" %}
{% block title %}Comic Overview{% endblock %}
{% block content %}
=======
{% load staticfiles %}
<link rel="stylesheet" type="text/css" href="{% static 'comics/style.css' %}" />
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Comic Overview</title>
</head>
<body>
>>>>>>> backup
<table>
<thead><td>Name</td><td>current Order</td><td>completed</td></thead>
{% for comic in comic_list %}
<tr>
<td><a href="{% url 'comics:detail' comic.id %}">{{ comic.title }}</a></td>
<td>{{ comic.current_order }}</td>
<td>{{ comic.completed }}</td>
</tr>
{% endfor %}
</table>
<<<<<<< HEAD
{% endblock %}
=======
</body>
</html>
>>>>>>> backup
+8
View File
@@ -0,0 +1,8 @@
from django.test import TestCase
# Create your tests here.
class ComicsViewsTestCase(TestCase):
def test_index(self):
resp = self.client.get('/comics/')
self.assertEqual(resp.status_code, 200)
+10
View File
@@ -0,0 +1,10 @@
from django.conf.urls import url
from . import views
app_name = 'comics'
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^(?P<pk>[0-9]+)/$', views.DetailView.as_view(), name='detail'),
]
+51
View File
@@ -0,0 +1,51 @@
<<<<<<< HEAD
from django.shortcuts import render
<<<<<<< HEAD
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.views import generic
from .models import Comic
# Create your views here.
class IndexView(generic.ListView):
template_name = 'comics/index.html'
context_object_name = 'comic_list'
def get_queryset(self):
"""Return the list of comics."""
return Comic.objects.all()
class DetailView(generic.DetailView):
model = Comic
template_name = 'comics/detail.html'
=======
=======
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.views import generic
>>>>>>> backup
from .models import Comic
# Create your views here.
<<<<<<< HEAD
>>>>>>> initial setup
=======
class IndexView(generic.ListView):
template_name = 'comics/index.html'
context_object_name = 'comic_list'
def get_queryset(self):
"""Return the list of comics."""
return Comic.objects.all()
class DetailView(generic.DetailView):
model = Comic
template_name = 'comics/detail.html'
>>>>>>> backup
View File
+3
View File
@@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.
+7
View File
@@ -0,0 +1,7 @@
from __future__ import unicode_literals
from django.apps import AppConfig
class HomeOfficeConfig(AppConfig):
name = 'homeoffice'
@@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.6 on 2016-06-20 16:58
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Expense',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
],
),
migrations.CreateModel(
name='Travel',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
],
),
]
View File
+10
View File
@@ -0,0 +1,10 @@
from __future__ import unicode_literals
from django.db import models
# Create your models here.
class Travel(models.Model):
pass
class Expense(models.Model):
pass
+2
View File
@@ -0,0 +1,2 @@
{% extends "kontor/base.html" %}
{% block title %}HomeOffice{% endblock %}
+3
View File
@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.
+8
View File
@@ -0,0 +1,8 @@
from django.conf.urls import url
from . import views
app_name = 'homeoffice'
urlpatterns = [
url(r'^$', views.index, name='index'),
]
+5
View File
@@ -0,0 +1,5 @@
from django.shortcuts import render
# Create your views here.
def index(request):
return render(request, 'homeoffice/index.html')
View File
+166
View File
@@ -0,0 +1,166 @@
"""
Django settings for kontor project.
<<<<<<< HEAD
<<<<<<< HEAD
Generated by 'django-admin startproject' using Django 1.9.6.
=======
Generated by 'django-admin startproject' using Django 1.9.5.
>>>>>>> initial setup
=======
>>>>>>> backup
For more information on this file, see
https://docs.djangoproject.com/en/1.6/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.6/ref/settings/
"""
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.6/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
<<<<<<< HEAD
<<<<<<< HEAD
SECRET_KEY = '8s-(!r%0yu)b(hdkes_v#g8kp7)0ma851j+&43cds#duk!s-_c'
=======
SECRET_KEY = 'c)&86w07k)091bgi1llt+aol5$8in8g=n#+iba4784cdw$#h)^'
>>>>>>> initial setup
=======
SECRET_KEY = 'i5qx(%mex)4ovh#y4m94b1(3xiw4%8+rx-!kpw9v4q*@0v6pd2'
>>>>>>> backup
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
TEMPLATE_DEBUG = True
ALLOWED_HOSTS = []
# Application definition
<<<<<<< HEAD
INSTALLED_APPS = [
<<<<<<< HEAD
<<<<<<< HEAD
'comics.apps.ComicsConfig',
'library.apps.LibraryConfig',
'tysc.apps.TyscConfig',
'tradingcards.apps.TradingCardsConfig',
'homeoffice.apps.HomeOfficeConfig',
'medien.apps.MedienConfig',
=======
>>>>>>> initial setup
=======
'comics.apps.ComicsConfig',
>>>>>>> add admin site for Comics
=======
INSTALLED_APPS = (
'comics.apps.ComicsConfig',
'tysc.apps.TyscConfig',
'library.apps.LibraryConfig',
>>>>>>> backup
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
)
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
)
ROOT_URLCONF = 'kontor.urls'
<<<<<<< HEAD
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
<<<<<<< HEAD
'DIRS': [os.path.join(BASE_DIR, 'templates')],
=======
'DIRS': [],
>>>>>>> initial setup
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
<<<<<<< HEAD
'django.template.context_processors.i18n',
'django.template.context_processors.media',
'django.template.context_processors.static',
'django.template.context_processors.tz',
=======
>>>>>>> initial setup
],
},
},
]
=======
>>>>>>> backup
WSGI_APPLICATION = 'kontor.wsgi.application'
# Database
# https://docs.djangoproject.com/en/1.6/ref/settings/#databases
DATABASES = {
'default': {
# 'ENGINE': 'django.db.backends.dummy',
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
#from mongoengine import connect
#connect('kontor')
#SESSION_ENGINE = 'mongoengine.django.sessions'
#SESSION_SERIALIZER = 'mongoengine.django.sessions.BSONSerializer'
# Internationalization
# https://docs.djangoproject.com/en/1.6/topics/i18n/
<<<<<<< HEAD
LANGUAGE_CODE = 'de-de'
=======
LANGUAGE_CODE = 'en-us'
>>>>>>> initial setup
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.6/howto/static-files/
STATIC_URL = '/static/'
<<<<<<< HEAD
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
]
=======
>>>>>>> initial setup
+61
View File
@@ -0,0 +1,61 @@
from django.conf.urls import patterns, include, url
<<<<<<< HEAD
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/1.9/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.conf.urls import url, include
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
"""
<<<<<<< HEAD
from django.conf.urls import url, include
from django.contrib import admin
from django.contrib.auth import views as auth_views
from . import views
admin.autodiscover()
urlpatterns = [
#url(r'^admin/', admin.site.urls),
url('^', include('django.contrib.auth.urls')),
url(r'^$', views.index, name='index'),
#url(r'^accounts/login/$', auth_views.login),
url(r'^accounts/login/$', auth_views.login, {'template_name': 'kontor/login.html'}),
url(r'^accounts/logout/$', auth_views.logout ),
url(r'^admin/', include(admin.site.urls)),
url(r'^comics/', include('comics.urls')),
url(r'^office/', include('homeoffice.urls')),
url(r'^tradingcards/', include('tradingcards.urls')),
url(r'^tysc/', include('tysc.urls')),
url(r'^library/', include('library.urls')),
url(r'^medien/', include('medien.urls')),
=======
from django.conf.urls import url
=======
>>>>>>> backup
from django.contrib import admin
admin.autodiscover()
<<<<<<< HEAD
urlpatterns = [
url(r'^admin/', admin.site.urls),
>>>>>>> initial setup
]
=======
urlpatterns = patterns('',
# Examples:
#url(r'^$', 'kontor.views.home', name='home'),
# url(r'^blog/', include('blog.urls')),
url(r'^comics/', include('comics.urls')),
url(r'^tysc/', include('tysc.urls')),
url(r'^admin/', include(admin.site.urls)),
)
>>>>>>> backup
+14
View File
@@ -0,0 +1,14 @@
from django.shortcuts import render
from django.http import HttpResponse
def index(request):
<<<<<<< HEAD
return render(request, 'kontor/index.html')
=======
return HttpResponse('You are in the Kontor application')
>>>>>>> backup
def home(request):
return HttpResponse('You are in the Kontor application')
+14
View File
@@ -0,0 +1,14 @@
"""
WSGI config for kontor project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/1.6/howto/deployment/wsgi/
"""
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "kontor.settings")
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
View File
+20
View File
@@ -0,0 +1,20 @@
from django.contrib import admin
from .models import Author
from .models import Book
<<<<<<< HEAD
from .models import Category
from .models import Edition
from .models import Publisher
=======
>>>>>>> backup
# Register your models here.
admin.site.register(Author)
admin.site.register(Book)
<<<<<<< HEAD
admin.site.register(Category)
admin.site.register(Edition)
admin.site.register(Publisher)
=======
>>>>>>> backup
+7
View File
@@ -0,0 +1,7 @@
from __future__ import unicode_literals
from django.apps import AppConfig
class LibraryConfig(AppConfig):
name = 'library'
+473
View File
@@ -0,0 +1,473 @@
- model: library.author
pk: 1
fields: {name: Terry Pratchett}
- model: library.author
pk: 2
fields: {name: Colin Forbes}
- model: library.author
pk: 3
fields: {name: Markus Heitz}
- model: library.author
pk: 4
fields: {name: Ralf Kuehnel}
- model: library.author
pk: 5
fields: {name: Richard Murch}
- model: library.author
pk: 6
fields: {name: Gunter Saake}
- model: library.author
pk: 7
fields: {name: Kai-Uwe Sattler}
- model: library.author
pk: 8
fields: {name: Joerg Thadeusz}
- model: library.author
pk: 9
fields: {name: Stephan Burgdorff}
- model: library.author
pk: 10
fields: {name: Christian Habbe}
- model: library.author
pk: 11
fields: {name: Stephen Kenson}
- model: library.author
pk: 12
fields: {name: Martin Fowler}
- model: library.author
pk: 13
fields: {name: Ramnivas Laddad}
- model: library.author
pk: 14
fields: {name: Thomas Gifford}
- model: library.author
pk: 15
fields: {name: Rene Goscinny}
- model: library.author
pk: 16
fields: {name: Albert Uderzo}
- model: library.author
pk: 17
fields: {name: Mel Odem}
- model: library.author
pk: 18
fields: {name: Harri Assmann}
- model: library.author
pk: 19
fields: {name: Harald Schmidt}
- model: library.author
pk: 20
fields: {name: Bruce Tate}
- model: library.author
pk: 21
fields: {name: Mike Clark}
- model: library.author
pk: 22
fields: {name: Bob Lee}
- model: library.author
pk: 23
fields: {name: Patrick Linskey}
- model: library.author
pk: 24
fields: {name: Jim Knipfel}
- model: library.author
pk: 25
fields: {name: Carl Sargent}
- model: library.author
pk: 26
fields: {name: Beate Sauer}
- model: library.author
pk: 27
fields: {name: Kent Beck}
- model: library.author
pk: 28
fields: {name: Erich Gamma}
- model: library.author
pk: 29
fields: {name: Ilko-Sascha Kowalczuk}
- model: library.author
pk: 30
fields: {name: Dalai Lama}
- model: library.author
pk: 31
fields: {name: Horst Saecker}
- model: library.author
pk: 32
fields: {name: Romain Sardou}
- model: library.author
pk: 33
fields: {name: Berthold Daum}
- model: library.author
pk: 34
fields: {name: Javier Sierra}
- model: library.author
pk: 35
fields: {name: Dieter Hesselberger}
- model: library.author
pk: 36
fields: {name: Anette Baecker}
- model: library.author
pk: 37
fields: {name: Paul Baecker}
- model: library.author
pk: 38
fields: {name: Lisa Smedmann}
- model: library.author
pk: 39
fields: {name: Michael Cordy}
- model: library.author
pk: 40
fields: {name: Stephen Fry}
- model: library.author
pk: 41
fields: {name: Jonathan Bond}
- model: library.author
pk: 42
fields: {name: Vince Flynn}
- model: library.author
pk: 43
fields: {name: Eric-Emmanuel Schmitt}
- model: library.author
pk: 44
fields: {name: Jak Koke}
- model: library.author
pk: 45
fields: {name: Nigel Findley}
- model: library.author
pk: 46
fields: {name: Edgar Noske}
- model: library.author
pk: 47
fields: {name: Hannes Wertheim}
- model: library.author
pk: 48
fields: {name: Frank Schaetzing}
- model: library.author
pk: 49
fields: {name: Frank Pilz}
- model: library.author
pk: 50
fields: {name: Frederick Forsyth}
- model: library.author
pk: 51
fields: {name: Chris Kubasik}
- model: library.author
pk: 52
fields: {name: Jordan K. Weisman}
- model: library.author
pk: 53
fields: {name: Hans Georg Lehmann}
- model: library.author
pk: 54
fields: {name: Nyx Smith}
- model: library.author
pk: 55
fields: {name: Ferdinand Seibt}
- model: library.author
pk: 56
fields: {name: Christopher Moore}
- model: library.author
pk: 57
fields: {name: Jens Gieseke}
- model: library.author
pk: 58
fields: {name: Bernd Lindner}
- model: library.author
pk: 59
fields: {name: Horst Poetzsch}
- model: library.author
pk: 60
fields: {name: Caroline Spector}
- model: library.author
pk: 61
fields: {name: Peter Godman}
- model: library.author
pk: 62
fields: {name: Hans Joachim Alpers}
- model: library.author
pk: 63
fields: {name: Bernhard Schlink}
- model: library.author
pk: 64
fields: {name: Rebecca Gable}
- model: library.author
pk: 65
fields: {name: Douglas Adams}
- model: library.author
pk: 66
fields: {name: Susan Cooper}
- model: library.author
pk: 67
fields: {name: Donna W. Cross}
- model: library.author
pk: 68
fields: {name: Peter Prange}
- model: library.author
pk: 69
fields: {name: Tanja Kinkel}
- model: library.author
pk: 70
fields: {name: Ken Follett}
- model: library.author
pk: 71
fields: {name: Minette Walters}
- model: library.author
pk: 72
fields: {name: Peter Tremayne}
- model: library.author
pk: 73
fields: {name: Marion Zimmer Bradley}
- model: library.author
pk: 74
fields: {name: Wolfgang Hohlbein}
- model: library.author
pk: 75
fields: {name: Friedrich Wilhelm Graf}
- model: library.author
pk: 76
fields: {name: Nyx Smith}
- model: library.author
pk: 78
fields: {name: Ferdinand Seibt}
- model: library.author
pk: 79
fields: {name: Christopher Moore}
- model: library.author
pk: 80
fields: {name: Jens Gieseke}
- model: library.author
pk: 81
fields: {name: Bernd Lindner}
- model: library.author
pk: 82
fields: {name: Horst Poetzsch}
- model: library.author
pk: 84
fields: {name: Caroline Spector}
- model: library.author
pk: 85
fields: {name: Peter Godman}
- model: library.author
pk: 86
fields: {name: Hans Joachim Alpers}
- model: library.author
pk: 87
fields: {name: Bernhard Schlink}
- model: library.author
pk: 89
fields: {name: Rebecca Gable}
- model: library.author
pk: 90
fields: {name: Douglas Adams}
- model: library.author
pk: 91
fields: {name: Susan Cooper}
- model: library.author
pk: 93
fields: {name: Donna W. Cross}
- model: library.author
pk: 94
fields: {name: Peter Prange}
- model: library.author
pk: 95
fields: {name: Tanja Kinkel}
- model: library.author
pk: 96
fields: {name: Ken Follett}
- model: library.author
pk: 97
fields: {name: Minette Walters}
- model: library.author
pk: 99
fields: {name: Peter Tremayne}
- model: library.author
pk: 101
fields: {name: Marion Zimmer Bradley}
- model: library.author
pk: 102
fields: {name: Wolfgang Hohlbein}
- model: library.author
pk: 103
fields: {name: Friedrich Wilhelm Graf}
- model: library.author
pk: 104
fields: {name: Terry Pratchett}
- model: library.author
pk: 105
fields: {name: Daniel Suarez}
- model: library.category
pk: 1
fields: {name: Science Fiction}
- model: library.category
pk: 2
fields: {name: Roman}
- model: library.category
pk: 3
fields: {name: Reference}
- model: library.category
pk: 4
fields: {name: Fantasy}
- model: library.category
pk: 5
fields: {name: Comics}
- model: library.category
pk: 6
fields: {name: Satire}
- model: library.category
pk: 7
fields: {name: Thriller}
- model: library.edition
pk: 1
fields: {name: Paperback}
- model: library.edition
pk: 2
fields: {name: Hardcover}
- model: library.edition
pk: 3
fields: {name: Softcover}
- model: library.publisher
pk: 1
fields: {name: Addison-Wesley Verlag}
- model: library.publisher
pk: 2
fields: {name: O'Reilly Media}
- model: library.publisher
pk: 3
fields: {name: O'Reilly & Associates}
- model: library.publisher
pk: 4
fields: {name: Klett-Cotta}
- model: library.publisher
pk: 5
fields: {name: Diogenes}
- model: library.publisher
pk: 6
fields: {name: Jaron Verlag}
- model: library.publisher
pk: 7
fields: {name: Merkur Verlag Rinteln}
- model: library.publisher
pk: 8
fields: {name: Ehapa Verlag}
- model: library.publisher
pk: 9
fields: {name: Markt+Technik Verlag}
- model: library.publisher
pk: 10
fields: {name: Kiepenheuer & Witsch}
- model: library.publisher
pk: 11
fields: {name: Goldmann Verlag}
- model: library.publisher
pk: 12
fields: {name: Sams Publishing}
- model: library.publisher
pk: 13
fields: {name: Wilhelm Heyne Verlag}
- model: library.publisher
pk: 14
fields: {name: Amman Verlag & Co.}
- model: library.publisher
pk: 15
fields: {name: Fischer Verlag}
- model: library.publisher
pk: 16
fields: {name: BestBook}
- model: library.publisher
pk: 17
fields: {name: List Verlag}
- model: library.publisher
pk: 18
fields: {name: dpunkt.verlag GmbH}
- model: library.publisher
pk: 19
fields: {name: Ullstein Verlag}
- model: library.publisher
pk: 20
fields: {name: Piper Verlag}
- model: library.publisher
pk: 21
fields: {name: Knaur Verlag}
- model: library.publisher
pk: 22
fields: {name: Heyne Fantasy}
- model: library.publisher
pk: 23
fields: {name: Manning Publications Co.}
- model: library.publisher
pk: 24
fields: {name: ADAC Verlag}
- model: library.publisher
pk: 25
fields: {name: dpunkt-Verlag}
- model: library.publisher
pk: 26
fields: {name: Verlag Kiepenheuer & Witsch}
- model: library.publisher
pk: 27
fields: {name: Hanser Wirtschaft}
- model: library.publisher
pk: 28
fields: {name: Droemersche Verlagsanstalt}
- model: library.publisher
pk: 29
fields: {name: Fischer Buecherei GmbH}
- model: library.publisher
pk: 30
fields: {name: rororo Verlag}
- model: library.publisher
pk: 31
fields: {name: Hoffmann und Campe}
- model: library.publisher
pk: 32
fields: {name: Heyne Verlag}
- model: library.publisher
pk: 33
fields: {name: dpunkt.verlag}
- model: library.publisher
pk: 34
fields: {name: Dorling Kindersley}
- model: library.publisher
pk: 35
fields: {name: Ammann Verlag}
- model: library.publisher
pk: 36
fields: {name: Addison-Wesley}
- model: library.publisher
pk: 37
fields: {name: Ueberreuter}
- model: library.publisher
pk: 38
fields: {name: Bertelsmann Club}
- model: library.publisher
pk: 39
fields: {name: Harriet Eder Verlag}
- model: library.publisher
pk: 40
fields: {name: Marix Verlag}
- model: library.publisher
pk: 41
fields: {name: Aufbau Taschenbuch Verlag}
- model: library.publisher
pk: 42
fields: {name: Rowohlt Taschenbuch Verlag}
- model: library.book
pk: 1
fields:
title: 2XS
publisher: null
isbn: ''
edition: 1
pages: null
category: 1
authors: [58]
- model: library.book
pk: 2
fields:
title: Daemon
publisher: 42
isbn: 978 3 499 25643 1
edition: 1
pages: 639
category: 7
authors: [105]
@@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
<<<<<<< HEAD
# Generated by Django 1.9.6 on 2016-05-31 08:57
=======
# Generated by Django 1.9.2 on 2016-02-16 19:01
>>>>>>> backup
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Author',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=40)),
],
),
migrations.CreateModel(
name='Book',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=40)),
],
),
]
@@ -0,0 +1,67 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.6 on 2016-06-24 12:30
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('library', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='Category',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=40)),
],
),
migrations.CreateModel(
name='Edition',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=40)),
],
),
migrations.CreateModel(
name='Publisher',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=40)),
],
),
migrations.AddField(
model_name='book',
name='authors',
field=models.ManyToManyField(blank=True, to='library.Author'),
),
migrations.AddField(
model_name='book',
name='isbn',
field=models.CharField(max_length=20, null=True),
),
migrations.AddField(
model_name='book',
name='pages',
field=models.IntegerField(null=True),
),
migrations.AddField(
model_name='book',
name='category',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='library.Category'),
),
migrations.AddField(
model_name='book',
name='edition',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='library.Edition'),
),
migrations.AddField(
model_name='book',
name='publisher',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='library.Publisher'),
),
]
@@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.6 on 2016-06-24 12:40
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('library', '0002_auto_20160624_1230'),
]
operations = [
migrations.AlterField(
model_name='book',
name='isbn',
field=models.CharField(blank=True, max_length=20, null=True),
),
migrations.AlterField(
model_name='book',
name='pages',
field=models.IntegerField(blank=True, null=True),
),
]
+51
View File
@@ -0,0 +1,51 @@
from __future__ import unicode_literals
from django.db import models
# Create your models here.
class Author(models.Model):
name = models.CharField(max_length=40)
def __str__(self):
return self.name
<<<<<<< HEAD
class Category(models.Model):
name = models.CharField(max_length=40)
def __str__(self):
return self.name
class Edition(models.Model):
name = models.CharField(max_length=40)
def __str__(self):
return self.name
class Publisher(models.Model):
name = models.CharField(max_length=40)
def __str__(self):
return self.name
class Book(models.Model):
title = models.CharField(max_length=40)
authors = models.ManyToManyField(Author, blank=True)
publisher = models.ForeignKey(Publisher, null=True, blank=True)
isbn = models.CharField(max_length=20, null=True, blank=True)
edition = models.ForeignKey(Edition, null=True, blank=True)
pages = models.IntegerField(null=True, blank=True)
category = models.ForeignKey(Category, null=True, blank=True)
=======
class Book(models.Model):
title = models.CharField(max_length=40)
>>>>>>> backup
def __str__(self):
return self.title
+12
View File
@@ -0,0 +1,12 @@
{% extends "base.html" %}
{% block title %}HomeOffice{% endblock %}
{% block content %}
<table>
<thead><td>Name</td></thead>
{% for author in author_list %}
<tr>
<td><a href="{% url 'autor:detail' author.id %}">{{ autor.name }}</a></td>
</tr>
{% endfor %}
</table>
{% endblock %}
+2
View File
@@ -0,0 +1,2 @@
{% extends "kontor/base.html" %}
{% block title %}B&uuml;cher{% endblock %}
+3
View File
@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.
+9
View File
@@ -0,0 +1,9 @@
from django.conf.urls import url
from . import views
app_name = 'library'
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^author/$', views.AuthorIndexView.as_view(), name='author_list'),
]
+46
View File
@@ -0,0 +1,46 @@
from django.shortcuts import render
<<<<<<< HEAD
from django.http import HttpResponse
from django.views import generic
from django.contrib.auth.decorators import login_required
=======
from django.views import generic
>>>>>>> backup
from .models import Author
from .models import Book
# Create your views here.
<<<<<<< HEAD
@login_required
def index(request):
return render(request, 'library/index.html')
=======
>>>>>>> backup
class AuthorIndexView(generic.ListView):
template_name = 'library/authorindex.html'
context_object_name = 'author_list'
def get_queryset(self):
"""Return the list of authors."""
return Author.objects.all()
class AuthorDetailView(generic.DetailView):
model = Author
template_name = 'library/authordetail.html'
class BookIndexView(generic.ListView):
template_name = 'library/bookindex.html'
context_object_name = 'book_list'
def get_queryset(self):
"""Return the list of books."""
return Book.objects.all()
class BookDetailView(generic.DetailView):
model = Book
template_name = 'library/bookdetail.html'
+10
View File
@@ -0,0 +1,10 @@
#!/usr/bin/env python
import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "kontor.settings")
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)
View File
+3
View File
@@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.
+7
View File
@@ -0,0 +1,7 @@
from __future__ import unicode_literals
from django.apps import AppConfig
class MedienConfig(AppConfig):
name = 'medien'
+2
View File
@@ -0,0 +1,2 @@
{% extends "kontor/base.html" %}
{% block title %}Medien{% endblock %}
+8
View File
@@ -0,0 +1,8 @@
from django.conf.urls import url
from . import views
app_name = 'medien'
urlpatterns = [
url(r'^$', views.index, name='index'),
]
+5
View File
@@ -0,0 +1,5 @@
from django.shortcuts import render
# Create your views here.
def index(request):
return render(request, 'medien/index.html')
+109
View File
@@ -0,0 +1,109 @@
body {
font-family: sans-serif;
color: #333333;
padding: 3em 0 4em;
}
body,
.wrapper {
margin: 10px auto;
/*max-width: 60em;*/
}
header, main, section, footer {
border-radius: 0px 0.5em 0.5em;
border: 1px solid;
padding: 10px;
margin: 10px;
}
header {
position:fixed;
top:0px;
left:0px;
right:0px;
text-align:center;
padding: 10px;
background: lightgrey;
/*border-bottom: 1px solid #d5d5d5;*/
}
nav {
/*position: fixed;*/
/*padding-top: 10em; */
border-radius: 0px 0.5em 0.5em;
border: 1px solid;
padding: 0;
margin: 10px;
font-size: 0.91em;
float: left;
width: 15em;
background: lightskyblue;
border-color: skyblue;
}
nav ul {
padding: 0;
}
nav li {
list-style: none;
margin: 0.4em;
padding: 0;
}
nav ul ul {
margin: 0 0 0 2em;
padding: 0;
border: none;
}
nav ul ul li {
margin: 0.3em 0;
}
nav a {
display: block;
padding: 0.4em;
text-decoration: none;
font-weight: bold;
border: 1px solid blue;
border-radius: 10px;
box-shadow: 0px 5px 10px white inset;
background-color: skyblue;
color: #333;
}
nav a:focus,
nav a:hover {
color: royalblue;
background-color: gold;
}
main {
display: block;
background: lightblue;
border-color: #8a9da8;
margin-left: 15em;
min-width: 16em; /* Mindestbreite (der Überschrift) verhindert Anzeigefehler in modernen Browsern */
}
footer {
position:fixed;
padding: 10px;
margin-top: 10px;
bottom:0;
left: 0;
right:0;
background: lightgrey;
border-color: grey;
}
footer p {
float:right;
margin: 0;
}
+9
View File
@@ -0,0 +1,9 @@
{% extends "admin/base.html" %}
{% block title %}{{ title }} | {{ site_title|default:_('Django site admin') }}{% endblock %}
{% block branding %}
<h1 id="site-name"><a href="{% url 'admin:index' %}">Kontor administration</a></h1>
{% endblock %}
{% block nav-global %}{% endblock %}
+32
View File
@@ -0,0 +1,32 @@
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}Kontor{% endblock %}</title>
{% load staticfiles %}
<link rel="stylesheet" type="text/css" href="{% static 'kontor.css' %}" />
</head>
<body>
<header>Kontor</header>
{% block navigation %}
<nav><ul>
<li><a href="/">Kontor</a></li>
<li><a href="/office">HomeOffice</a></li>
<li><a href="/comics">Comics</a></li>
<li><a href="/library">B&uuml;cher</a></li>
<li><a href="/medien">Medien</a></li>
<li><a href="/tradingcards">Trading Cards</a></li>
<li><a href="/tysc">TradeYourSportsCards</a></li>
</ul></nav>
{% endblock %}
<main role="main">
<details>
{% block content %}{% endblock %}
</details>
</main>
{% if user.is_authenticated %}
<footer><a href="/accounts/logout">{{ user }}</a><p>Ingenieurb&uuml;ro Thomas Peetz</p></footer>
{% else %}
<footer><a href="/accounts/login">Login</a><p>Ingenieurb&uuml;ro Thomas Peetz</p></footer>
{% endif %}
</body>
</html>
+1
View File
@@ -0,0 +1 @@
{% extends "kontor/base.html" %}
+33
View File
@@ -0,0 +1,33 @@
{% extends "kontor/base.html" %}
{% block content %}
{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}
{% if next %}
{% if user.is_authenticated %}
<p>Your account doesn't have access to this page. To proceed,
please login with an account that has access.</p>
{% else %}
<p>Please login to see this page.</p>
{% endif %}
{% endif %}
<form method="post" action="{% url 'login' %}">
{% csrf_token %}
<table>
<tr>
<td>{{ form.username.label_tag }}</td>
<td>{{ form.username }}</td>
</tr>
<tr>
<td>{{ form.password.label_tag }}</td>
<td>{{ form.password }}</td>
</tr>
</table>
<input type="submit" value="login" />
<input type="hidden" name="next" value="{{ next }}" />
</form>
{% endblock %}
View File
+3
View File
@@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.
+7
View File
@@ -0,0 +1,7 @@
from __future__ import unicode_literals
from django.apps import AppConfig
class TradingCardsConfig(AppConfig):
name = 'tradingcards'
View File

Some files were not shown because too many files have changed in this diff Show More