[svn] QM parser now parses Hauchhoehle QMs.py

Photo model added.

Logbook parser now puts mugshots in as photo models, and descriptions from the old folk html pages in as "blurbs" on the person model.

Experimented with eye candy and a random logbook quote generator.
Copied from http://cucc@cucc.survex.com/svn/trunk/expoweb/troggle/, rev. 8094 by aaron @ 12/31/2008 2:59 AM
This commit is contained in:
substantialnoninfringinguser 2009-05-13 05:25:17 +01:00
parent 8c818906b5
commit 7aee3fb920
14 changed files with 261 additions and 93 deletions

View File

@ -8,7 +8,7 @@ class RoleInline(admin.TabularInline):
class SurvexBlockAdmin(admin.ModelAdmin): class SurvexBlockAdmin(admin.ModelAdmin):
inlines = (RoleInline,) inlines = (RoleInline,)
admin.site.register(Photo)
admin.site.register(Cave) admin.site.register(Cave)
admin.site.register(Area) admin.site.register(Area)
admin.site.register(OtherCaveName) admin.site.register(OtherCaveName)
@ -24,3 +24,4 @@ admin.site.register(Role)
admin.site.register(LogbookEntry) admin.site.register(LogbookEntry)
admin.site.register(PersonTrip) admin.site.register(PersonTrip)
admin.site.register(QM) admin.site.register(QM)

View File

@ -27,8 +27,9 @@ class Expedition(models.Model):
class Person(models.Model): class Person(models.Model):
first_name = models.CharField(max_length=100) first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100) last_name = models.CharField(max_length=100)
is_vfho = models.BooleanField() is_vfho = models.BooleanField(help_text="VFHO is the Vereines für Höhlenkunde in Obersteier, a nearby Austrian caving club.")
mug_shot = models.CharField(max_length=100, blank=True,null=True) mug_shot = models.CharField(max_length=100, blank=True,null=True)
blurb = models.TextField(blank=True,null=True)
def __unicode__(self): def __unicode__(self):
return "%s %s" % (self.first_name, self.last_name) return "%s %s" % (self.first_name, self.last_name)
@ -55,7 +56,6 @@ class PersonExpedition(models.Model):
#class LogbookSentanceRating(models.Model): #class LogbookSentanceRating(models.Model):
# rating = models.IntegerField() # rating = models.IntegerField()
@ -157,10 +157,7 @@ class LogbookEntry(models.Model):
author = models.ForeignKey(PersonExpedition,blank=True,null=True) # the person who writes it up doesn't have to have been on the trip author = models.ForeignKey(PersonExpedition,blank=True,null=True) # the person who writes it up doesn't have to have been on the trip
title = models.CharField(max_length=200) title = models.CharField(max_length=200)
cave = models.ForeignKey(Cave,blank=True,null=True) cave = models.ForeignKey(Cave,blank=True,null=True)
# this will be a foreign key of the place the logbook is describing - JT
place = models.CharField(max_length=100,blank=True,null=True) place = models.CharField(max_length=100,blank=True,null=True)
# adding optional cave reference
# cave = models.ForeignKey(Cave,blank=True,null=True)
text = models.TextField() text = models.TextField()
# several PersonTrips point in to this object # several PersonTrips point in to this object
@ -273,4 +270,25 @@ class QM(models.Model):
#dateKilled = models.DateField(blank=True) #dateKilled = models.DateField(blank=True)
def __str__(self): def __str__(self):
QMnumber=str(self.found_by.cave)+'-'+str(self.found_by.date.year)+"-"+str(self.number)+self.grade QMnumber=str(self.found_by.cave)+'-'+str(self.found_by.date.year)+"-"+str(self.number)+self.grade
return str(QMnumber) return str(QMnumber)
class Photo(models.Model):
caption = models.CharField(max_length=1000,blank=True,null=True)
contains_person_trip = models.ManyToManyField(PersonTrip,blank=True,null=True)
contains_person = models.ManyToManyField(Person,blank=True,null=True)
file = models.ImageField(upload_to='photos',)
is_mugshot = models.BooleanField(default=False)
contains_cave = models.ForeignKey(Cave,blank=True,null=True)
contains_entrance = models.ForeignKey(Entrance, related_name="photo_file",blank=True,null=True)
nearest_survey_point = models.ForeignKey(SurveyStation,blank=True,null=True)
nearest_QM = models.ForeignKey(QM,blank=True,null=True)
lon_utm = models.FloatField(blank=True,null=True)
lat_utm = models.FloatField(blank=True,null=True)
#content_type = models.ForeignKey(ContentType)
#object_id = models.PositiveIntegerField()
#location = generic.GenericForeignKey('content_type', 'object_id')
def __str__(self):
return self.caption

