Xzzy is right. A lot of companies also try to get free tech support and consultation this way too. Mostly smaller businesses with absolutely no IT staff will ask these sorts of questions and really stay away from them.
You jumping in and handling a large client database like that is a red flag in my opinion. Although you'd be surprised at how much you know when you start doing it and you'll wonder why you ever worried.
bowen on
not a doctor, not a lawyer, examples I use may not be fully researched so don't take out of context plz, don't @ me
It's not the concepts of normalization that are hard. What is the hard part is having the experience to know what is necessary, and where to apply your knowledge. You have to know what data is coming in, what information users need from that data, and how often they are requesting it.
The knee-jerk reaction is to normalize everything from start to finish. A google search said that 5NF normalization is the best, so anything less is uncivilized!
In this regard, it's a lot like programming. You have to balance the desire to write perfect code against solving problems efficiently. They are not the same thing.
It's knowing why you should do things a certain way that you can't just read a SQL reference and get it, just like you can't learn how to design good algorithms just by reading a C language reference.
I'm sure many people have seen the results of "someone learn SQL and do the database" before. The actual database design is often... amazing. :x
import cgi
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db
class Greeting(db.Model):
author = db.UserProperty()
content = db.StringProperty(multiline=True)
date = db.DateTimeProperty(auto_now_add=True)
class MainPage(webapp.RequestHandler):
def get(self):
self.response.out.write('<html><body>')
greetings = db.GqlQuery("SELECT * FROM Greeting ORDER BY date DESC LIMIT 10")
for greeting in greetings:
if greeting.author:
self.response.out.write('<b>%s</b> wrote:' % greeting.author.nickname())
else:
self.response.out.write('An anonymous person wrote:')
self.response.out.write('<blockquote>%s</blockquote>' %
cgi.escape(greeting.content))
# Write the submission form and the footer of the page
self.response.out.write("""
<form action="/sign" method="post">
<div><textarea name="content" rows="3" cols="60"></textarea></div>
<div><input type="submit" value="Sign Guestbook"></div>
</form>
</body>
</html>""")
class Guestbook(webapp.RequestHandler):
def post(self):
greeting = Greeting()
if users.get_current_user():
greeting.author = users.get_current_user()
greeting.content = self.request.get('content')
greeting.put()
self.redirect('/')
application = webapp.WSGIApplication(
[('/', MainPage),
('/sign', Guestbook)],
debug=True)
def main():
run_wsgi_app(application)
if __name__ == "__main__":
main()
import cgi
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db
class BBSThreads(db.Model):
author = db.UserProperty;
thread = db.StringProperty(multiline=True)
date = db.DateTimeProperty(auto_now_add=True)
class DisplayThreads(webapp.RequestHandler):
def get(self):
self.response.out.write('<html><body>')
threads = db.GqlQuery("SELECT * FROM BBSThreads ORDER BY date DESC LIMIT 10")
for thread in threads:
if thread.author:
self.response.out.write('<b>%s</b> wrote:' % thread.author.nickname())
else:
self.response.out.write('Anonymous wrote:')
self.response.out.write('<blockquote>%s</blockquote>' %
cgi.escape(thread.content))
# Write the submission form and the footer of the page
self.response.out.write("""
<form action="/postthread" method="post">
<div><textarea name="content" rows="3" cols="60"></textarea></div>
<div><input type="submit" value="Post Thread"></div>
</form>
</body>
</html>""")
class BBS(webapp.RequestHandler):
def post(self):
thread = BBSThreads()
if users.get_current_user():
thread.author = users.get_current_user()
thread.content = self.request.get('content')
thread.put()
self.redirect('/')
application = webapp.WSGIApplication(
[('/', DisplayThreads),
('/postthread', BBS)],
debug=True)
def main():
run_wsgi_app(application)
if __name__ == "__main__":
main()
Traceback (most recent call last):
File "C:\Program Files\Google\google_appengine\google\appengine\ext\webapp\__init__.py", line 507, in __call__
handler.get(*groups)
File "C:\Documents and Settings\mkr\Desktop\GoogleAppEngine-Development\New Folder\FancyPants\bbs.py", line 21, in get
self.response.out.write('<b>%s</b> wrote:' % thread.author.nickname())
AttributeError: type object 'UserProperty' has no attribute 'nickname'
Short of running a diff on this and the guestbook script, I can't figure out what difference between the two is making it behave differently.
for thread in threads:
if thread.author:
self.response.out.write('<b>%s</b> wrote:' % thread.author.nickname())
thread.author doesn't have a function called nickname()
That's about all I can gather from that error message.
My guess is that the UserProperty (author in this case) isn't the right object type for what you're trying to do there.
That's the thing. As far as I can tell that part is structurally identical to the Google-supplied guestbook code, which works fine. All the imports are there.
edit: Crap, forgot the (). Whoops.
author = db.UserProperty; should be author = db.UserProperty();
edit: Now for something completely different!
import cgi
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db
class BBSThreads(db.Model):
author = db.UserProperty()
content = db.StringProperty(multiline=True)
date = db.DateTimeProperty(auto_now_add=True)
class DisplayThreads(webapp.RequestHandler):
def get(self):
self.response.out.write('<html><body>')
threads = db.GqlQuery("SELECT * FROM BBSThreads ORDER BY date DESC LIMIT 10")
for thread in threads:
if thread.author:
self.response.out.write('<b>%s</b> wrote:' % thread.author.nickname())
else:
self.response.out.write('Anonymous wrote:')
self.response.out.write('<blockquote>%s</blockquote>' %
cgi.escape(thread.content))
# Write the submission form and the footer of the page
self.response.out.write("""
<form action="/postthread" method="post">
<div><textarea name="content" rows="3" cols="60"></textarea></div>
<div><input type="submit" value="Post Thread"></div>
</form>
</body>
</html>""")
class BBS(webapp.RequestHandler):
def post(self):
thread = BBSThreads()
if users.get_current_user():
thread.author = users.get_current_user()
thread.content = self.request.get('content')
thread.put()
self.redirect('/')
application = webapp.WSGIApplication(
[('/', DisplayThreads),
('/postthread', BBS)],
debug=True)
def main():
run_wsgi_app(application)
if __name__ == "__main__":
main()
Traceback (most recent call last):
File "C:\Program Files\Google\google_appengine\google\appengine\ext\webapp\__init__.py", line 507, in __call__
handler.get(*groups)
File "C:\Documents and Settings\mkr\Desktop\GoogleAppEngine-Development\New Folder\FancyPants\bbs.py", line 25, in get
cgi.escape(thread.content))
File "C:\Python26\lib\cgi.py", line 1035, in escape
s = s.replace("&", "&") # Must be done first!
AttributeError: 'NoneType' object has no attribute 'replace'
I honestly can't figure out why it won't work. main.py runs fine, while bbs.py produces this:
Traceback (most recent call last):
File "C:\Program Files\Google\google_appengine\google\appengine\ext\webapp\__init__.py", line 507, in __call__
handler.get(*groups)
File "C:\Documents and Settings\mkr\Desktop\GoogleAppEngine-Development\New Folder\FancyPants\bbs.py", line 25, in get
cgi.escape(currentthread.content))
File "C:\Python26\lib\cgi.py", line 1035, in escape
s = s.replace("&", "&") # Must be done first!
AttributeError: 'NoneType' object has no attribute 'replace'
And I don't see anything that could possibly be causing this. I took the cgi.escape call out and got my list of posts, so I know the posts are going to the data store and being retrieved without difficulty. This call is the only hindrance, and it's being used in the same way as in the functional template in a way consistent with its documentation.
I'm at a complete loss here.
edit: I grabbed the actual code for cgi.replace out of cgi.py and swapped it out in my code. It looks like there should be a replace method in s, but it's not there.
s = currentthread.content
s = s.replace("&", "&") # Must be done first!
s = s.replace("<", "<")
s = s.replace(">", ">")
self.response.out.write('<blockquote>%s</blockquote>' % s)
And it's the same error.
edit: On the subject of database design...
I forgot to delete on old column in my DB when I changed to a layout that has two rather than three columns. The 3 column entry was making cgi.escape spaz I guess. It worked fine after I deleted the entry.
class Greeting(db.Model):
author = db.UserProperty()
content = db.StringProperty(multiline=True)
date = db.DateTimeProperty(auto_now_add=True)
[/SPOILER]
class BBSThreads(db.Model):
author = db.UserProperty;
thread = db.StringProperty(multiline=True)
date = db.DateTimeProperty(auto_now_add=True)
Haven't done any python in a while, and even then it was only scripting in a game engine. But I'm going to take a wild stab and say that those two author declaration lines are doing different things, since they have different syntax.
Edit: You know, I always forget that the little "latest unread post" button can take you to the bottom of a previous page. This is like the third time this week I've done this.
So I'm reading through C# 3.0, an O'Reilley book. Well, first it sucks because the book is aimed straight at beginning programmers, who have no clue what a for loop is. Apparently I bought the wrong book, oh well.
So I'm skimming the chapters, and come through Branching, and blam, right there they explain goto.
I don't follow the Dijkstra school of through (GOTO considered harmful), but I think beginners, hell, intermediate programmers should stay away from goto and instead focus on a good design that doesn't need goto.
It's a good principle to understand, though I agree it never should be used. Many higher-level languages lose too much touch with the actual CPU as it is, and goto reminds you that everything ultimately boils down to sequential instructions.
My only brush with goto since I stopped doing TI-83 programming was in VBA, during my first ever experience with being violated by said "language", when I couldn't find any other way to make several common loop constructs due to a stunning lack of documentation.
Probably my primary case for goto is when you might not have the best loop-auxiliary commands like break and continue. Parametrized break (e.g. "break 2;" to leave two nested levels of loop), especially, is something you don't use often but you really miss if you don't have it. That said, I don't find myself wishing I had goto approximately ever.
The main hazard of goto is easy to understand, so I don't think there's much harm in mentioning it as long as the dangers are noted. They're going to encounter it sooner or later, so it's better to make sure it's from a source that lets them know why it's dangerous.
I have never had to use goto, ever. As such, it should be taught in an advanced topic book so when I maintain or approve your shitty code jr programmers, I don't have to deal with it. Because most jr programmers read "introduction to X" and then use google for the advanced stuff.
Yeah, I'm a bit bitter about it because this one guy wrote code like he was programming for the TI-83.
bowen on
not a doctor, not a lawyer, examples I use may not be fully researched so don't take out of context plz, don't @ me
I suppose that you can work around that by just completely ditching functions and manually maintaining a stack pointer that you shift whenever you would switch from one function to another.
So, I've got two separate windows in curses, I filled the game window with my background tile letter and I'm capturing keys well. However, I can't get my program to exit cleanly. My terminal is all screwy despite undoing everything I do in the setup portion. As it is right now, it returns the terminal to a blank terminal, but with my regular command line. There's no echo and some window size settings are still screwy it seems. I can't really wrap my head around what's going wrong. Here's the interface snippet:
#!/usr/bin/python
## INTERFACE.PY
import curses
import sys
import os
# Set up environment
stdscr = curses.initscr()
curses.noecho()
curses.cbreak()
stdscr.keypad(0)
curses.curs_set(0)
def title(): # Spawning the title window
begin_x = 20
begin_y = 0
height = 5
width = 100
global win
win = curses.newwin(height, width, begin_y, begin_x)
win.addstr(begin_y+2, width/2-10 , "Hide The Knife!", curses.A_BOLD) # Printing title, approximately in the middle
win.border(0)
win.erase
win.refresh()
return win
def gamewindow(): # Spawning the game window
begin_x = 20
begin_y = 6
height = 30
width = 100
global gamewin
gamewin = curses.newwin(height, width, begin_y, begin_x)
gamewin.border(0)
gamewin.erase
gamewin.refresh()
pad = curses.newpad(100, 100)
# These loops fill the pad with background letters
for y in range(0, 30):
for x in range(0, 100):
try: pad.addch(y,x, ord('.') + 1 % 1 )
except curses.error: pass
pad.refresh( 0, 0, 7, 21, 34, 118)
return gamewin
def quit():
curses.nocbreak()
curses.echo()
stdscr.keypad(0)
curses.endwin
os.system("clear")
def controls(): # Get character input
while 1:
c = gamewin.getch()
if c == ord('q') or ord('Q'):
quit()
break
def main(): # Main loop
os.system("clear")
title()
gamewindow()
controls()
main()
Also, am I doing something terribly wrong in how I'm setting this up? It's basically my first program containing functions and what not, so I'm a little shaky.
I have never had to use goto, ever. As such, it should be taught in an advanced topic book so when I maintain or approve your shitty code jr programmers, I don't have to deal with it. Because most jr programmers read "introduction to X" and then use google for the advanced stuff.
Yeah, I'm a bit bitter about it because this one guy wrote code like he was programming for the TI-83.
Jeez, can I have his job? Even working in VB6 looks pretty cushy to me now.
Right chaps, here's a very, very familiar tale. I'm looking to start learning to program. I've done some Basic and Java in the past at university, never to an advanced level but enough to pass the modules. I do concede that I will need to start from the beginning again, though, as this was a few years ago and I don't remember a great deal of it. The other issue is that since I've recently acquired an Android phone, I'm interested in learning to make stuff for that. I've got ideas for where I ultimately want to go, but I know that you need to start small and take a long time to work up. What I'm really asking for is advice on where to get started and what the best tutorials are for a total novice.
Also to be told if this is the worst idea since the invention of dick sandwiches.
Right chaps, here's a very, very familiar tale. I'm looking to start learning to program. I've done some Basic and Java in the past at university, never to an advanced level but enough to pass the modules. I do concede that I will need to start from the beginning again, though, as this was a few years ago and I don't remember a great deal of it. The other issue is that since I've recently acquired an Android phone, I'm interested in learning to make stuff for that. I've got ideas for where I ultimately want to go, but I know that you need to start small and take a long time to work up. What I'm really asking for is advice on where to get started and what the best tutorials are for a total novice.
Also to be told if this is the worst idea since the invention of dick sandwiches.
The Android SDK probably has a guide and loads of examples. Google likes to do that.
So, I've got two separate windows in curses, I filled the game window with my background tile letter and I'm capturing keys well. However, I can't get my program to exit cleanly. My terminal is all screwy despite undoing everything I do in the setup portion. As it is right now, it returns the terminal to a blank terminal, but with my regular command line. There's no echo and some window size settings are still screwy it seems. I can't really wrap my head around what's going wrong. Here's the interface snippet:
#!/usr/bin/python
## INTERFACE.PY
import curses
import sys
import os
# Set up environment
stdscr = curses.initscr()
curses.noecho()
curses.cbreak()
stdscr.keypad(0)
curses.curs_set(0)
def title(): # Spawning the title window
begin_x = 20
begin_y = 0
height = 5
width = 100
global win
win = curses.newwin(height, width, begin_y, begin_x)
win.addstr(begin_y+2, width/2-10 , "Hide The Knife!", curses.A_BOLD) # Printing title, approximately in the middle
win.border(0)
win.erase
win.refresh()
return win
def gamewindow(): # Spawning the game window
begin_x = 20
begin_y = 6
height = 30
width = 100
global gamewin
gamewin = curses.newwin(height, width, begin_y, begin_x)
gamewin.border(0)
gamewin.erase
gamewin.refresh()
pad = curses.newpad(100, 100)
# These loops fill the pad with background letters
for y in range(0, 30):
for x in range(0, 100):
try: pad.addch(y,x, ord('.') + 1 % 1 )
except curses.error: pass
pad.refresh( 0, 0, 7, 21, 34, 118)
return gamewin
def quit():
curses.nocbreak()
curses.echo()
stdscr.keypad(0)
curses.endwin
os.system("clear")
def controls(): # Get character input
while 1:
c = gamewin.getch()
if c == ord('q') or ord('Q'):
quit()
break
def main(): # Main loop
os.system("clear")
title()
gamewindow()
controls()
main()
Also, am I doing something terribly wrong in how I'm setting this up? It's basically my first program containing functions and what not, so I'm a little shaky.
edit: slapping some spoiler tags on that..
Prepare to feel like a goof!
You have to call curses.endwin(), not curses.endwin
edit - also, you have to be super careful about fatal errors when making curses programs. My terminal, for example, does not support changing the cursor. So the call to curses.curs_set(0) causes the program to terminate and leaving my terminal in shambles. The proper fix is to use a try/catch block so that you can cleanly exit if any terminal-setting calls fail.
Yeah Android SDK is free and it's Java based. Really easy for you to learn if you'd learned it in the past. If you want a little reference to GUI stuff I'm in a class that's talking about it so you could check out this place: http://www.cs.wright.edu/~thartrum/CEG355WI10/intro355.html it's got some examples and stuff. I'd really just read the Swing stuff and the JTables if you'd like to go into GUI.
But he's got a lot of examples there. Might not be for beginners but it could be a refresher.
I have never had to use goto, ever. As such, it should be taught in an advanced topic book so when I maintain or approve your shitty code jr programmers, I don't have to deal with it. Because most jr programmers read "introduction to X" and then use google for the advanced stuff.
Yeah, I'm a bit bitter about it because this one guy wrote code like he was programming for the TI-83.
Jeez, can I have his job? Even working in VB6 looks pretty cushy to me now.
Unfortunately this code was remnants of an old system that was contracted out. If we had the room and the budget for more IT, then so fucking hard yes.
bowen on
not a doctor, not a lawyer, examples I use may not be fully researched so don't take out of context plz, don't @ me
So studying for my IT Design midterm, I ran into something I'm not sure what's going on. I normally do everything in one file, which isn't very robust. If you change one thing you have to change a lot of the files.
So we're learning about separating the application from the GUI.
This is the code I'm reading:
//*********************************************
// main - creates the application and the GUI.
//*********************************************
public static void main(String args[])
{
Comparer2 tester = new Comparer2();
CompareGUI2 myGUI = new CompareGUI2(tester);
tester.setGUI(myGUI);
}//main
//*********************************************
// setGUI - sets the pointer to call the GUI.
//*********************************************
public void setGUI(CompareGUI2 g)
{
gui = g;
}
I don't know why you would need a separate function for that. Why couldn't you just do that in the main?
So studying for my IT Design midterm, I ran into something I'm not sure what's going on. I normally do everything in one file, which isn't very robust. If you change one thing you have to change a lot of the files.
So we're learning about separating the application from the GUI.
This is the code I'm reading:
//*********************************************
// main - creates the application and the GUI.
//*********************************************
public static void main(String args[])
{
Comparer2 tester = new Comparer2();
CompareGUI2 myGUI = new CompareGUI2(tester);
tester.setGUI(myGUI);
}//main
//*********************************************
// setGUI - sets the pointer to call the GUI.
//*********************************************
public void setGUI(CompareGUI2 g)
{
gui = g;
}
I don't know why you would need a separate function for that. Why couldn't you just do that in the main?
Do something like: myGUI = gui;
It's probably to hammer in the idea of separating things. Right now it's simple, but what happens when you need a thousand line class to handle your GUI? Do you want that mingling with GUI framework code?
So studying for my IT Design midterm, I ran into something I'm not sure what's going on. I normally do everything in one file, which isn't very robust. If you change one thing you have to change a lot of the files.
So we're learning about separating the application from the GUI.
This is the code I'm reading:
//*********************************************
// main - creates the application and the GUI.
//*********************************************
public static void main(String args[])
{
Comparer2 tester = new Comparer2();
CompareGUI2 myGUI = new CompareGUI2(tester);
tester.setGUI(myGUI);
}//main
//*********************************************
// setGUI - sets the pointer to call the GUI.
//*********************************************
public void setGUI(CompareGUI2 g)
{
gui = g;
}
I don't know why you would need a separate function for that. Why couldn't you just do that in the main?
Do something like: myGUI = gui;
It's probably to hammer in the idea of separating things. Right now it's simple, but what happens when you need a thousand line class to handle your GUI? Do you want that mingling with GUI framework code?
Ah I see. Yeah I don't like to have much of anything in my main method and I guess it helps to separate it out.
So, I've got two separate windows in curses, I filled the game window with my background tile letter and I'm capturing keys well. However, I can't get my program to exit cleanly. My terminal is all screwy despite undoing everything I do in the setup portion. As it is right now, it returns the terminal to a blank terminal, but with my regular command line. There's no echo and some window size settings are still screwy it seems. I can't really wrap my head around what's going wrong. Here's the interface snippet:
#!/usr/bin/python
## INTERFACE.PY
import curses
import sys
import os
# Set up environment
stdscr = curses.initscr()
curses.noecho()
curses.cbreak()
stdscr.keypad(0)
curses.curs_set(0)
def title(): # Spawning the title window
begin_x = 20
begin_y = 0
height = 5
width = 100
global win
win = curses.newwin(height, width, begin_y, begin_x)
win.addstr(begin_y+2, width/2-10 , "Hide The Knife!", curses.A_BOLD) # Printing title, approximately in the middle
win.border(0)
win.erase
win.refresh()
return win
def gamewindow(): # Spawning the game window
begin_x = 20
begin_y = 6
height = 30
width = 100
global gamewin
gamewin = curses.newwin(height, width, begin_y, begin_x)
gamewin.border(0)
gamewin.erase
gamewin.refresh()
pad = curses.newpad(100, 100)
# These loops fill the pad with background letters
for y in range(0, 30):
for x in range(0, 100):
try: pad.addch(y,x, ord('.') + 1 % 1 )
except curses.error: pass
pad.refresh( 0, 0, 7, 21, 34, 118)
return gamewin
def quit():
curses.nocbreak()
curses.echo()
stdscr.keypad(0)
curses.endwin
os.system("clear")
def controls(): # Get character input
while 1:
c = gamewin.getch()
if c == ord('q') or ord('Q'):
quit()
break
def main(): # Main loop
os.system("clear")
title()
gamewindow()
controls()
main()
Also, am I doing something terribly wrong in how I'm setting this up? It's basically my first program containing functions and what not, so I'm a little shaky.
edit: slapping some spoiler tags on that..
Prepare to feel like a goof!
You have to call curses.endwin(), not curses.endwin
edit - also, you have to be super careful about fatal errors when making curses programs. My terminal, for example, does not support changing the cursor. So the call to curses.curs_set(0) causes the program to terminate and leaving my terminal in shambles. The proper fix is to use a try/catch block so that you can cleanly exit if any terminal-setting calls fail.
Jesus christ. Thanks a lot!
The Python implementation of Curses has some sort of wrapper to help that problem with errors, but I can't seem to get it to work. You're supposed to pass your main() to it, but it always fails, ironically leaving my term cluttered.
It's annoying to have the framework of what I want to make 90% done, but with a few little things that keep me from building on it.
My little BBS script:
1. Creates new threads and makes a first post for the thread
2. Displays the list of threads
3. Loads clicked threads
But my PostInTopic class is being a silly goose. Entries show if I add them manually, but not when posted with the form. It's probably simple, but I'm too tired to figure out the exact cause. But I did make loads of progress on it. :rotate:
And I have a question for people with competency in DB design. Should I be tossing all my posts into one table (like they are now) with the associated thread's ID in each post (row), or should I be creating some new container for each thread's posts?
edit: Yay, solved the post issue. There was a mysterious if block on the post code that always returned false, so the post code never ran.
Posts
You jumping in and handling a large client database like that is a red flag in my opinion. Although you'd be surprised at how much you know when you start doing it and you'll wonder why you ever worried.
Let me check what I can dig.
Edit: Some links
http://www.devx.com/ibm/Article/20859/1763
http://www.sqlteam.com/article/database-design-and-modeling-fundamentals
"We have years of struggle ahead, mostly within ourselves." - Made in USA
The knee-jerk reaction is to normalize everything from start to finish. A google search said that 5NF normalization is the best, so anything less is uncivilized!
In this regard, it's a lot like programming. You have to balance the desire to write perfect code against solving problems efficiently. They are not the same thing.
It's knowing why you should do things a certain way that you can't just read a SQL reference and get it, just like you can't learn how to design good algorithms just by reading a C language reference.
I'm sure many people have seen the results of "someone learn SQL and do the database" before.
Why does it appears the tables are named by incrementing a number?
Wait.. all the columns are varchar? How does that happen?
And then each separate table is in it's own database.
Here's the original guestbook script (http://code.google.com/appengine/docs/python/gettingstarted/usingdatastore.html):
import cgi from google.appengine.api import users from google.appengine.ext import webapp from google.appengine.ext.webapp.util import run_wsgi_app from google.appengine.ext import db class Greeting(db.Model): author = db.UserProperty() content = db.StringProperty(multiline=True) date = db.DateTimeProperty(auto_now_add=True) class MainPage(webapp.RequestHandler): def get(self): self.response.out.write('<html><body>') greetings = db.GqlQuery("SELECT * FROM Greeting ORDER BY date DESC LIMIT 10") for greeting in greetings: if greeting.author: self.response.out.write('<b>%s</b> wrote:' % greeting.author.nickname()) else: self.response.out.write('An anonymous person wrote:') self.response.out.write('<blockquote>%s</blockquote>' % cgi.escape(greeting.content)) # Write the submission form and the footer of the page self.response.out.write(""" <form action="/sign" method="post"> <div><textarea name="content" rows="3" cols="60"></textarea></div> <div><input type="submit" value="Sign Guestbook"></div> </form> </body> </html>""") class Guestbook(webapp.RequestHandler): def post(self): greeting = Greeting() if users.get_current_user(): greeting.author = users.get_current_user() greeting.content = self.request.get('content') greeting.put() self.redirect('/') application = webapp.WSGIApplication( [('/', MainPage), ('/sign', Guestbook)], debug=True) def main(): run_wsgi_app(application) if __name__ == "__main__": main()import cgi from google.appengine.api import users from google.appengine.ext import webapp from google.appengine.ext.webapp.util import run_wsgi_app from google.appengine.ext import db class BBSThreads(db.Model): author = db.UserProperty; thread = db.StringProperty(multiline=True) date = db.DateTimeProperty(auto_now_add=True) class DisplayThreads(webapp.RequestHandler): def get(self): self.response.out.write('<html><body>') threads = db.GqlQuery("SELECT * FROM BBSThreads ORDER BY date DESC LIMIT 10") for thread in threads: if thread.author: self.response.out.write('<b>%s</b> wrote:' % thread.author.nickname()) else: self.response.out.write('Anonymous wrote:') self.response.out.write('<blockquote>%s</blockquote>' % cgi.escape(thread.content)) # Write the submission form and the footer of the page self.response.out.write(""" <form action="/postthread" method="post"> <div><textarea name="content" rows="3" cols="60"></textarea></div> <div><input type="submit" value="Post Thread"></div> </form> </body> </html>""") class BBS(webapp.RequestHandler): def post(self): thread = BBSThreads() if users.get_current_user(): thread.author = users.get_current_user() thread.content = self.request.get('content') thread.put() self.redirect('/') application = webapp.WSGIApplication( [('/', DisplayThreads), ('/postthread', BBS)], debug=True) def main(): run_wsgi_app(application) if __name__ == "__main__": main()Short of running a diff on this and the guestbook script, I can't figure out what difference between the two is making it behave differently.
for thread in threads: if thread.author: self.response.out.write('<b>%s</b> wrote:' % thread.author.nickname())thread.author doesn't have a function called nickname()
That's about all I can gather from that error message.
My guess is that the UserProperty (author in this case) isn't the right object type for what you're trying to do there.
That's the thing. As far as I can tell that part is structurally identical to the Google-supplied guestbook code, which works fine. All the imports are there.
edit: Crap, forgot the (). Whoops.
author = db.UserProperty; should be author = db.UserProperty();
edit: Now for something completely different!
import cgi from google.appengine.api import users from google.appengine.ext import webapp from google.appengine.ext.webapp.util import run_wsgi_app from google.appengine.ext import db class BBSThreads(db.Model): author = db.UserProperty() content = db.StringProperty(multiline=True) date = db.DateTimeProperty(auto_now_add=True) class DisplayThreads(webapp.RequestHandler): def get(self): self.response.out.write('<html><body>') threads = db.GqlQuery("SELECT * FROM BBSThreads ORDER BY date DESC LIMIT 10") for thread in threads: if thread.author: self.response.out.write('<b>%s</b> wrote:' % thread.author.nickname()) else: self.response.out.write('Anonymous wrote:') self.response.out.write('<blockquote>%s</blockquote>' % cgi.escape(thread.content)) # Write the submission form and the footer of the page self.response.out.write(""" <form action="/postthread" method="post"> <div><textarea name="content" rows="3" cols="60"></textarea></div> <div><input type="submit" value="Post Thread"></div> </form> </body> </html>""") class BBS(webapp.RequestHandler): def post(self): thread = BBSThreads() if users.get_current_user(): thread.author = users.get_current_user() thread.content = self.request.get('content') thread.put() self.redirect('/') application = webapp.WSGIApplication( [('/', DisplayThreads), ('/postthread', BBS)], debug=True) def main(): run_wsgi_app(application) if __name__ == "__main__": main()The offending line is:
If I take the cgi.escape call out, it works, but input checking is kind of a big deal.
I honestly can't figure out why it won't work. main.py runs fine, while bbs.py produces this:
And I don't see anything that could possibly be causing this. I took the cgi.escape call out and got my list of posts, so I know the posts are going to the data store and being retrieved without difficulty. This call is the only hindrance, and it's being used in the same way as in the functional template in a way consistent with its documentation.
I'm at a complete loss here.
edit: I grabbed the actual code for cgi.replace out of cgi.py and swapped it out in my code. It looks like there should be a replace method in s, but it's not there.
s = currentthread.content s = s.replace("&", "&") # Must be done first! s = s.replace("<", "<") s = s.replace(">", ">") self.response.out.write('<blockquote>%s</blockquote>' % s)And it's the same error.
edit: On the subject of database design...
I forgot to delete on old column in my DB when I changed to a layout that has two rather than three columns. The 3 column entry was making cgi.escape spaz I guess. It worked fine after I deleted the entry.
Edit: You know, I always forget that the little "latest unread post" button can take you to the bottom of a previous page. This is like the third time this week I've done this.
So I'm skimming the chapters, and come through Branching, and blam, right there they explain goto.
I don't follow the Dijkstra school of through (GOTO considered harmful), but I think beginners, hell, intermediate programmers should stay away from goto and instead focus on a good design that doesn't need goto.
See how many books I've read so far in 2010
See how many books I've read so far in 2010
if (conditional) { statements }with
You can do a similar thing with your while loops.
Why should you expect your compiler to do all the work for you?
SE++ Forum Battle Archive
Yeah, I'm a bit bitter about it because this one guy wrote code like he was programming for the TI-83.
Bah, next you'll be saying that you shouldn't replace all of your local variables with stack offsets.
Actually, does C have a way to get the start of the local stack?
I suppose that you can work around that by just completely ditching functions and manually maintaining a stack pointer that you shift whenever you would switch from one function to another.
#!/usr/bin/python ## INTERFACE.PY import curses import sys import os # Set up environment stdscr = curses.initscr() curses.noecho() curses.cbreak() stdscr.keypad(0) curses.curs_set(0) def title(): # Spawning the title window begin_x = 20 begin_y = 0 height = 5 width = 100 global win win = curses.newwin(height, width, begin_y, begin_x) win.addstr(begin_y+2, width/2-10 , "Hide The Knife!", curses.A_BOLD) # Printing title, approximately in the middle win.border(0) win.erase win.refresh() return win def gamewindow(): # Spawning the game window begin_x = 20 begin_y = 6 height = 30 width = 100 global gamewin gamewin = curses.newwin(height, width, begin_y, begin_x) gamewin.border(0) gamewin.erase gamewin.refresh() pad = curses.newpad(100, 100) # These loops fill the pad with background letters for y in range(0, 30): for x in range(0, 100): try: pad.addch(y,x, ord('.') + 1 % 1 ) except curses.error: pass pad.refresh( 0, 0, 7, 21, 34, 118) return gamewin def quit(): curses.nocbreak() curses.echo() stdscr.keypad(0) curses.endwin os.system("clear") def controls(): # Get character input while 1: c = gamewin.getch() if c == ord('q') or ord('Q'): quit() break def main(): # Main loop os.system("clear") title() gamewindow() controls() main()Also, am I doing something terribly wrong in how I'm setting this up? It's basically my first program containing functions and what not, so I'm a little shaky.
edit: slapping some spoiler tags on that..
Jeez, can I have his job? Even working in VB6 looks pretty cushy to me now.
Also to be told if this is the worst idea since the invention of dick sandwiches.
The Android SDK probably has a guide and loads of examples. Google likes to do that.
Prepare to feel like a goof!
edit - also, you have to be super careful about fatal errors when making curses programs. My terminal, for example, does not support changing the cursor. So the call to curses.curs_set(0) causes the program to terminate and leaving my terminal in shambles. The proper fix is to use a try/catch block so that you can cleanly exit if any terminal-setting calls fail.
But he's got a lot of examples there. Might not be for beginners but it could be a refresher.
Unfortunately this code was remnants of an old system that was contracted out. If we had the room and the budget for more IT, then so fucking hard yes.
So we're learning about separating the application from the GUI.
This is the code I'm reading:
//********************************************* // main - creates the application and the GUI. //********************************************* public static void main(String args[]) { Comparer2 tester = new Comparer2(); CompareGUI2 myGUI = new CompareGUI2(tester); tester.setGUI(myGUI); }//main //********************************************* // setGUI - sets the pointer to call the GUI. //********************************************* public void setGUI(CompareGUI2 g) { gui = g; }I don't know why you would need a separate function for that. Why couldn't you just do that in the main?
Do something like: myGUI = gui;
It's probably to hammer in the idea of separating things. Right now it's simple, but what happens when you need a thousand line class to handle your GUI? Do you want that mingling with GUI framework code?
Ah I see. Yeah I don't like to have much of anything in my main method and I guess it helps to separate it out.
Jesus christ. Thanks a lot!
The Python implementation of Curses has some sort of wrapper to help that problem with errors, but I can't seem to get it to work. You're supposed to pass your main() to it, but it always fails, ironically leaving my term cluttered.
My little BBS script:
1. Creates new threads and makes a first post for the thread
2. Displays the list of threads
3. Loads clicked threads
But my PostInTopic class is being a silly goose. Entries show if I add them manually, but not when posted with the form. It's probably simple, but I'm too tired to figure out the exact cause. But I did make loads of progress on it. :rotate:
And I have a question for people with competency in DB design. Should I be tossing all my posts into one table (like they are now) with the associated thread's ID in each post (row), or should I be creating some new container for each thread's posts?
edit: Yay, solved the post issue. There was a mysterious if block on the post code that always returned false, so the post code never ran.