From dc1e3ce99f1807573f9e8dc4c3c70e97c620b179 Mon Sep 17 00:00:00 2001 From: crunk Date: Mon, 5 Apr 2021 21:42:43 +0200 Subject: [PATCH] csv writer! you can add books now --- library/csvparser/csvparser.py | 51 ++++++++++++++++++++++++++++++- library/csvparser/varlib.csv | 5 ++-- library/page.py | 16 ++++++++-- library/static/css/style.css | 4 +++ library/templates/upload.html | 34 ++++++++++++++++----- library/uploadform.py | 55 +++++++++++++++++++++++++++------- 6 files changed, 142 insertions(+), 23 deletions(-) diff --git a/library/csvparser/csvparser.py b/library/csvparser/csvparser.py index e5dc9d9..a776645 100644 --- a/library/csvparser/csvparser.py +++ b/library/csvparser/csvparser.py @@ -6,6 +6,21 @@ import os script_dir = os.path.dirname(__file__) image_dir = os.path.abspath(os.path.join(script_dir, "../static/images")) +fieldnames = [ + 'Id', + 'Publication', + 'Author', + 'Year', + 'Custodian', + 'Fields', + 'Type', + 'Publishers', + 'License', + 'LicenseShort', + 'Highlights', + 'Comments', + 'Currently borrowed by', +] def parsecsv(): @@ -139,4 +154,38 @@ def getfullpublication(pubid): return pubinfo -# print(getlicenses()) +def generatenewpublicationid(): + libcsv = open(os.path.join(script_dir, "varlib.csv"), "r") + allidsincsv = [] + with libcsv: + csv_as_dict = csv.DictReader(libcsv) + for row in csv_as_dict: + allidsincsv.append(int(row["Id"])) + return str(max(allidsincsv) + 1) + + +def writepublication(uploadform): + id = generatenewpublicationid() + with open( + os.path.join(script_dir, "varlib.csv"), + 'a', + newline='') as csvfile: + writer = csv.DictWriter(csvfile, fieldnames=fieldnames) + writer.writerow( + { + "Id": id, + "Publication": uploadform.uploadpublication.data, + "Author": uploadform.author.data, + "Year": uploadform.year.data, + "Custodian": uploadform.custodian.data, + "Fields": uploadform.fields.data, + "Type": uploadform.type.data, + "Publishers": uploadform.publishers.data, + "License": uploadform.license.data, + "LicenseShort": uploadform.licenseshort.data, + "Highlights": uploadform.highlights.data, + "Comments": uploadform.comments.data, + "Currently borrowed by": uploadform.borrowed.data, + }) + print("succesfully written book to csv") + return id diff --git a/library/csvparser/varlib.csv b/library/csvparser/varlib.csv index c886c54..1a154c6 100644 --- a/library/csvparser/varlib.csv +++ b/library/csvparser/varlib.csv @@ -13,8 +13,6 @@ Id,Publication,Author,Year,Custodian,Fields,Type,Publishers,License,LicenseShort 12,Abolish restaurants,Prole.info,2010,Varia,"Labour, Food industry",Paperback,Pm Press,Copyright 2010,Copyright,Drawing on a range of anti-capitalist ideas as well as a heaping plate of personal experience,, 13,"Elk Woord Een Vonk: Verboden Teksten, verwerpelijke vervolging: de zaak Joke Kaviaar",Steungroep 13 September,2014,Varia (or Luke?),"Joke Kaviaar, Immigration, Activism, Forbidden Texts, Incarceration",Softcover,Self-published,Copyleft,Copyleft,,https://13-september.nl, 14,A NO BORDERS manifesto,Ill Will Editions,2015,Varia,Migrant justice,Zine,Self-published,No license mentioned,No license mentioned,,, -15,Short Circuit: Towards an Arnarchist to Gentrification,,,Varia,"Gentrification, Anarchism",Zine,Self-published,No license mentioned,No license mentioned,"Anarchists understandably feel an intrinsic and visceral opposition to gentrification -",, 16,Futur Musique,De fanfare voor vooruit strevende volksmuziek,2018,Varia,"Musical Instruments, DIY",Zine,Self-published,No license mentioned,No license mentioned,Copied instructions on building one's own musical instruments,, 17,Franchir le cap,Quentin Juhel,2019,Varia,Convivial computation,Zine,Self-publsihed,Creative commons CC-BY-SA,Creative commons,,, 18,Consensus: Decision Making,Seeds For Change UK,2010,Varia,"Decision making, Consensus",Zine,Self-published,No license mentioned,No license mentioned,Short guide ,, @@ -48,8 +46,9 @@ Id,Publication,Author,Year,Custodian,Fields,Type,Publishers,License,LicenseShort 54,Xavan et Jaluka - The Death of the Authors 1946,Peter Westenberg,2018,Varia,Public domain,Zine,Constant Verlag,Copyleft,Copyleft,,, 55,Spreekt U Sint-Gillis? Parlez-vous Saint-Gillois?,,,Varia,"Bruxelles, Language, Sint-Gillis",Softcover,Constant Verlag,Copyleft,Copyleft,,, 56,Mondothèque: a radiated book,"André Castro , Sînziana Păltineanu , Dennis Pohl , Dick Reckard , Natacha Roussel , Femke Snelting , Alexia de Visscher",2016,Varia,"Archive, Otlet, Library science, Mondaneum, Google, Mons",Softcover,Constant,Copyleft,Copyleft,,, - ,"The Death of the Authors: 'James Joyce, Rabindranath Tagore & Their Return to Life in Four Seasons",A Constant Remix,2013,Varia,"James Joyce, Ulysses",Softcover,Constant,Public domain,Public domain,,'generated from Public domain sources, +57,"The Death of the Authors: 'James Joyce, Rabindranath Tagore & Their Return to Life in Four Seasons",A Constant Remix,2013,Varia,"James Joyce, Ulysses",Softcover,Constant,Public domain,Public domain,,'generated from Public domain sources, 58,Verbindingen/Jonctions 10 : Tracks in electr(on)ic fields,Constant,2009,Varia,"Art, activism, technological culture",Softcover,Constant,Copyleft,Copyleft,,, 59,Conversations,Constant,2014,Varia,"Software studies, Libre graphics",Softcover,Constant Verlag,Copyleft,Copyleft,,, 60,Networks of one's own #1: Etherbox,"Michael Murtaugh, An Mertens, Roel Roscam Abbing, Femke Snelting",2018,Varia,"Networks, Digital Infrastructures, DIY, DIWO, Executable publication, Experimental Publishing, wireless",Paperback,Constant Verlag,Copyleft,Copyleft,,, 61,Mots de la cage aux ours - woorden uit de berenkuil,Constant,2012,Varia,"words, language, Bruxelles",Softcover,Constant,Copyleft,Copyleft,,, +62,Snake rituals and switching circuits,Florian Cramer,2009,Danny,"mass communication, personal communication, new media",paperback,Piet Zwart Institute,Creative Commons Attribution-Share Alike 3.0,Creative Commons,The function of a medium is ultimately decided by its users and not by its creators,, diff --git a/library/page.py b/library/page.py index eb2b3f8..72921ae 100644 --- a/library/page.py +++ b/library/page.py @@ -5,7 +5,11 @@ import flask from requests import get from icalendar import Calendar import datetime -from flask import render_template +from flask import ( + render_template, + redirect, + request, +) from rnrfeed.rnrfeeder import getevents, getlatestevent from uploadform import PublicationForm from csvparser.csvparser import ( @@ -14,6 +18,7 @@ from csvparser.csvparser import ( gettypes, getyears, getfullpublication, + writepublication, ) from flask_wtf.csrf import CSRFProtect @@ -41,9 +46,16 @@ def index(): return template -@APP.route("/upload") +@APP.route("/upload", methods=["GET", "POST"]) def upload(): uploadform = PublicationForm() + if request.method == 'POST': + if uploadform.validate_on_submit(): + id = writepublication(uploadform) + return redirect(str(id), code=303) + else: + return render_template("upload.html", uploadform=uploadform) + print("test") return render_template("upload.html", uploadform=uploadform) diff --git a/library/static/css/style.css b/library/static/css/style.css index 57b36df..a476ddb 100644 --- a/library/static/css/style.css +++ b/library/static/css/style.css @@ -135,3 +135,7 @@ td { width: 100%; height: 100%; } + +.error{ + color: #ff1111; +} diff --git a/library/templates/upload.html b/library/templates/upload.html index 8bc8c40..bbf2487 100644 --- a/library/templates/upload.html +++ b/library/templates/upload.html @@ -5,27 +5,45 @@
-