View File

@ -0,0 +1,24 @@
import troggle.settings as settings
from django import forms
from expo.models import LogbookEntry
import random
import re
def weighted_choice(lst):
n = random.uniform(0,1)
for item, weight in lst:
if n < weight:
break
n = n - weight
return item
def randomLogbookSentence():
#Choose a random logbook entry
randSent={}
randSent['entry']=LogbookEntry.objects.order_by('?')[0]
#Choose a random sentence from that entry. Store the sentence as randSent['sentence'], and the number of that sentence in the entry as randSent['number']
sentenceList=re.findall('[A-Z].*?\.',randSent['entry'].text)
randSent['number']=random.randrange(0,len(sentenceList))
randSent['sentence']=sentenceList[randSent['number']]
return randSent

View File

@ -3,6 +3,8 @@ from troggle.expo.models import Cave, Expedition, Person, LogbookEntry
import troggle.settings as settings import troggle.settings as settings
from django import forms from django import forms
from django.db.models import Q from django.db.models import Q
import re
import randSent
def stats(request): def stats(request):
statsDict={} statsDict={}
@ -10,4 +12,8 @@ def stats(request):
statsDict['caveCount'] = int(Cave.objects.count()) statsDict['caveCount'] = int(Cave.objects.count())
statsDict['personCount'] = int(Person.objects.count()) statsDict['personCount'] = int(Person.objects.count())
statsDict['logbookEntryCount'] = int(LogbookEntry.objects.count()) statsDict['logbookEntryCount'] = int(LogbookEntry.objects.count())
return render_to_response('statistics.html', statsDict) return render_to_response('statistics.html', statsDict)
def frontPage(request):
return render_to_response('index.html', {'randSent':randSent.randomLogbookSentence(),'settings':settings})

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

View File

