This is a small web application that I have created using the Flask framework.
I am looking for best practices feedback, as well as design pointers. I am not confident that my design choices have been very good, or rather that they were the best they could have been, but I would like some feedback regardless on where I can improve and expand as I'm new to Python.
To begin, I'd like to review where I process my XML configuration file. The file is validated, and then a database is populated with the information. I feel like it could be improved, however, not included is validation and safety-checking of the user-supplied (really admin supplied) HTML from the XML doc.
from lxml import etree import time, datetime from time import mktime from contestassist.database import db_session from contestassist.contest import Contest from contestassist.question import Question from contestassist.config import Config import sqlalchemy import sys class XMLParser: def __init__(self, xml_file): self.xml_file = xml_file self.time_format = "%Y-%m-%d %H:%M:%S" def ProcessTemplate(self): #parser = etree.XMLParser(dtd_validation=True) parser = etree.XMLParser() xmldoc = etree.parse(self.xml_file, parser) contests = xmldoc.getroot() #validate against DTD dtd = open(Config.DTDPATH, 'r') dtdObj = etree.DTD(dtd) if dtdObj.validate(contests) is False: print "Supplied XML file is not correctly formatted" print(dtdObj.error_log.filter_from_errors()) sys.exit() for contest in contests.getchildren(): contest_id = self.parseContestInfo(contest) self.parseContestQuestions(contest, contest_id) def parseContestInfo(self, contestNodes): title = contestNodes.xpath('title') self.title_data = title.text description = contestNodes.xpath('description') self.description_data = description.text #Here we carefully extract the time from our xml node into a datetime object #in a couple steps. First we get the string from the node, then a time struct using strptime and a format string #then we create a datetime from the struct. start = contestNodes.xpath('start') start_node = start.text t_struct = time.strptime(start_node, self.time_format) self.start_datetime = datetime.datetime.fromtimestamp(mktime(t_struct)) end = contestNodes.xpath('end') end_node = end.text t_struct = time.strptime(end_node, self.time_format) self.end_datetime = datetime.datetime.fromtimestamp(mktime(t_struct)) #create contest and insert it into the database contest = Contest(self.title_data, self.description_data, self.end_datetime, self.start_datetime) try: db_session.add(contest) db_session.commit() except sqlalchemy.exc.IntegrityError, exc: reason = exc.message if reason.endswith('is not unique'): print "%s already exists" % exc.params db_session.rollback() #return the ID of this contest, so we can use it in the next function return contest.id def parseContestQuestions(self, contestNodes, contest_id): #get a list of questions for our contest questions = contestNodes.xpath('questions/question') #loop through these questions, grab the appropriate data #and then create question entries in the database for question in questions: points_temp = question.xpath('point-value') p_value = points_temp.text text_temp = question.xpath('question-text') q_text_value = text_temp.text answer_temp = question.xpath('question-answer') q_answer = answer_temp.text #create question object, and attach it to the contest with the id contest_id question = Question(p_value, q_text_value, q_answer, contest_id) try: db_session.add(question) db_session.commit() except sqlalchemy.exc.IntegrityError, exc: reason = exc.message if reason.endswith('is not unique'): print "%s already exists" % exc.params db_session.rollback()
I have a couple areas where I'd like to focus on:
user.py- Here, I'd like some critique on my class design choices. This class is used to store user information in the database. It provides some utility functions specific to the Flask framework and its plug-ins. It works with SQL Alchemy, so I can retain user info in a database. Am I storing user credentials poorly? How do the
flaskapp.py- this is where I do my app's route handling, build/process forms, etc. Most views are rendered with a list of dictionaries as an argument (containing for example questions, users, etc as part of the application). Is that bad design for a web application? Do I process forms in a decent manner? is there a way I can better organize all these routes? This file got sort of big fast.
Any feedback is appreciated. I would love to hear feedback in any areas, not necessarily what is named in the tags.