Upload a new book

-
+ {% for message in uploadform.uploadpublication.errors %} +
{{ message }}
+ {% endfor %} + + {% for message in uploadform.author.errors %} +
{{ message }}
+ {% endfor %} +

Upload a new book

+ + {{ uploadform.csrf_token }}
{{ uploadform.uploadpublication.label }} - {{ uploadform.uploadpublication(size=20) }} + {{ uploadform.uploadpublication }} + {% for message in uploadform.uploadpublication.errors %} +
{{ message }}
+ {% endfor %}
{{ uploadform.author.label }} {{ uploadform.author }} + {% for message in uploadform.author.errors %} +
{{ message }}
+ {% endfor %}
{{ uploadform.year.label }} {{ uploadform.year }} + {% for message in uploadform.year.errors %} +
{{ message }}
+ {% endfor %}
+
{{ uploadform.custodian.label }} - {{ uploadform.custodian(size=20) }} + {{ uploadform.custodian }}
@@ -36,11 +54,14 @@
{{ uploadform.type.label }} {{ uploadform.type }} + {% for message in uploadform.type.errors %} +
{{ message }}
+ {% endfor %}
{{ uploadform.publishers.label }} - {{ uploadform.publishers(size=20) }} + {{ uploadform.publishers }}
@@ -55,7 +76,7 @@
{{ uploadform.highlights.label }} - {{ uploadform.highlights(size=20) }} + {{ uploadform.highlights }}
@@ -72,5 +93,4 @@
- {% endblock %} diff --git a/library/uploadform.py b/library/uploadform.py index 9ea488b..afae259 100644 --- a/library/uploadform.py +++ b/library/uploadform.py @@ -7,22 +7,57 @@ from wtforms import ( RadioField, SubmitField, ) -from wtforms.validators import DataRequired, Length +from wtforms import validators +from wtforms.validators import ( + Length, + NumberRange, +) class PublicationForm(FlaskForm): - """Contact form.""" + """Publication upload form.""" uploadpublication = StringField( - "Title of the publication:", [DataRequired()] + "Title of the publication:", + [ + validators.InputRequired(), + Length( + min=3, message="A publication in the library needs a title." + ), + ], + ) + author = StringField( + "The author or editor:", + [ + validators.InputRequired(), + Length( + min=3, + message=( + "If the author or editor is not known just type unkown." + ), + ), + ], + ) + year = IntegerField( + "Year:", [validators.InputRequired(), NumberRange(min=0, max=2050)] + ) + custodian = StringField("Custodian:") + fields = StringField("Fields:") + type = StringField( + "Type of publication:", + [ + validators.InputRequired(), + Length( + min=3, + message=( + "Here you can use terms such as zine, paperback," + " hardcover." + ), + ), + ], ) - author = StringField("The author or editor:", [DataRequired()]) - year = IntegerField("Year:", [DataRequired()]) - custodian = StringField("Custodian:", [DataRequired()]) - fields = StringField("Fields:", [DataRequired()]) - type = StringField("Type:", [DataRequired()]) - publishers = StringField("Publishers:", [DataRequired()]) - license = StringField("License:", [DataRequired()]) + publishers = StringField("Publishers:") + license = StringField("License:") licenseshort = RadioField( "Select the closest license type:", choices=[