@ -2,11 +2,18 @@
.centre { text-align: center; } .centre { text-align: center; }
.plus2pt { font-size: 160%; } .plus2pt { font-size: 160%; }
body, td, center, ul, p, input { color: #000; font-family: sans-serif; } body, td, center, ul, p, input {
color: rgb(204, 204, 102);
font-family: sans-serif;
}
body {
background-color: #000;
}
a:link, a:visited { text-decoration: none; } a:link, a:visited { text-decoration: none; }
div.centre img { vertical-align: middle; } div.centre img { vertical-align: middle; }
h1 { text-align: center; font-size: 210%; line-height: 100%; } h1 { text-align: center; font-size: 210%; opacity:0.7; filter:alpha(opacity=70);}
h2 { color: #009900; } h2 { color: #009900; }
h3 { color: #2c105e; } h3 { color: #2c105e; }
h4 { color: #0d664c; } h4 { color: #0d664c; }
@ -19,6 +26,23 @@ img.onleft, div.onleft { vertical-align: top; float: left;
margin-left: 8pt; } margin-left: 8pt; }
img.icon { vertical-align: middle; } img.icon { vertical-align: middle; }
img.aligntop { vertical-align: top; } img.aligntop { vertical-align: top; }
blockquote {
font: Georgia, "Times New Roman", Times, serif;
font-weight:bold;
font-variant:small-caps;
width: 400px;
background: url(../close-quote.gif) no-repeat right bottom;
padding-left: 25px;
text-indent: -25px;
text-align: right;
vertical-align:bottom;
color:#CCCC66;
}
blockquote:first-letter {
background: url(../open-quote.gif) no-repeat left top;
padding-left: 40px;
font: italic 1.4em Georgia, "Times New Roman", Times, serif;
}
table.imgtable { margin-left: auto; margin-right: auto; } table.imgtable { margin-left: auto; margin-right: auto; }
table.imgtable td { vertical-align: middle; text-align: center; table.imgtable td { vertical-align: middle; text-align: center;
padding: 10px; } padding: 10px; }
@ -38,6 +62,7 @@ table.trad td, table.trad th { margin: 0pt; border: 1px solid #aaa;
html, body, div.contents { html, body, div.contents {
min-height: 100%; min-height: 100%;
height: 100%; height: 100%;
width:100%;
} }
html>body, html>body div.contents { html>body, html>body div.contents {
height: auto; height: auto;
@ -47,12 +72,12 @@ body {
div.contents { div.contents {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; right: 0;
} }
div.footer { div.footer {
position: fixed; position: fixed;
bottom: 2px; bottom: 2px;
right: 2px; left: 2px;
} }
div.main { div.main {
margin-bottom: 3em; margin-bottom: 3em;

46
media/js/base.js Normal file
View File

@ -0,0 +1,46 @@
function showDiv(collapsed,expanded){
document.getElementById(collapsed).style.display = 'none';
document.getElementById(expanded).style.display = 'block';
}
function hideDiv(collapsed,expanded){
document.getElementById(collapsed).style.display = 'block';
document.getElementById(expanded).style.display = 'none';
}
function makeDivTransparent(div){
document.getElementById(div).style.backgroundColor = 'transparent';
}
hex=0 // Initial color value.
leftPos=25
year=1976
currentDate= new Date()
currentYear = currentDate.getFullYear()
function fadeText(){
if(hex<153) { //If color is not black yet
hex=hex+10; // increase color darkness
leftPos-=1;
document.getElementById("expoHeader").style.color="rgb("+0+","+hex+","+0+")";
// document.getElementById("expoFinalDate").style.color="rgb("+0+","+hex+","+0+")";
document.getElementById("expoHeader").style.left=leftPos;
setTimeout("fadeText()",50)
setTimeout("countUpYear()",1000)
}
else {
hex=0;
leftPos=25;
}
}
function countUpYear(){
if (year<currentYear) {
// alert (year+''+currentYear)
year=year+1
document.getElementById("expoFinalDate").innerHTML="<h1>"+year+"</h1>"
setTimeout("countUpYear()",1000)
}
}

BIN
media/loserBanner.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 KiB

BIN
media/open-quote.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 B

View File

@ -8,29 +8,56 @@ import re
QM.objects.all().delete() QM.objects.all().delete()
def parseCaveQMs(cave,pathToCSV):
if cave=='stein':
def parseSteinbrQMs(): try:
try: steinBr=Cave.objects.get(official_name="Steinbr&uuml;ckenh&ouml;hle")
steinBr=Cave.objects.get(official_name="Steinbr&uuml;ckenh&ouml;hle") except Cave.DoesNotExist:
except Cave.DoesNotExist: print "Steinbruckenhoehle is not in the database. Please run parsers.cavetab first."
print "Steinbruckenhoehle is not in the database. Please run parsers.cavetab first." return
return elif cave=='hauch':
try:
hauchHl=Cave.objects.get(official_name="Hauchh&ouml;hle")
except Cave.DoesNotExist:
print "Steinbruckenhoehle is not in the database. Please run parsers.cavetab first."
return
qmPath = settings.EXPOWEB+r"smkridge/204/qm.csv" qmPath = settings.EXPOWEB+pathToCSV
qmReader = csv.reader(open(qmPath,'r'),dialect="excel-tab") qmCSVContents = open(qmPath,'r')
dialect=csv.Sniffer().sniff(qmCSVContents.read())
qmCSVContents.seek(0,0)
qmReader = csv.reader(qmCSVContents,dialect=dialect)
qmReader.next() # Skip header row qmReader.next() # Skip header row
for line in qmReader: for line in qmReader:
year=int(line[0][1:5]) try:
year=int(line[0][1:5])
#check if placeholder exists for given year, create it if not
if cave=='stein':
placeholder, hadToCreate = LogbookEntry.objects.get_or_create(date__year=year, text="placeholder for QMs in 204", defaults={"date": date(year, 1, 1),"cave":steinBr})
elif cave=='hauch':
placeholder, hadToCreate = LogbookEntry.objects.get_or_create(date__year=year, text="placeholder for QMs in 234", defaults={"date": date(year, 1, 1),"cave":hauchHl})
if hadToCreate:
print cave+" placeholder logbook entry for " + str(year) + " added to database"
QMnum=re.match(r".*?-\d*?-X?(?P<numb>\d*)",line[0]).group("numb")
newQM = QM()
newQM.found_by=placeholder
newQM.number=QMnum
if line[1]=="Dig":
newQM.grade="D"
else:
newQM.grade=line[1]
newQM.area=line[2]
newQM.location_description=line[3]
newQM.nearest_station_description=line[4]
newQM.completion_description=line[5]
newQM.comment=line[6]
newQM.save()
print "QM "+str(newQM) + " added to database"
except KeyError:
continue
# except IndexError:
# print "Index error in " + str(line)
# continue
#check if placeholder exists for given year, create it if not parseCaveQMs(cave='stein',pathToCSV=r"smkridge/204/qm.csv")
placeholder, hadToCreate = LogbookEntry.objects.get_or_create(date__year=year, text="placeholder for QMs in 204", defaults={"date": date(year, 1, 1),"cave":steinBr}) parseCaveQMs(cave='hauch',pathToCSV=r"smkridge/234/qm.csv")
if hadToCreate:
print "204 placeholder logbook entry for " + str(year) + " added to database"
QMnum=re.match(r".*?-\d*?-X?(?P<numb>\d*)",line[0]).group("numb")
newQM = QM(found_by=placeholder,number=QMnum,grade=line[1],area=line[2],location_description=line[3],nearest_station_description=line[4],completion_description=line[5],comment=line[6])
newQM.save()
print "QM "+str(newQM) + " added to database"
parseSteinbrQMs()

View File

@ -45,10 +45,37 @@ def LoadPersons():
pObject = models.Person(first_name = firstname, pObject = models.Person(first_name = firstname,
last_name = lastname, last_name = lastname,
is_vfho = person[header["VfHO member"]], is_vfho = person[header["VfHO member"]],
mug_shot = person[header["Mugshot"]]) )
pObject.save()
is_guest = person[header["Guest"]] == "1" # this is really a per-expo catagory; not a permanent state
is_guest = person[header["Guest"]] == "1" # this is really a per-expo catagory; not a permanent state
pObject.save()
#create mugshot Photo instance
mugShotPath = settings.EXPOWEB+"folk/"+person[header["Mugshot"]]
if mugShotPath[-3:]=='jpg': #if person just has an image, add it
mugShotObj = models.Photo(
caption="Mugshot for "+firstname+" "+lastname,
is_mugshot=True,
file=mugShotPath,
)
mugShotObj.save()
mugShotObj.contains_person.add(pObject)
mugShotObj.save()
elif mugShotPath[-3:]=='htm': #if person has an html page, find the image(s) and add it. Also, add the text from the html page to the "blurb" field in his model instance.
personPageOld=open(mugShotPath,'r').read()
pObject.blurb=re.search('<body>.*<hr',personPageOld,re.DOTALL).group() #this needs to be refined, take care of the HTML and make sure it doesn't match beyond the blurb
for photoFilename in re.findall('i/.*?jpg',personPageOld,re.DOTALL):
mugShotPath=settings.EXPOWEB+"folk/"+photoFilename
mugShotObj = models.Photo(
caption="Mugshot for "+firstname+" "+lastname,
is_mugshot=True,
file=mugShotPath,
)
mugShotObj.save()
mugShotObj.contains_person.add(pObject)
mugShotObj.save()
pObject.save()
for year, attended in zip(headers, person)[5:]: for year, attended in zip(headers, person)[5:]:
yo = models.Expedition.objects.filter(year = year)[0] yo = models.Expedition.objects.filter(year = year)[0]
if attended == "1" or attended == "-1": if attended == "1" or attended == "-1":

View File

@ -1,68 +1,60 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en"> <html lang="en">
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" type="text/css" href="{{ settings.MEDIA_URL }}css/main2.css" /> <link rel="stylesheet" type="text/css" href="{{ settings.MEDIA_URL }}css/main2.css" />
<title>{% block title %}{% endblock %}</title> <title>{% block title %}{% endblock %}</title>
<!-- script to toggle navbar --> <!-- script to toggle navbar -->
<script src="{{ settings.MEDIA_URL }}js/base.js" type="text/javascript"></script>
<script language="javascript">
<!--
function showFooter(){
document.getElementById('footerHidden').style.display = 'none';
document.getElementById('footerShowing').style.display = 'block';
}
function hideFooter(){
document.getElementById('footerHidden').style.display = 'block';
document.getElementById('footerShowing').style.display = 'none';
}
function makeTransparent(){
document.getElementById('footerShowing').style.backgroundColor = 'transparent';
}
-->
</script>
</head> </head>
<body> <body>
<div id="editLink" style="right:0px; top:0px; text-align: right; position: absolute; top:0; right:0; z-index:1">
{% block editLink %}not editable
{% endblock %}
</div>
<div id="bottomRight" style="position:absolute;right:0;bottom:0">
<img src="{{ settings.MEDIA_URL }}SilkRoadsilouetteAndrew.png" id="bridge" style="position:absolute; right:60px; bottom:0;z-index:-1;">
{% block lgbkQuote %}{% endblock %}
</div>
<div id="headerBackBar" style="background-color:#CCCC66; position:absolute; left:0; right:0; z-index:-2; top:60px; opacity:0.7; filter:alpha(opacity=70);height:75px; color:#000000; text-indent:100px">
<p>
<br>
{% block currentLocation %}
Welcome to the website of the Cambridge University Caving Club's expeditions to Austria.
{% endblock %}
</p>
</div>
<div class="contents"> <div class="contents">
<div class="main"> <div class="main"> {% block content %}{% endblock %} </div>
{% block content %}{% endblock %} {% block footer %}
<div class="footer" id="footerHidden">
<h4><a href="javascript:;" onMouseDown="showDiv('footerHidden','footerShowing');">[Show Troggle Navigation / Search]</a></h4>
</div> </div>
{% block footer %} <div class="footer" id="footerShowing" style="background-color:#CCC; display:none">
<h4 class="navbar"> Troggle navigation <a href="javascript:;" onMouseDown="hideDiv('footerHidden','footerShowing');">[Hide]</a> or <a href="javascript:;" onMouseDown="makeDivTransparent('footerShowing');">[Make transparent]</a>
<div class="footer" id="footerHidden" style="display:none"> </align>
<h4><a href="javascript:;" onMouseDown="showFooter();">[Show Troggle Navigation / Search]</a></h4> </h4>
</div> <table class="normal">
<tr>
<div class="footer" id="footerShowing" style="background-color:#CCC"> <td rowspan="2"><a href="{{ settings.URL_ROOT }}cave">list caves</a> or
<h4 class="navbar"> Troggle navigation <a href="javascript:;" onMouseDown="hideFooter();">[Hide]</a> or <a href="javascript:;" onMouseDown="makeTransparent();">[Make transparent]</a></align></h4> <form name="input" action="{{ settings.URL_ROOT }}cavesearch" method="get">
<table class="normal"> <input type="text" name="q" value="search caves">
<tr> <input type="submit" value="Submit">
<td rowspan="2"> </form></td>
<a href="{{ settings.URL_ROOT }}cave">list caves</a> or <td rowspan="2"><a href="{{ settings.URL_ROOT }}logbookentry">list logbook entries</a> or
<form name="input" action="{{ settings.URL_ROOT }}cavesearch" method="get"> <form name="input" action="{{ settings.URL_ROOT }}logbooksearch" method="get">
<input type="text" name="q" value="search caves"> <input type="text" name="q" value="search logbooks">
<input type="submit" value="Submit"> <input type="submit" value="Submit">
</form> </form></td>
</td> <td><a href="{{ settings.URL_ROOT }}person">list cavers</a></td>
<td rowspan="2"> <td><a href="{{ settings.URL_ROOT }}statistics"> statistics</a></td>
<a href="{{ settings.URL_ROOT }}logbookentry">list logbook entries</a> or <tr>
<form name="input" action="{{ settings.URL_ROOT }}logbooksearch" method="get">
<input type="text" name="q" value="search logbooks">
<input type="submit" value="Submit">
</form>
</td>
<td><a href="{{ settings.URL_ROOT }}person">list cavers</a></td>
<td><a href="{{ settings.URL_ROOT }}statistics"> statistics</a></td>
<tr>
<td><a href="{{ settings.URL_ROOT }}photos">photos</a></td> <td><a href="{{ settings.URL_ROOT }}photos">photos</a></td>
<td><a href="{{ settings.URL_ROOT }}admin"> admin</a></td> <td><a href="{{ settings.URL_ROOT }}admin"> admin</a></td>
</table> </table>
</div> </div>
<p>{% endblock %}</p> <p>{% endblock %}</p>
</body>
</body>
</html> </html>

View File

@ -2,7 +2,7 @@
{% load wiki_markup %} {% load wiki_markup %}
{% block title %}Logbook {{logbookentry.id}}{% endblock %} {% block title %}Logbook {{logbookentry.id}}{% endblock %}
{% block editLink %}<a href="{{settings.URL_ROOT}}admin/expo/logbookentry/{{logbookentry.id}}">edit </a>{% endblock %}
{% block content %} {% block content %}
<div class="logbookblock"> <div class="logbookblock">
<h2>{{logbookentry.title}} - {{logbookentry.date}}</h2> <h2>{{logbookentry.title}} - {{logbookentry.date}}</h2>
@ -11,6 +11,7 @@
{% for persontrip in logbookentry.persontrip_set.all %} {% for persontrip in logbookentry.persontrip_set.all %}
<li> <li>
<a href="/person/{{persontrip.personexpedition.person.id}}">{{persontrip.personexpedition}}</a> <a href="/person/{{persontrip.personexpedition.person.id}}">{{persontrip.personexpedition}}</a>
<a href="{{settings.URL_ROOT}}admin/expo/logbookentry/{{logbookentry.id}}">edit </a>
{% ifequal persontrip.personexpedition logbookentry.author %} {% ifequal persontrip.personexpedition logbookentry.author %}
(author) (author)
{% endifequal %} {% endifequal %}

View File

@ -6,6 +6,7 @@ admin.autodiscover()
urlpatterns = patterns('', urlpatterns = patterns('',
# Example: # Example:
(r'^$', frontPage),
(r'^cave/?$', caveindex), (r'^cave/?$', caveindex),
(r'^cave/(?P<cave_id>[^/]+)/?$', cave), (r'^cave/(?P<cave_id>[^/]+)/?$', cave),
(r'^cave/(?P<cave_id>[^/]+)/?(?P<ent_letter>[^/])$', ent), (r'^cave/(?P<cave_id>[^/]+)/?(?P<ent_letter>[^/])$', ent),