2
0
mirror of https://expo.survex.com/repositories/troggle/.git synced 2026-02-08 11:49:50 +00:00

[svn] Renaming troggle.expo to troggle.core. To do this, used:

perl -p -i -e "s/expo(?=[\s\.']+)/core/g" `find -name \*.py`

and then manually checked each change (had to remove a couple)
This commit is contained in:
substantialnoninfringinguser
2009-07-02 20:43:18 +01:00
parent c0b274767b
commit ae3fe8cd42
32 changed files with 32 additions and 37 deletions

0
core/__init__.py Normal file
View File

129
core/admin.py Normal file
View File

@@ -0,0 +1,129 @@
from troggle.core.models import *
from django.contrib import admin
from feincms.admin import editor
from django.forms import ModelForm
import django.forms as forms
from core.forms import LogbookEntryForm
from django.http import HttpResponse
from django.core import serializers
from core.views_other import downloadLogbook
#from troggle.reversion.admin import VersionAdmin #django-reversion version control
#overriding admin save so we have the new since parsing field
class TroggleModelAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
obj.new_since_parsing=True
obj.save()
class RoleInline(admin.TabularInline):
model = PersonRole
extra = 4
class SurvexBlockAdmin(TroggleModelAdmin):
inlines = (RoleInline,)
class ScannedImageInline(admin.TabularInline):
model = ScannedImage
extra = 4
class SurveyAdmin(TroggleModelAdmin):
inlines = (ScannedImageInline,)
search_fields = ('expedition__year','wallet_number')
class QMsFoundInline(admin.TabularInline):
model=QM
fk_name='found_by'
class PhotoInline(admin.TabularInline):
model = Photo
exclude = ['is_mugshot' ]
extra = 1
class PersonTripInline(admin.TabularInline):
model = PersonTrip
exclude = ['persontrip_next','Delete']
extra = 1
#class LogbookEntryAdmin(VersionAdmin):
class LogbookEntryAdmin(TroggleModelAdmin):
prepopulated_fields = {'slug':("title",)}
search_fields = ('title','expedition__year')
date_heirarchy = ('date')
inlines = (PersonTripInline, PhotoInline, QMsFoundInline)
form = LogbookEntryForm
actions=('export_logbook_entries_as_html','export_logbook_entries_as_txt')
def export_logbook_entries_as_html(modeladmin, request, queryset):
response=downloadLogbook(request=request, queryset=queryset, extension='html')
return response
def export_logbook_entries_as_txt(modeladmin, request, queryset):
response=downloadLogbook(request=request, queryset=queryset, extension='txt')
return response
class PersonExpeditionInline(admin.TabularInline):
model = PersonExpedition
extra = 1
class PersonAdmin(TroggleModelAdmin):
search_fields = ('first_name','last_name')
inlines = (PersonExpeditionInline,)
class QMAdmin(TroggleModelAdmin):
search_fields = ('found_by__cave__kataster_number','number','found_by__date')
list_display = ('__unicode__','grade','found_by','ticked_off_by')
list_display_links = ('__unicode__',)
list_editable = ('found_by','ticked_off_by','grade')
list_per_page = 20
class PersonExpeditionAdmin(TroggleModelAdmin):
search_fields = ('person__first_name','expedition__year')
class CaveAdmin(TroggleModelAdmin):
search_fields = ('official_name','kataster_number','unofficial_number')
#inlines = (QMInline,)
extra = 4
class SubcaveAdmin(editor.TreeEditorMixin,TroggleModelAdmin):
pass
admin.site.register(Photo)
admin.site.register(Subcave, SubcaveAdmin)
admin.site.register(Cave, CaveAdmin)
admin.site.register(Area)
admin.site.register(OtherCaveName)
admin.site.register(CaveAndEntrance)
admin.site.register(SurveyStation)
admin.site.register(Entrance)
admin.site.register(SurvexBlock, SurvexBlockAdmin)
admin.site.register(Expedition)
admin.site.register(Person,PersonAdmin)
admin.site.register(PersonRole)
admin.site.register(PersonExpedition,PersonExpeditionAdmin)
admin.site.register(Role)
admin.site.register(LogbookEntry, LogbookEntryAdmin)
#admin.site.register(PersonTrip)
admin.site.register(QM, QMAdmin)
admin.site.register(Survey, SurveyAdmin)
admin.site.register(ScannedImage)
def export_as_json(modeladmin, request, queryset):
response = HttpResponse(mimetype="text/json")
response['Content-Disposition'] = 'attachment; filename=troggle_output.json'
serializers.serialize("json", queryset, stream=response)
return response
def export_as_xml(modeladmin, request, queryset):
response = HttpResponse(mimetype="text/xml")
response['Content-Disposition'] = 'attachment; filename=troggle_output.xml'
serializers.serialize("xml", queryset, stream=response)
return response
admin.site.add_action(export_as_xml)
admin.site.add_action(export_as_json)
try:
mptt.register(Subcave, order_insertion_by=['name'])
except mptt.AlreadyRegistered:
print "mptt already registered"

5
core/context.py Normal file
View File

@@ -0,0 +1,5 @@
from django.conf import settings
from core.models import Expedition
def troggle_context(request):
return { 'settings':settings, 'Expedition':Expedition }

43
core/fileAbstraction.py Normal file
View File

@@ -0,0 +1,43 @@
import troggle.settings as settings
import os
import urllib
def urljoin(x, y): return x + "/" + y
def listdir(*path):
try:
strippedpath = [p for p in path if p]
root = os.path.join(settings.FILES, *strippedpath )
l = ""
#l = root + "\n"
isdir = os.path.isdir(root) #This seems to be required for os.path.isdir to work...
#l += str(isdir) + "\n"
for p in os.listdir(root):
if os.path.isdir(os.path.join(root, p)):
l += p + "/\n"
elif os.path.isfile(os.path.join(root, p)):
l += p + "\n"
#Ignore non-files and non-directories
return l
except:
if strippedpath:
c = reduce(urljoin, strippedpath)
else:
c = ""
c = c.replace("#", "%23")
print "FILE: ", settings.FILES + "listdir/" + c
return urllib.urlopen(settings.FILES + "listdir/" + c).read()
def dirsAsList(*path):
return [d for d in listdir(*path).split("\n") if len(d) > 0 and d[-1] == "/"]
def filesAsList(*path):
return [d for d in listdir(*path).split("\n") if len(d) > 0 and d[-1] != "/"]
def readFile(*path):
try:
f = open(os.path.join(settings.FILES, *path))
except:
f = urllib.urlopen(settings.FILES + "download/" + reduce(urljoin, path))
return f.read()

48
core/forms.py Normal file
View File

@@ -0,0 +1,48 @@
from django.forms import ModelForm
from models import Cave, Person, LogbookEntry, QM
import django.forms as forms
from django.forms.formsets import formset_factory
from django.contrib.admin.widgets import AdminDateWidget
import string
from datetime import date
class CaveForm(ModelForm):
class Meta:
model = Cave
class PersonForm(ModelForm):
class Meta:
model = Person
class LogbookEntryForm(ModelForm):
class Meta:
model = LogbookEntry
def wikiLinkHints(LogbookEntry=None):
"""
This function returns html-formatted paragraphs for each of the
wikilink types that are related to this logbookentry. Each paragraph
contains a list of all of the related wikilinks.
Perhaps an admin javascript solution would be better.
"""
res = ["Please use the following wikilinks, which are related to this logbook entry:"]
res.append(r'</p><p style="float: left;"><b>QMs found:</b>')
for QM in LogbookEntry.instance.QMs_found.all():
res.append(QM.wiki_link())
res.append(r'</p><p style="float: left;"><b>QMs ticked off:</b>')
for QM in LogbookEntry.instance.QMs_ticked_off.all():
res.append(QM.wiki_link())
# res.append(r'</p><p style="float: left; "><b>People</b>')
# for persontrip in LogbookEntry.instance.persontrip_set.all():
# res.append(persontrip.wiki_link())
# res.append(r'</p>')
return string.join(res, r'<br />')
def __init__(self, *args, **kwargs):
super(LogbookEntryForm, self).__init__(*args, **kwargs)
self.fields['text'].help_text=self.wikiLinkHints()

22
core/imagekit_specs.py Normal file
View File

@@ -0,0 +1,22 @@
from imagekit.specs import ImageSpec
from imagekit import processors
class ResizeThumb(processors.Resize):
width = 100
crop = False
class ResizeDisplay(processors.Resize):
width = 600
#class EnhanceThumb(processors.Adjustment):
#contrast = 1.2
#sharpness = 2
class Thumbnail(ImageSpec):
access_as = 'thumbnail_image'
pre_cache = True
processors = [ResizeThumb]
class Display(ImageSpec):
increment_count = True
processors = [ResizeDisplay]

665
core/models.py Normal file
View File

@@ -0,0 +1,665 @@
import urllib, urlparse, string, os, datetime, logging
import troggle.mptt as mptt
from django.forms import ModelForm
from django.db import models
from django.contrib import admin
from django.core.files.storage import FileSystemStorage
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.conf import settings
from decimal import Decimal, getcontext
from django.core.urlresolvers import reverse
from imagekit.models import ImageModel
getcontext().prec=2 #use 2 significant figures for decimal calculations
from models_survex import *
logging.basicConfig(level=logging.DEBUG,
filename=settings.LOGFILE,
filemode='w')
#This class is for adding fields and methods which all of our models will have.
class TroggleModel(models.Model):
new_since_parsing = models.BooleanField(default=False, editable=False)
non_public = models.BooleanField(default=False)
def object_name(self):
return self._meta.object_name
def get_admin_url(self):
return urlparse.urljoin(settings.URL_ROOT, "/admin/expo/" + self.object_name().lower() + "/" + str(self.pk))
class Meta:
abstract = True
class TroggleImageModel(ImageModel):
new_since_parsing = models.BooleanField(default=False, editable=False)
def object_name(self):
return self._meta.object_name
def get_admin_url(self):
return urlparse.urljoin(settings.URL_ROOT, "/admin/expo/" + self.object_name().lower() + "/" + str(self.pk))
class Meta:
abstract = True
class Expedition(TroggleModel):
year = models.CharField(max_length=20, unique=True)
name = models.CharField(max_length=100)
date_from = models.DateField(blank=True,null=True)
date_to = models.DateField(blank=True,null=True)
def __unicode__(self):
return self.year
class Meta:
ordering = ('-year',)
get_latest_by = 'date_from'
def get_absolute_url(self):
#return settings.URL_ROOT + "/expedition/%s" % self.year
return urlparse.urljoin(settings.URL_ROOT, reverse('expedition',args=[self.year]))
# lose these two functions (inelegant, and we may create a file with the dates that we can load from)
def GuessDateFrom(self):
try:
return self.logbookentry_set.order_by('date')[0].date
except IndexError:
pass
def GuessDateTo(self): # returns the date of the last logbook entry in the expedition
try:
return self.logbookentry_set.order_by('date')[-1].date
except IndexError:
pass
def ListDays(self):
if self.date_from and self.date_to:
res=[]
date=self.date_from
while date <= self.date_to:
res.append(date)
date+=datetime.timedelta(days=1)
return res
elif self.GuessDateFrom() and self.GuessDateTo(): # if we don't have the real dates, try it with the dates taken from the earliest and latest logbook entries
date=self.GuessDateFrom()
while date <= self.GuessDateTo():
res.append(date)
date+=datetime.timedelta(days=1)
return res
class Person(TroggleModel):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
is_vfho = models.BooleanField(help_text="VFHO is the Vereines f&uuml;r H&ouml;hlenkunde in Obersteier, a nearby Austrian caving club.")
mug_shot = models.CharField(max_length=100, blank=True,null=True)
blurb = models.TextField(blank=True,null=True)
#href = models.CharField(max_length=200)
orderref = models.CharField(max_length=200) # for alphabetic
#the below have been removed and made methods. I'm not sure what the b in bisnotable stands for. - AC 16 Feb
#notability = models.FloatField() # for listing the top 20 people
#bisnotable = models.BooleanField()
user = models.OneToOneField(User, null=True, blank=True)
def get_absolute_url(self):
return urlparse.urljoin(settings.URL_ROOT,reverse('person',kwargs={'first_name':self.first_name,'last_name':self.last_name}))
class Meta:
verbose_name_plural = "People"
class Meta:
ordering = ('orderref',) # "Wookey" makes too complex for: ('last_name', 'first_name')
def __unicode__(self):
if self.last_name:
return "%s %s" % (self.first_name, self.last_name)
return self.first_name
# Below are no longer needed. Use {{ person.personexpedition_set.all.0.expedition }} for Firstexpedition, and {{ person.personexpedition_set.latest.expedition }} for Lastexpedition
# these ought to be possible by piping through |min in the template, or getting the first of an ordered list
# def Firstexpedition(self):
# return self.personexpedition_set.order_by('expedition')[0]
# def Lastexpedition(self):
# return self.personexpedition_set.order_by('-expedition')[0]
def notability(self):
notability = Decimal(0)
for personexpedition in self.personexpedition_set.all():
if not personexpedition.is_guest:
notability += Decimal(1) / (2012 - int(personexpedition.expedition.year))
return notability
def bisnotable(self):
return self.notability() > Decimal(1)/Decimal(3)
#def Sethref(self):
#if self.last_name:
#self.href = self.first_name.lower() + "_" + self.last_name.lower()
#self.orderref = self.last_name + " " + self.first_name
#else:
# self.href = self.first_name.lower()
#self.orderref = self.first_name
#self.notability = 0.0 # set temporarily
class PersonExpedition(TroggleModel):
expedition = models.ForeignKey(Expedition)
person = models.ForeignKey(Person)
date_from = models.DateField(blank=True,null=True)
date_to = models.DateField(blank=True,null=True)
is_guest = models.BooleanField(default=False)
COMMITTEE_CHOICES = (
('leader','Expo leader'),
('medical','Expo medical officer'),
('treasurer','Expo treasurer'),
('sponsorship','Expo sponsorship coordinator'),
('research','Expo research coordinator'),
)
expo_committee_position = models.CharField(blank=True,null=True,choices=COMMITTEE_CHOICES,max_length=200)
nickname = models.CharField(max_length=100,blank=True,null=True)
def GetPersonroles(self):
res = [ ]
for personrole in self.personrole_set.order_by('survex_block'):
if res and res[-1]['survexpath'] == personrole.survex_block.survexpath:
res[-1]['roles'] += ", " + str(personrole.role)
else:
res.append({'date':personrole.survex_block.date, 'survexpath':personrole.survex_block.survexpath, 'roles':str(personrole.role)})
return res
class Meta:
ordering = ('expedition',)
#order_with_respect_to = 'expedition'
get_latest_by = 'expedition'
def GetPersonChronology(self):
res = { }
for persontrip in self.persontrip_set.all():
a = res.setdefault(persontrip.date, { })
a.setdefault("persontrips", [ ]).append(persontrip)
for personrole in self.personrole_set.all():
a = res.setdefault(personrole.survex_block.date, { })
b = a.setdefault("personroles", { })
survexpath = personrole.survex_block.survexpath
if b.get(survexpath):
b[survexpath] += ", " + str(personrole.role)
else:
b[survexpath] = str(personrole.role)
# needs converting dict into list
return sorted(res.items())
# possibly not useful functions anyway -JT
# if you can find a better way to make the expo calendar table, be my guest. It isn't possible to do this logic in a django template without writing custom tags.-AC
def ListDays(self):
"""
Returns a list of the days the person was on the expedition (i.e. the days that the PersonExpedition was in existance). Needed for expedition calendar.
"""
if self.date_from and self.date_to:
res=[]
date=self.date_from
while date <= self.date_to:
res.append(date)
date+=datetime.timedelta(days=1)
return res
def ListDaysTF(self):
"""
Returns a list of true / false values. Each value corresponds to one day on the expedition; True means the person was there, False means they weren't.
"""
if self.date_from and self.date_to:
res=[]
for date in self.expedition.ListDays():
res.append(date in self.ListDays())
return res
def __unicode__(self):
return "%s: (%s)" % (self.person, self.expedition)
#why is the below a function in personexpedition, rather than in person? - AC 14 Feb 09
def name(self):
if self.nickname:
return "%s (%s) %s" % (self.person.first_name, self.nickname, self.person.last_name)
if self.person.last_name:
return "%s %s" % (self.person.first_name, self.person.last_name)
return self.person.first_name
def get_absolute_url(self):
#return settings.URL_ROOT + '/personexpedition/' + str(self.person.first_name) + '_' + str(self.person.last_name) + '/' +self.expedition.year
return urlparse.urljoin(settings.URL_ROOT, reverse('personexpedition',kwargs={'first_name':self.person.first_name,'last_name':self.person.last_name,'year':self.expedition.year}))
class LogbookEntry(TroggleModel):
date = models.DateField()
expedition = models.ForeignKey(Expedition,blank=True,null=True) # yes this is double-
author = models.ForeignKey(PersonExpedition,blank=True,null=True) # the person who writes it up doesn't have to have been on the trip.
# Re: the above- so this field should be "typist" or something, not "author". - AC 15 jun 09
title = models.CharField(max_length=200)
cave = models.ForeignKey('Cave',blank=True,null=True)
place = models.CharField(max_length=100,blank=True,null=True,help_text="Only use this if you haven't chosen a cave")
text = models.TextField()
slug = models.SlugField(max_length=50)
#href = models.CharField(max_length=100)
#logbookentry_next = models.ForeignKey('LogbookEntry', related_name='pnext', blank=True,null=True)
#logbookentry_prev = models.ForeignKey('LogbookEntry', related_name='pprev', blank=True,null=True)
class Meta:
verbose_name_plural = "Logbook Entries"
# several PersonTrips point in to this object
class Meta:
ordering = ('-date',)
def get_absolute_url(self):
return urlparse.urljoin(settings.URL_ROOT, reverse('logbookentry',kwargs={'date':self.date,'slug':self.slug}))
def __unicode__(self):
return "%s: (%s)" % (self.date, self.title)
def get_next_by_id(self):
LogbookEntry.objects.get(id=self.id+1)
def get_previous_by_id(self):
LogbookEntry.objects.get(id=self.id-1)
class PersonTrip(TroggleModel):
person_expedition = models.ForeignKey(PersonExpedition,null=True)
# this will be a foreign key of the place(s) the trip went through
# possibly a trip has a plurality of triplets pointing into it
#place = models.CharField(max_length=100)
#date = models.DateField()
time_underground = models.FloatField(help_text="In decimal hours")
logbook_entry = models.ForeignKey(LogbookEntry)
is_logbook_entry_author = models.BooleanField()
def date(self):
return self.logbook_entry.date
def place(self):
if self.logbook_entry.cave:
return self.logbook_entry.cave
else:
return self.logbook_entry.place
#persontrip_next = models.ForeignKey('PersonTrip', related_name='pnext', blank=True,null=True)
#persontrip_prev = models.ForeignKey('PersonTrip', related_name='pprev', blank=True,null=True)
def __unicode__(self):
return "%s %s (%s)" % (self.person_expedition, self.place(), self.date())
def get_persons_next_trip(self):
try:
return PersonTrip.objects.filter(person_expedition__person=self.person_expedition.person, person_expedition__date__gt=self.date)[0]
except:
return
def get_persons_previous_trip(self):
try:
return PersonTrip.objects.filter(person_expedition__person=self.person_expedition.person, person_expedition__date__lt=self.date)[0]
except:
return
# def get_persons_previous_trip(self):
#
# move following classes into models_cave
#
class Area(TroggleModel):
short_name = models.CharField(max_length=100)
name = models.CharField(max_length=200, blank=True, null=True)
description = models.TextField(blank=True,null=True)
parent = models.ForeignKey('Area', blank=True, null=True)
def __unicode__(self):
if self.parent:
return unicode(self.parent) + u" - " + unicode(self.short_name)
else:
return unicode(self.short_name)
def kat_area(self):
if self.short_name in ["1623", "1626"]:
return self.short_name
elif self.parent:
return self.parent.kat_area()
class CaveAndEntrance(TroggleModel):
cave = models.ForeignKey('Cave')
entrance = models.ForeignKey('Entrance')
entrance_letter = models.CharField(max_length=20,blank=True,null=True)
def __unicode__(self):
return unicode(self.cave) + unicode(self.entrance_letter)
class Cave(TroggleModel):
# too much here perhaps
official_name = models.CharField(max_length=160)
area = models.ManyToManyField(Area, blank=True, null=True)
kataster_code = models.CharField(max_length=20,blank=True,null=True)
kataster_number = models.CharField(max_length=10,blank=True, null=True)
unofficial_number = models.CharField(max_length=60,blank=True, null=True)
entrances = models.ManyToManyField('Entrance', through='CaveAndEntrance')
explorers = models.TextField(blank=True,null=True)
underground_description = models.TextField(blank=True,null=True)
equipment = models.TextField(blank=True,null=True)
references = models.TextField(blank=True,null=True)
survey = models.TextField(blank=True,null=True)
kataster_status = models.TextField(blank=True,null=True)
underground_centre_line = models.TextField(blank=True,null=True)
notes = models.TextField(blank=True,null=True)
length = models.CharField(max_length=100,blank=True,null=True)
depth = models.CharField(max_length=100,blank=True,null=True)
extent = models.CharField(max_length=100,blank=True,null=True)
survex_file = models.CharField(max_length=100,blank=True,null=True)
description_file = models.CharField(max_length=200,blank=True,null=True)
#href = models.CharField(max_length=100)
def get_absolute_url(self):
if self.kataster_number:
href = self.kataster_number
elif self.unofficial_number:
href = self.unofficial_number
else:
href = official_name.lower()
#return settings.URL_ROOT + '/cave/' + href + '/'
return urlparse.urljoin(settings.URL_ROOT, reverse('cave',kwargs={'cave_id':href,}))
def __unicode__(self):
if self.kataster_number:
if self.kat_area():
return self.kat_area() + u": " + self.kataster_number
else:
return unicode("l") + u": " + self.kataster_number
else:
if self.kat_area():
return self.kat_area() + u": " + self.unofficial_number
else:
return self.unofficial_number
def get_QMs(self):
return QM.objects.filter(found_by__cave=self)
def kat_area(self):
for a in self.area.all():
if a.kat_area():
return a.kat_area()
def entrances(self):
return CaveAndEntrance.objects.filter(cave=self)
def entrancelist(self):
rs = []
res = ""
for e in CaveAndEntrance.objects.filter(cave=self):
rs.append(e.entrance_letter)
rs.sort()
prevR = None
n = 0
for r in rs:
if prevR:
if chr(ord(prevR) + 1 ) == r:
prevR = r
n += 1
else:
if n == 0:
res += ", " + prevR
else:
res += "&ndash;" + prevR
else:
prevR = r
n = 0
res += r
if n == 0:
res += ", " + prevR
else:
res += "&ndash;" + prevR
return res
def nextQMnumber(self, year=datetime.date.today().year):
"""
Given a cave and the current year, returns the next QM number.
"""
res=QM.objects.filter(found_by__date__year=year, found_by__cave=self).order_by('-number')[0]
return res.number+1
class OtherCaveName(TroggleModel):
name = models.CharField(max_length=160)
cave = models.ForeignKey(Cave)
def __unicode__(self):
return unicode(self.name)
class SurveyStation(TroggleModel):
name = models.CharField(max_length=200)
def __unicode__(self):
return unicode(self.name)
class Entrance(TroggleModel):
name = models.CharField(max_length=100, blank=True,null=True)
entrance_description = models.TextField(blank=True,null=True)
explorers = models.TextField(blank=True,null=True)
map_description = models.TextField(blank=True,null=True)
location_description = models.TextField(blank=True,null=True)
approach = models.TextField(blank=True,null=True)
underground_description = models.TextField(blank=True,null=True)
photo = models.TextField(blank=True,null=True)
MARKING_CHOICES = (
('P', 'Paint'),
('P?', 'Paint (?)'),
('T', 'Tag'),
('T?', 'Tag (?)'),
('R', 'Retagged'),
('S', 'Spit'),
('S?', 'Spit (?)'),
('U', 'Unmarked'),
('?', 'Unknown'))
marking = models.CharField(max_length=2, choices=MARKING_CHOICES)
marking_comment = models.TextField(blank=True,null=True)
FINDABLE_CHOICES = (
('?', 'To be confirmed ...'),
('S', 'Surveyed'),
('L', 'Lost'),
('R', 'Refindable'))
findability = models.CharField(max_length=1, choices=FINDABLE_CHOICES, blank=True, null=True)
findability_description = models.TextField(blank=True,null=True)
alt = models.TextField(blank=True, null=True)
northing = models.TextField(blank=True, null=True)
easting = models.TextField(blank=True, null=True)
tag_station = models.ForeignKey(SurveyStation, blank=True,null=True, related_name="tag_station")
exact_station = models.ForeignKey(SurveyStation, blank=True,null=True, related_name="exact_station")
other_station = models.ForeignKey(SurveyStation, blank=True,null=True, related_name="other_station")
other_description = models.TextField(blank=True,null=True)
bearings = models.TextField(blank=True,null=True)
def __unicode__(self):
a = CaveAndEntrance.objects.filter(entrance = self)
name = u''
if self.name:
name = unicode(self.name) + u' '
if len(a) == 1:
return name + unicode(a[0])
return name + unicode(a)
def marking_val(self):
for m in self.MARKING_CHOICES:
if m[0] == self.marking:
return m[1]
def findability_val(self):
for f in self.FINDABLE_CHOICES:
if f[0] == self.findability:
return f[1]
class Subcave(TroggleModel):
description = models.TextField(blank=True, null=True)
title = models.CharField(max_length=200, )
cave = models.ForeignKey('Cave', blank=True, null=True, help_text="Only the top-level subcave should be linked to a cave!")
parent = models.ForeignKey('self', null=True, blank=True, related_name='children')
#adjoining = models.ManyToManyField('Subcave',blank=True, null=True,)
legacy_description_path = models.CharField(max_length=600, blank=True, null=True)
def __unicode__(self):
return self.title
def get_absolute_url(self):
ancestor_titles='/'.join([subcave.title for subcave in self.get_ancestors()])
if ancestor_titles:
res = '/'.join((self.get_root().cave.get_absolute_url(), ancestor_titles, self.title))
else:
res = '/'.join((self.get_root().cave.get_absolute_url(), self.title))
return res
# This was the old way, before we were using django-mptt
# def get_absolute_url(self):
# urlString=self.name
# if self.parent:
# parent=self.parent
# while parent: #recursively walk up the tree, adding parents to the left of the URL
# urlString=parent.name+'/'+urlString
# if parent.cave:
# cave=parent.cave
# parent=parent.parent
# urlString='cave/'+unicode(cave.kataster_number)+'/'+urlString
# else:
# urlString='cave/'+unicode(self.cave.kataster_number)+'/'+urlString
# return urlparse.urljoin(settings.URL_ROOT, urlString)
try:
mptt.register(Subcave, order_insertion_by=['title'])
except mptt.AlreadyRegistered:
print "mptt already registered"
class QM(TroggleModel):
#based on qm.csv in trunk/expoweb/smkridge/204 which has the fields:
#"Number","Grade","Area","Description","Page reference","Nearest station","Completion description","Comment"
found_by = models.ForeignKey(LogbookEntry, related_name='QMs_found',blank=True, null=True )
ticked_off_by = models.ForeignKey(LogbookEntry, related_name='QMs_ticked_off',null=True,blank=True)
number = models.IntegerField(help_text="this is the sequential number in the year")
GRADE_CHOICES=(
('A', 'A: Large obvious lead'),
('B', 'B: Average lead'),
('C', 'C: Tight unpromising lead'),
('D', 'D: Dig'),
('X', 'X: Unclimbable aven')
)
grade = models.CharField(max_length=1, choices=GRADE_CHOICES)
location_description = models.TextField(blank=True)
#should be a foreignkey to surveystation
nearest_station_description = models.CharField(max_length=400,null=True,blank=True)
nearest_station = models.CharField(max_length=200,blank=True,null=True)
area = models.CharField(max_length=100,blank=True,null=True)
completion_description = models.TextField(blank=True,null=True)
comment=models.TextField(blank=True,null=True)
#the below are unneeded- instead use the date fields of the QM's trips
#dateFound = models.DateField(blank=True)
#dateKilled = models.DateField(blank=True)
def __unicode__(self):
QMnumber=str(self.found_by.cave)+'-'+str(self.found_by.date.year)+"-"+str(self.number)+self.grade
return str(QMnumber)
def get_absolute_url(self):
#return settings.URL_ROOT + '/cave/' + self.found_by.cave.kataster_number + '/' + str(self.found_by.date.year) + '-' + '%02d' %self.number
return urlparse.urljoin(settings.URL_ROOT, reverse('qm',kwargs={'cave_id':self.found_by.cave.kataster_number,'year':self.found_by.date.year,'qm_id':self.number,'grade':self.grade}))
def get_next_by_id(self):
return QM.objects.get(id=self.id+1)
def get_previous_by_id(self):
return QM.objects.get(id=self.id-1)
def wiki_link(self):
res = '[[cave:' + str(self.found_by.cave.kataster_number) + ' '
res += 'QM:' + str(self.found_by.date.year) + '-'
res += str(self.number) + self.grade + ']]'
return res
photoFileStorage = FileSystemStorage(location=settings.PHOTOS_ROOT, base_url=settings.PHOTOS_URL)
class Photo(TroggleImageModel):
caption = models.CharField(max_length=1000,blank=True,null=True)
contains_logbookentry = models.ForeignKey(LogbookEntry,blank=True,null=True)
contains_person = models.ManyToManyField(Person,blank=True,null=True)
file = models.ImageField(storage=photoFileStorage, upload_to='.',)
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)
class IKOptions:
spec_module = 'core.imagekit_specs'
cache_dir = 'thumbs'
image_field = 'file'
#content_type = models.ForeignKey(ContentType)
#object_id = models.PositiveIntegerField()
#location = generic.GenericForeignKey('content_type', 'object_id')
def __unicode__(self):
return self.caption
scansFileStorage = FileSystemStorage(location=settings.SURVEY_SCANS, base_url=settings.SURVEYS_URL)
def get_scan_path(instance, filename):
year=instance.survey.expedition.year
print "WN: ", type(instance.survey.wallet_number), instance.survey.wallet_number
number="%02d" % instance.survey.wallet_number + str(instance.survey.wallet_letter) #using %02d string formatting because convention was 2009#01
return os.path.join('./',year,year+r'#'+number,instance.contents+str(instance.number_in_wallet)+r'.jpg')
class ScannedImage(TroggleImageModel):
file = models.ImageField(storage=scansFileStorage, upload_to=get_scan_path)
scanned_by = models.ForeignKey(Person,blank=True, null=True)
scanned_on = models.DateField(null=True)
survey = models.ForeignKey('Survey')
contents = models.CharField(max_length=20,choices=(('notes','notes'),('plan','plan_sketch'),('elevation','elevation_sketch')))
number_in_wallet = models.IntegerField(null=True)
lon_utm = models.FloatField(blank=True,null=True)
lat_utm = models.FloatField(blank=True,null=True)
class IKOptions:
spec_module = 'core.imagekit_specs'
cache_dir = 'thumbs'
image_field = 'file'
#content_type = models.ForeignKey(ContentType)
#object_id = models.PositiveIntegerField()
#location = generic.GenericForeignKey('content_type', 'object_id')
#This is an ugly hack to deal with the #s in our survey scan paths. The correct thing is to write a custom file storage backend which calls urlencode on the name for making file.url but not file.path.
def correctURL(self):
return string.replace(self.file.url,r'#',r'%23')
def __unicode__(self):
return get_scan_path(self,'')
class Survey(TroggleModel):
expedition = models.ForeignKey('Expedition') #REDUNDANT (logbook_entry)
wallet_number = models.IntegerField(blank=True,null=True)
wallet_letter = models.CharField(max_length=1,blank=True,null=True)
comments = models.TextField(blank=True,null=True)
location = models.CharField(max_length=400,blank=True,null=True) #REDUNDANT
subcave = models.ForeignKey('Subcave', blank=True, null=True)
#notes_scan = models.ForeignKey('ScannedImage',related_name='notes_scan',blank=True, null=True) #Replaced by contents field of ScannedImage model
survex_block = models.OneToOneField('SurvexBlock',blank=True, null=True)
logbook_entry = models.ForeignKey('LogbookEntry')
centreline_printed_on = models.DateField(blank=True, null=True)
centreline_printed_by = models.ForeignKey('Person',related_name='centreline_printed_by',blank=True,null=True)
#sketch_scan = models.ForeignKey(ScannedImage,blank=True, null=True) #Replaced by contents field of ScannedImage model
tunnel_file = models.FileField(upload_to='surveyXMLfiles',blank=True, null=True)
tunnel_main_sketch = models.ForeignKey('Survey',blank=True,null=True)
integrated_into_main_sketch_on = models.DateField(blank=True,null=True)
integrated_into_main_sketch_by = models.ForeignKey('Person' ,related_name='integrated_into_main_sketch_by', blank=True,null=True)
rendered_image = models.ImageField(upload_to='renderedSurveys',blank=True,null=True)
def __unicode__(self):
return self.expedition.year+"#"+"%02d" % int(self.wallet_number)
def notes(self):
return self.scannedimage_set.filter(contents='notes')
def plans(self):
return self.scannedimage_set.filter(contents='plan')
def elevations(self):
return self.scannedimage_set.filter(contents='elevation')

66
core/models_survex.py Normal file
View File

@@ -0,0 +1,66 @@
from django.db import models
from django.conf import settings
import os
class SurvexBlock(models.Model):
name = models.CharField(max_length=100, blank=True, null=True)
parent = models.ForeignKey('SurvexBlock', blank=True, null=True)
text = models.TextField()
# non-useful representation of incomplete data
start_year = models.IntegerField(blank=True, null=True)
start_month = models.IntegerField(blank=True, null=True)
start_day = models.IntegerField(blank=True, null=True)
end_year = models.IntegerField(blank=True, null=True)
end_month = models.IntegerField(blank=True, null=True)
end_day = models.IntegerField(blank=True, null=True)
date = models.DateField(blank=True, null=True)
survexpath = models.CharField(max_length=100)
# superfluous
person = models.ManyToManyField('Person', through='PersonRole', blank=True, null=True)
# code for where in the survex data files this block sits
begin_file = models.CharField(max_length=200)
begin_char = models.IntegerField()
end_file = models.CharField(max_length=200, blank=True, null=True)
end_char = models.IntegerField(blank=True, null=True)
class Meta:
ordering = ('date', 'survexpath')
def __unicode__(self):
return unicode(self.name)
def filecontents(self):
f = os.path.join(settings.SURVEX_DATA, self.begin_file)
fin = open(f, "rb")
res = fin.read().decode("latin1")
fin.close()
return res
def GetPersonroles(self):
res = [ ]
for personrole in self.personrole_set.order_by('personexpedition'):
if res and res[-1]['person'] == personrole.personexpedition.person:
res[-1]['roles'] += ", " + str(personrole.role)
else:
res.append({'person':personrole.personexpedition.person, 'expeditionyear':personrole.personexpedition.expedition.year, 'roles':str(personrole.role)})
print res
return res
class PersonRole(models.Model):
personexpedition = models.ForeignKey('PersonExpedition')
person = models.ForeignKey('Person')
survex_block = models.ForeignKey('SurvexBlock')
role = models.ForeignKey('Role')
def __unicode__(self):
return unicode(self.person) + " - " + unicode(self.survex_block) + " - " + unicode(self.role)
class Role(models.Model):
name = models.CharField(max_length=50)
def __unicode__(self):
return unicode(self.name)

32
core/randSent.py Normal file
View File

@@ -0,0 +1,32 @@
import troggle.settings as settings
from django import forms
from troggle.core.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():
randSent={}
# needs to handle empty logbooks without crashing
#Choose a random logbook entry
randSent['entry']=LogbookEntry.objects.order_by('?')[0]
#Choose again if there are no sentances (this happens if it is a placeholder entry)
while len(re.findall('[A-Z].*?\.',randSent['entry'].text))==0:
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

39
core/search.py Normal file
View File

@@ -0,0 +1,39 @@
import re
from django.db.models import Q
# search script from http://www.julienphalip.com/blog/2008/08/16/adding-search-django-site-snap/
def normalize_query(query_string,
findterms=re.compile(r'"([^"]+)"|(\S+)').findall,
normspace=re.compile(r'\s{2,}').sub):
''' Splits the query string in invidual keywords, getting rid of unecessary spaces
and grouping quoted words together.
Example:
>>> normalize_query(' some random words "with quotes " and spaces')
['some', 'random', 'words', 'with quotes', 'and', 'spaces']
'''
return [normspace(' ', (t[0] or t[1]).strip()) for t in findterms(query_string)]
def get_query(query_string, search_fields):
''' Returns a query, that is a combination of Q objects. That combination
aims to search keywords within a model by testing the given search fields.
'''
query = None # Query to search for every search term
terms = normalize_query(query_string)
for term in terms:
or_query = None # Query to search for a given term in each field
for field_name in search_fields:
q = Q(**{"%s__icontains" % field_name: term})
if or_query is None:
or_query = q
else:
or_query = or_query | q
if query is None:
query = or_query
else:
query = query & or_query
return query

View File

View File

@@ -0,0 +1,8 @@
from django import template
from django.utils.safestring import mark_safe
register = template.Library()
@register.filter()
def link(value):
return mark_safe("<a href=\'%s\'>"%value.get_absolute_url()+unicode(value)+"</a>")

View File

@@ -0,0 +1,52 @@
from django import template
from django.utils.html import conditional_escape
from django.template.defaultfilters import stringfilter
from django.utils.safestring import mark_safe
import re
register = template.Library()
# seems to add extra lines between the commented lines, which isn't so great.
regexes = []
regexes.append((re.compile(r"(;.*)$", re.IGNORECASE|re.MULTILINE),
r'<span class = "comment">\1</span>\n'))
regexes.append((re.compile(r"^(\s*)(\*include)(\s+)([^\s]*)(.svx)$", re.IGNORECASE|re.MULTILINE),
r'\1<span class = "command">\2</span>\3<a href="\4.index">\4\5</a>'))
regexes.append((re.compile(r"^(\s*)(\*include)(\s+)([^\s]*)$", re.IGNORECASE|re.MULTILINE),
r'\1<span class = "command">\2</span>\3<a href="\4.index">\4</a>'))
regexes.append((re.compile(r"^(\s*)(\*team\s+(?:notes|tape|insts|pics))(\s+)(.*)$", re.IGNORECASE|re.MULTILINE),
r'\1<span class = "command">\2</span>\3\4'))
regexes.append((re.compile(r"^(\s*)(\*(?:begin|end|copyright|date|entrance|equate|export|fix|prefix|require|SOLVE|title|truncate))(\s+)(.*)$", re.IGNORECASE|re.MULTILINE),
r'\1<span class = "command">\2</span>\3\4'))
regexes.append((re.compile(r"^(\s*)(\*calibrate\s+(?:TAPE|COMPASS|CLINO|COUNTER|DEPTH|DECLINATION|X|Y|Z)+)(\s+)(.*)$", re.IGNORECASE|re.MULTILINE),
r'\1<span class = "command">\2</span>\3\4'))
regexes.append((re.compile(r"^(\s*)(\*data\s+(?:DEFAULT|NORMAL|DIVING|CARTESIAN|TOPOFIL|CYLPOLAR|NOSURVEY|passage)(?:\s+station|\s+from|\s+to|\s+FROMDEPTH|\s+TODEPTH|\s+DEPTHCHANGE|\s+newline|\s+direction|\s+tape|\s+compass|\s+clino|\s+northing|\s+easting|\s+altitude|\s+length|\s+bearing|\s+gradient|\s+ignoreall|\sleft|\sright|\sup|\sdown)*)$", re.IGNORECASE|re.MULTILINE),
r'\1<span class = "command">\2</span>'))
regexes.append((re.compile(r"^(\s*)(\*default\s+(?:CALIBRATE|DATA|UNITS)+)(\s+)(.*)$", re.IGNORECASE|re.MULTILINE),
r'\1<span class = "command">\2</span>\3\4'))
regexes.append((re.compile(r"^(\s*)(\*flags\s+(?:DUPLICATE|SPLAY|SURFACE|not DUPLICATE|not SPLAY|not SURFACE))(\s+)(.*)$", re.IGNORECASE|re.MULTILINE),
r'\1<span class = "command">\2</span>\3\4'))
regexes.append((re.compile(r"^(\s*)(\*infer\s+(?:plumbs|equates|exports))(\s+)(.*)$", re.IGNORECASE|re.MULTILINE),
r'\1<span class = "command">\2</span>\3\4'))
regexes.append((re.compile(r"^(\s*)(\*instrument\s+(?:compass|clino|tape))(\s+)(.*)$", re.IGNORECASE|re.MULTILINE),
r'\1<span class = "command">\2</span>\3\4'))
regexes.append((re.compile(r"^(\s*)(\*instrument\s+(?:compass|clino|tape))(\s+)(.*)$", re.IGNORECASE|re.MULTILINE),
r'\1<span class = "command">\2</span>\3\4'))
regexes.append((re.compile(r"^(\s*)(\*sd\s+(?:TAPE|COMPASS|CLINO|COUNTER|DEPTH|DECLINATION|DX|DY|DZ))(\s+)(.*)$", re.IGNORECASE|re.MULTILINE),
r'\1<span class = "command">\2</span>\3\4'))
regexes.append((re.compile(r"^(\s*)(\*set\s+(?:BLANK|COMMENT|DECIMAL|EOL|KEYWORD|MINUS|NAMES|OMIT|PLUS|ROOT|SEPARATOR))(\s+)(.*)$", re.IGNORECASE|re.MULTILINE),
r'\1<span class = "command">\2</span>\3\4'))
regexes.append((re.compile(r"^(\s*)(\*units\s+(?:TAPE|LENGTH|COMPASS|BEARING|CLINO|GRADIENT|COUNTER|DEPTH|DECLINATION|X|Y|Z))(\s+)(.*)$", re.IGNORECASE|re.MULTILINE),
r'\1<span class = "command">\2</span>\3\4'))
regexes.append((re.compile(r"^(.*)$", re.IGNORECASE|re.MULTILINE),
r'<div>\1&nbsp;</div>\n'))
@register.filter()
@stringfilter
def survex_to_html(value, autoescape=None):
if autoescape:
value = conditional_escape(value)
for regex, sub in regexes:
print sub
value = regex.sub(sub, value)
return mark_safe(value)

View File

@@ -0,0 +1,138 @@
from django import template
from django.utils.html import conditional_escape
from django.template.defaultfilters import stringfilter
from django.utils.safestring import mark_safe
from django.conf import settings
from core.models import QM, Photo
import re, urlparse
register = template.Library()
if settings.URL_ROOT.endswith('/'):
url_root=settings.URL_ROOT[:-1]
def wiki_list(line, listdepth):
l = ""
for d in listdepth:
l += d
mstar = re.match(l + "\*(.*)", line)
if mstar:
listdepth.append("\*")
return ("<ul>\n" + " " * len(listdepth) + "<li>%s</li>\n" % mstar.groups()[0], listdepth)
mhash = re.match(l + "#(.*)", line)
if mhash:
listdepth.append("#")
return ("<ol>\n" + " " * len(listdepth) + "<li>%s</li>\n" % mhash.groups()[0], listdepth)
mflat = re.match(l + "(.*)", line)
if mflat and listdepth:
return (" " * len(listdepth) + "<li>%s</li>\n" % mflat.groups()[0], listdepth)
if listdepth:
prev = listdepth.pop()
if prev == "\*":
t, l = wiki_list(line, listdepth)
return ("</ul>\n" + t, l)
if prev == "#":
t, l = wiki_list(line, listdepth)
return ("</ol>\n" + t, l)
return (line, listdepth)
@register.filter()
@stringfilter
def wiki_to_html(value, autoescape=None):
#find paragraphs
outValue = ""
for paragraph in re.split("\n\s*?\n", value, re.DOTALL):
outValue += "<p>"
outValue += wiki_to_html_short(paragraph, autoescape)
outValue += "</p>\n"
return mark_safe(outValue)
@register.filter()
@stringfilter
def wiki_to_html_short(value, autoescape=None):
"""
This is the tag which turns wiki syntax into html. Aaron wonders
why it is called "short." It is long, and it operates on long things.
It even has a long name itself.
"""
if autoescape:
value = conditional_escape(value)
#deescape doubly escaped characters
value = re.sub("&amp;(.*?);", r"&\1;", value, re.DOTALL)
#italics and bold
value = re.sub("&#39;&#39;&#39;&#39;([^']+)&#39;&#39;&#39;&#39;", r"<b><i>\1</i></b>", value, re.DOTALL)
value = re.sub("&#39;&#39;&#39;([^']+)&#39;&#39;&#39;", r"<b>\1</b>", value, re.DOTALL)
value = re.sub("&#39;&#39;([^']+)&#39;&#39;", r"<i>\1</i>", value, re.DOTALL)
#make cave links
value = re.sub("\[\[\s*cave:([^\s]+)\s*\s*\]\]", r'<a href="%s/cave/\1/">\1</a>' % url_root, value, re.DOTALL)
#make people links
value = re.sub("\[\[\s*person:(.+)\]\]",r'<a href="%s/person/\1/">\1</a>' % url_root, value, re.DOTALL)
#make qm links. this takes a little doing
qmMatchPattern="\[\[\s*cave:([^\s]+)\s*\s*\QM:(\d*)-(\d*)([ABCDX]?)\]\]"
def qmrepl(matchobj):
"""
A function for replacing wikicode qm links with html qm links.
Given a matchobj matching a wikilink in the format
[[cave:204 QM:1999-24C]] where the grade (C) is optional.
If the QM does not exist, the function will return a link for creating it.
"""
# if there are four matched groups, the fourth one should be the QM grade
if len(matchobj.groups())==4:
grade=matchobj.groups()[3]
else:
grade=''
qmdict={'urlroot':url_root,'cave':matchobj.groups()[0],'year':matchobj.groups()[1],'number':matchobj.groups()[2],'grade':grade}
try:
qm=QM.objects.get(found_by__cave__kataster_number=qmdict['cave'],found_by__date__year=qmdict['year'], number=qmdict['number'])
res=r'<a href=' + str(qm.get_absolute_url()) +'>' + str(qm) + '</a>'
except QM.DoesNotExist:
res = r'<a class="redtext" href="%(urlroot)s/cave/%(cave)s/%(year)s-%(number)s%(grade)s">%(cave)s:%(year)s-%(number)s%(grade)s</a>' % qmdict
return res
value = re.sub(qmMatchPattern,qmrepl, value, re.DOTALL)
#make photo links for [[photo:filename]] or [[photo:filename linktext]], and
#insert photos for [[display:left photo:filename]]
photoLinkPattern="\[\[\s*photo:(?P<photoName>[^\s]+)\s*(?P<linkText>.*)\]\]"
photoSrcPattern="\[\[\s*display:(?P<style>[^\s]+) photo:(?P<photoName>[^\s]+)\s*\]\]"
def photoLinkRepl(matchobj):
matchdict=matchobj.groupdict()
try:
linkText=matchdict['linkText']
except KeyError:
linkText=None
try:
photo=Photo.objects.get(file=matchdict['photoName'])
if not linkText:
linkText=str(photo)
res=r'<a href=' + photo.get_admin_url() +'>' + linkText + '</a>'
except Photo.DoesNotExist:
res = r'<a class="redtext" href="">make new photo</a>'
return res
def photoSrcRepl(matchobj):
matchdict=matchobj.groupdict()
style=matchdict['style']
try:
photo=Photo.objects.get(file=matchdict['photoName'])
res=r'<a href='+photo.file.url+'><img src=' + photo.thumbnail_image.url +' class='+style+' /></a>'
except Photo.DoesNotExist:
res = r'<a class="redtext" href="">make new photo</a>'
return res
value = re.sub(photoLinkPattern,photoLinkRepl, value, re.DOTALL)
value = re.sub(photoSrcPattern,photoSrcRepl, value, re.DOTALL)
#Make lists from lines starting with lists of [stars and hashes]
outValue = ""
listdepth = []
for line in value.split("\n"):
t, listdepth = wiki_list(line, listdepth)
outValue += t
for item in listdepth:
if item == "\*":
outValue += "</ul>\n"
elif item == "#":
outValue += "</ol>\n"
return mark_safe(outValue)
wiki_to_html.needs_autoescape = True

161
core/view_surveys.py Normal file
View File

@@ -0,0 +1,161 @@
from django.conf import settings
import fileAbstraction
from django.shortcuts import render_to_response
from django.http import HttpResponse, Http404
import os
import re
# inline fileabstraction into here if it's not going to be useful anywhere else
# keep things simple and ignore exceptions everywhere for now
def getMimeType(extension):
try:
return {"txt": "text/plain",
"html": "text/html",
}[extension]
except:
print "unknown file type"
return "text/plain"
def listdir(request, path):
#try:
return HttpResponse(fileAbstraction.listdir(path), mimetype = "text/plain")
#except:
# raise Http404
def upload(request, path):
pass
def download(request, path):
#try:
return HttpResponse(fileAbstraction.readFile(path), mimetype=getMimeType(path.split(".")[-1]))
#except:
# raise Http404
#
# julian's quick hack for something that works
# could signal directories by ending with /, and forward cases where it's missing
#
extmimetypes = {".txt": "text/plain",
".html": "text/html",
".png": "image/png",
".jpg": "image/jpeg",
}
def jgtfile(request, f):
fp = os.path.join(settings.SURVEYS, f)
# could also surf through SURVEX_DATA
# directory listing
if os.path.isdir(fp):
listdirfiles = [ ]
listdirdirs = [ ]
for lf in sorted(os.listdir(fp)):
hpath = os.path.join(f, lf) # not absolute path
if lf[0] == "." or lf[-1] == "~":
continue
hpath = hpath.replace("\\", "/") # for windows users
href = hpath.replace("#", "%23") # '#' in file name annoyance
flf = os.path.join(fp, lf)
if os.path.isdir(flf):
nfiles = len([sf for sf in os.listdir(flf) if sf[0] != "."])
listdirdirs.append((href, hpath + "/", nfiles))
else:
listdirfiles.append((href, hpath, os.path.getsize(flf)))
upperdirs = [ ]
lf = f
while lf:
hpath = lf.replace("\\", "/") # for windows users
if hpath[-1] != "/":
hpath += "/"
href = hpath.replace("#", "%23")
lf = os.path.split(lf)[0]
upperdirs.append((href, hpath))
upperdirs.append(("", "/"))
return render_to_response('listdir.html', {'file':f, 'listdirfiles':listdirfiles, 'listdirdirs':listdirdirs, 'upperdirs':upperdirs, 'settings': settings})
# flat output of file when loaded
if os.path.isfile(fp):
ext = os.path.splitext(fp)[1].lower()
mimetype = extmimetypes.get(ext, "text/plain")
fin = open(fp)
ftext = fin.read()
fin.close()
return HttpResponse(ftext, mimetype=mimetype)
return HttpResponse("unknown file::%s::" % f, mimetype = "text/plain")
def UniqueFile(fname):
while True:
if not os.path.exists(fname):
break
mname = re.match("(.*?)(?:-(\d+))?\.(png|jpg|jpeg)$(?i)", fname)
if mname:
fname = "%s-%d.%s" % (mname.group(1), int(mname.group(2) or "0") + 1, mname.group(3))
return fname
# join it all up and then split them off for the directories that don't exist
# anyway, this mkdir doesn't work
def SaveImageInDir(name, imgdir, project, fdata, bbinary):
print ("hihihihi", fdata, settings.SURVEYS)
fimgdir = os.path.join(settings.SURVEYS, imgdir)
if not os.path.isdir(fimgdir):
print "*** Making directory", fimgdir
os.path.mkdir(fimgdir)
fprojdir = os.path.join(fimgdir, project)
if not os.path.isdir(fprojdir):
print "*** Making directory", fprojdir
os.path.mkdir(fprojdir)
print "hhh"
fname = os.path.join(fprojdir, name)
print fname, "fff"
fname = UniqueFile(fname)
p2, p1 = os.path.split(fname)
p3, p2 = os.path.split(p2)
p4, p3 = os.path.split(p3)
res = os.path.join(p3, p2, p1)
print "saving file", fname
fout = open(fname, (bbinary and "wb" or "w"))
fout.write(fdata.read())
fout.close()
res = os.path.join(imgdir, name)
return res.replace("\\", "/")
# do we want to consider saving project/field rather than field/project
def jgtuploadfile(request):
filesuploaded = [ ]
project, user, password, tunnelversion = request.POST["tunnelproject"], request.POST["tunneluser"], request.POST["tunnelpassword"], request.POST["tunnelversion"]
print (project, user, tunnelversion)
for uploadedfile in request.FILES.values():
if uploadedfile.field_name in ["tileimage", "backgroundimage"] and \
uploadedfile.content_type in ["image/png", "image/jpeg"]:
fname = user + "_" + re.sub("[\\\\/]", "-", uploadedfile.name) # very escaped \
print fname
fileuploaded = SaveImageInDir(fname, uploadedfile.field_name, project, uploadedfile, True)
filesuploaded.append(settings.URL_ROOT + "/jgtfile/" + fileuploaded)
if uploadedfile.field_name in ["sketch"] and \
uploadedfile.content_type in ["text/plain"]:
fname = user + "_" + re.sub("[\\\\/]", "-", uploadedfile.name) # very escaped \
print fname
fileuploaded = SaveImageInDir(fname, uploadedfile.field_name, project, uploadedfile, False)
filesuploaded.append(settings.URL_ROOT + "/jgtfile/" + fileuploaded)
#print "FF", request.FILES
#print ("FFF", request.FILES.values())
message = ""
print "gothere"
return render_to_response('fileupload.html', {'message':message, 'filesuploaded':filesuploaded, 'settings': settings})

8
core/views.py Normal file
View File

@@ -0,0 +1,8 @@
# primary namespace
import view_surveys
import views_caves
import views_survex
import views_logbooks
import views_other

99
core/views_caves.py Normal file
View File

@@ -0,0 +1,99 @@
from troggle.core.models import Cave, CaveAndEntrance, Survey, Expedition, QM
import troggle.core.models as models
import troggle.settings as settings
from django.forms.models import formset_factory
import search
from django.core.urlresolvers import reverse
from troggle.alwaysUseRequestContext import render_response # see views_logbooks for explanation on this.
from django.http import HttpResponseRedirect
from django.conf import settings
import re, urlparse
def getCave(cave_id):
"""Returns a cave object when given a cave name or number. It is used by views including cavehref, ent, and qm."""
try:
cave = Cave.objects.get(kataster_number=cave_id)
except Cave.DoesNotExist:
cave = Cave.objects.get(unofficial_number=cave_id)
return cave
def caveindex(request):
caves = Cave.objects.all()
notablecavehrefs = [ "161", "204", "258", "76" ] # could detect notability by trips and notability of people who have been down them
notablecaves = [Cave.objects.get(kataster_number=kataster_number) for kataster_number in notablecavehrefs ]
return render_response(request,'caveindex.html', {'caves': caves, 'notablecaves':notablecaves})
def cave(request, cave_id='', offical_name=''):
cave=getCave(cave_id)
if cave.non_public and not request.user.is_authenticated():
return render_response(request,'nonpublic.html', {'instance': cave})
else:
return render_response(request,'cave.html', {'cave': cave})
def qm(request,cave_id,qm_id,year,grade=None):
year=int(year)
try:
qm=getCave(cave_id).get_QMs().get(number=qm_id,found_by__date__year=year)
return render_response(request,'qm.html',locals())
except QM.DoesNotExist:
url=urlparse.urljoin(settings.URL_ROOT, r'/admin/expo/qm/add/'+'?'+ r'number=' + qm_id)
if grade:
url += r'&grade=' + grade
return HttpResponseRedirect(url)
def ent(request, cave_id, ent_letter):
cave = Cave.objects.filter(kataster_number = cave_id)[0]
cave_and_ent = CaveAndEntrance.objects.filter(cave = cave).filter(entrance_letter = ent_letter)[0]
return render_response(request,'entrance.html', {'cave': cave,
'entrance': cave_and_ent.entrance,
'letter': cave_and_ent.entrance_letter,})
def survexblock(request, survexpath):
survexblock = models.SurvexBlock.objects.get(survexpath=survexpath)
#ftext = survexblock.filecontents()
ftext = survexblock.text
return render_response(request,'survexblock.html', {'survexblock':survexblock, 'ftext':ftext, })
def subcave(request, cave_id, subcave):
print subcave
subcaveSeq=re.findall('(?:/)([^/]*)',subcave)
print subcaveSeq
cave=models.Cave.objects.get(kataster_number = cave_id)
subcave=models.Subcave.objects.get(title=subcaveSeq[0], cave=cave)
if len(subcaveSeq)>1:
for subcaveUrlSegment in subcaveSeq[1:]:
if subcaveUrlSegment:
subcave=subcave.children.get(title=subcaveUrlSegment)
print subcave
return render_response(request,'subcave.html', {'subcave': subcave,'cave':cave})
def caveSearch(request):
query_string = ''
found_entries = None
if ('q' in request.GET) and request.GET['q'].strip():
query_string = request.GET['q']
entry_query = search.get_query(query_string, ['underground_description','official_name',])
found_entries = Cave.objects.filter(entry_query)
return render_response(request,'cavesearch.html',
{ 'query_string': query_string, 'found_entries': found_entries,})
def surveyindex(request):
surveys=Survey.objects.all()
expeditions=Expedition.objects.order_by("-year")
return render_response(request,'survey.html',locals())
def survey(request,year,wallet_number):
surveys=Survey.objects.all()
expeditions=Expedition.objects.order_by("-year")
current_expedition=Expedition.objects.filter(year=year)[0]
if wallet_number!='':
current_survey=Survey.objects.filter(expedition=current_expedition,wallet_number=wallet_number)[0]
notes=current_survey.scannedimage_set.filter(contents='notes')
planSketches=current_survey.scannedimage_set.filter(contents='plan')
elevationSketches=current_survey.scannedimage_set.filter(contents='elevation')
return render_response(request,'survey.html', locals())

124
core/views_logbooks.py Normal file
View File

@@ -0,0 +1,124 @@
from django.shortcuts import render_to_response
from troggle.core.models import Expedition, Person, PersonExpedition, PersonTrip, LogbookEntry
import troggle.settings as settings
from django.db import models
from troggle.parsers.logbooks import LoadLogbookForExpedition
from troggle.parsers.people import GetPersonExpeditionNameLookup
from troggle.core.forms import PersonForm
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
# Django uses Context, not RequestContext when you call render_to_response. We always want to use RequestContext, so that django adds the context from settings.TEMPLATE_CONTEXT_PROCESSORS. This way we automatically get necessary settings variables passed to each template. So we use a custom method, render_response instead of render_to_response. Hopefully future Django releases will make this unnecessary.
from troggle.alwaysUseRequestContext import render_response
import search
import re
@models.permalink #this allows the nice get_absolute_url syntax we are using
def getNotablePersons():
notablepersons = []
for person in Person.objects.all():
if person.bisnotable():
notablepersons.append(person)
return notablepersons
def personindex(request):
persons = Person.objects.all()
# From what I can tell, "persons" seems to be the table rows, while "personss" is the table columns. - AC 16 Feb 09
personss = [ ]
ncols = 5
nc = (len(persons) + ncols - 1) / ncols
for i in range(ncols):
personss.append(persons[i * nc: (i + 1) * nc])
notablepersons = []
for person in Person.objects.all():
if person.bisnotable():
notablepersons.append(person)
return render_response(request,'personindex.html', {'persons': persons, 'personss':personss, 'notablepersons':notablepersons, })
def expedition(request, expeditionname):
year = int(expeditionname)
expedition = Expedition.objects.get(year=year)
expedition_next = Expedition.objects.filter(year=year+1) and Expedition.objects.get(year=year+1) or None
expedition_prev = Expedition.objects.filter(year=year-1) and Expedition.objects.get(year=year-1) or None
message = "No message"
if "reload" in request.GET:
message = LoadLogbookForExpedition(expedition)
#message = str(GetPersonExpeditionNameLookup(expedition).keys())
logbookentries = expedition.logbookentry_set.order_by('date')
return render_response(request,'expedition.html', {'expedition': expedition, 'expedition_next':expedition_next, 'expedition_prev':expedition_prev, 'logbookentries':logbookentries, 'message':message, })
def get_absolute_url(self):
return ('expedition', (expedition.year))
def person(request, first_name='', last_name='', ):
person = Person.objects.get(first_name = first_name, last_name = last_name)
#This is for removing the reference to the user's profile, in case they set it to the wrong person
if request.method == 'GET':
if request.GET.get('clear_profile')=='True':
person.user=None
person.save()
return HttpResponseRedirect(reverse('profiles_select_profile'))
return render_response(request,'person.html', {'person': person, })
def get_absolute_url(self):
return settings.URL_ROOT + self.first_name + '_' + self.last_name
#def person(request, name):
# person = Person.objects.get(href=name)
#
def personexpedition(request, first_name='', last_name='', year=''):
person = Person.objects.get(first_name = first_name, last_name = last_name)
expedition = Expedition.objects.get(year=year)
personexpedition = person.personexpedition_set.get(expedition=expedition)
return render_response(request,'personexpedition.html', {'personexpedition': personexpedition, })
def newQMlink(logbookentry):
biggestQMnumber=0
if logbookentry.cave:
for log in logbookentry.cave.logbookentry_set.all():
try:
biggestQMnumberInLog = logbookentry.QMs_found.order_by('-number')[0].number
except IndexError:
biggestQMnumberInLog = 0
if biggestQMnumberInLog > biggestQMnumber:
biggestQMnumber = biggestQMnumberInLog
else:
return None
nextQMnumber=biggestQMnumber+1
return settings.URL_ROOT + r'/admin/expo/qm/add/?' + r'found_by=' + str(logbookentry.pk) +'&number=' + str(nextQMnumber)
def logbookentry(request, date, slug):
logbookentry = LogbookEntry.objects.filter(date=date, slug=slug)
if len(logbookentry)>1:
return render_response(request, 'object_list.html',{'object_list':logbookentry})
else:
logbookentry=logbookentry[0]
return render_response(request, 'logbookentry.html', {'logbookentry': logbookentry, 'newQMlink':newQMlink(logbookentry)})
def logbookSearch(request, extra):
query_string = ''
found_entries = None
if ('q' in request.GET) and request.GET['q'].strip():
query_string = request.GET['q']
entry_query = search.get_query(query_string, ['text','title',])
found_entries = LogbookEntry.objects.filter(entry_query)
return render_response(request,'logbooksearch.html',
{ 'query_string': query_string, 'found_entries': found_entries, })
#context_instance=RequestContext(request))
def personForm(request,pk):
person=Person.objects.get(pk=pk)
form=PersonForm(instance=person)
return render_response(request,'personform.html', {'form':form,})

155
core/views_other.py Normal file
View File

@@ -0,0 +1,155 @@
from troggle.core.models import Cave, Expedition, Person, LogbookEntry, PersonExpedition, PersonTrip, Photo
import troggle.settings as settings
from django import forms
from django.template import loader, Context
from django.db.models import Q
import databaseReset
import re
import randSent
from django.http import HttpResponse, HttpResponseRedirect
from django.core.urlresolvers import reverse
from troggle.alwaysUseRequestContext import render_response # see views_logbooks for explanation on this.
from core.models import *
def showrequest(request):
return HttpResponse(request.GET)
def stats(request):
statsDict={}
statsDict['expoCount'] = int(Expedition.objects.count())
statsDict['caveCount'] = int(Cave.objects.count())
statsDict['personCount'] = int(Person.objects.count())
statsDict['logbookEntryCount'] = int(LogbookEntry.objects.count())
return render_response(request,'statistics.html', statsDict)
def frontpage(request):
message = "no test message" #reverse('personn', kwargs={"name":"hkjhjh"})
if "reloadexpos" in request.GET:
message = LoadPersonsExpos()
message = "Reloaded personexpos"
if "reloadsurvex" in request.POST:
message = LoadAllSurvexBlocks()
message = "Reloaded survexblocks"
#'randSent':randSent.randomLogbookSentence(),
expeditions = Expedition.objects.order_by("-year")
logbookentry = LogbookEntry
cave = Cave
photo = Photo
from django.contrib.admin.templatetags import log
return render_response(request,'frontpage.html', locals())
def todo(request):
message = "no test message" #reverse('personn', kwargs={"name":"hkjhjh"})
if "reloadexpos" in request.GET:
message = LoadPersonsExpos()
message = "Reloaded personexpos"
if "reloadsurvex" in request.POST:
message = LoadAllSurvexBlocks()
message = "Reloaded survexblocks"
#'randSent':randSent.randomLogbookSentence(),
expeditions = Expedition.objects.order_by("-year")
totallogbookentries = LogbookEntry.objects.count()
return render_response(request,'index.html', {'expeditions':expeditions, 'all':'all', 'totallogbookentries':totallogbookentries, "message":message})
def calendar(request,year):
week=['S','S','M','T','W','T','F']
if year:
expedition=Expedition.objects.get(year=year)
PersonExpeditions=expedition.personexpedition_set.all()
return render_response(request,'calendar.html', locals())
def controlPanel(request):
jobs_completed=[]
if request.method=='POST':
if request.user.is_superuser:
#importlist is mostly here so that things happen in the correct order.
#http post data seems to come in an unpredictable order, so we do it this way.
importlist=['reload_db', 'import_people', 'import_cavetab', 'import_logbooks', 'import_surveys', 'import_QMs']
databaseReset.make_dirs()
for item in importlist:
if item in request.POST:
print "running"+ " databaseReset."+item+"()"
exec "databaseReset."+item+"()"
jobs_completed.append(item)
else:
if request.user.is_authenticated(): #The user is logged in, but is not a superuser.
return render_response(request,'controlPanel.html', {'caves':Cave.objects.all(),'error':'You must be a superuser to use that feature.'})
else:
return HttpResponseRedirect(reverse('auth_login'))
return render_response(request,'controlPanel.html', {'caves':Cave.objects.all(),'expeditions':Expedition.objects.all(),'jobs_completed':jobs_completed})
def downloadCavetab(request):
from export import tocavetab
response = HttpResponse(mimetype='text/csv')
response['Content-Disposition'] = 'attachment; filename=CAVETAB2.CSV'
tocavetab.writeCaveTab(response)
return response
def downloadSurveys(request):
from export import tosurveys
response = HttpResponse(mimetype='text/csv')
response['Content-Disposition'] = 'attachment; filename=Surveys.csv'
tosurveys.writeCaveTab(response)
return response
def downloadLogbook(request,year=None,extension=None,queryset=None):
if year:
expedition=Expedition.objects.get(year=year)
logbook_entries=LogbookEntry.objects.filter(expedition=expedition)
filename='logbook'+year
elif queryset:
logbook_entries=queryset
filename='logbook'
else:
return response(r"Error: Logbook downloader doesn't know what year you want")
if 'year' in request.GET:
year=request.GET['year']
if 'extension' in request.GET:
extension=request.GET['extension']
if extension =='txt':
response = HttpResponse(mimetype='text/plain')
style='2008'
elif extension == 'html':
response = HttpResponse(mimetype='text/html')
style='2005'
template='logbook'+style+'style.'+extension
response['Content-Disposition'] = 'attachment; filename='+filename+'.'+extension
t=loader.get_template(template)
c=Context({'logbook_entries':logbook_entries})
response.write(t.render(c))
return response
def downloadQMs(request):
# Note to self: use get_cave method for the below
if request.method=='GET':
try:
cave=Cave.objects.get(kataster_number=request.GET['cave_id'])
except Cave.DoesNotExist:
cave=Cave.objects.get(name=cave_id)
from export import toqms
response = HttpResponse(mimetype='text/csv')
response['Content-Disposition'] = 'attachment; filename=qm.csv'
toqms.writeQmTable(response,cave)
return response
def ajax_test(request):
post_text = request.POST['post_data']
return HttpResponse("{'response_text': '"+post_text+" recieved.'}",
mimetype="application/json")
def eyecandy(request):
return render_response(request,'eyecandy.html', {})

167
core/views_survex.py Normal file
View File

@@ -0,0 +1,167 @@
from django import forms
from django.http import HttpResponseRedirect, HttpResponse
from django.shortcuts import render_to_response
from django.http import HttpResponse, Http404
import re
import os
import datetime
import difflib
import troggle.settings as settings
def ReplaceTabs(stext):
res = [ ]
nsl = 0
for s in re.split("(\t|\n)", stext):
if s == "\t":
res.append(" " * (4 - (nsl % 4)))
nsl = 0
continue
if s == "\n":
nsl = 0
else:
nsl += len(s)
res.append(s)
return "".join(res)
class SvxForm(forms.Form):
dirname = forms.CharField(widget=forms.TextInput(attrs={"readonly":True}))
filename = forms.CharField(widget=forms.TextInput(attrs={"readonly":True}))
datetime = forms.DateTimeField(widget=forms.TextInput(attrs={"readonly":True}))
outputtype = forms.CharField(widget=forms.TextInput(attrs={"readonly":True}))
code = forms.CharField(widget=forms.Textarea(attrs={"cols":150, "rows":18}))
def GetDiscCode(self):
fname = settings.SURVEX_DATA + self.data['filename'] + ".svx"
if not os.path.isfile(fname):
return None
fin = open(fname, "rb")
svxtext = fin.read().decode("latin1") # unicode(a, "latin1")
svxtext = ReplaceTabs(svxtext).strip()
fin.close()
return svxtext
def DiffCode(self, rcode):
code = self.GetDiscCode()
difftext = difflib.unified_diff(code.splitlines(), rcode.splitlines())
difflist = [ diffline.strip() for diffline in difftext if not re.match("\s*$", diffline) ]
return difflist
def SaveCode(self, rcode):
fname = settings.SURVEX_DATA + self.data['filename'] + ".svx"
if not os.path.isfile(fname):
return False
fout = open(fname, "w")
res = fout.write(rcode.encode("latin1"))
fout.close()
return True
def Process(self):
print "....\n\n\n....Processing\n\n\n"
cwd = os.getcwd()
os.chdir(os.path.split(settings.SURVEX_DATA + self.data['filename'])[0])
os.system(settings.CAVERN + " --log " + settings.SURVEX_DATA + self.data['filename'] + ".svx")
os.chdir(cwd)
fin = open(settings.SURVEX_DATA + self.data['filename'] + ".log", "rb")
log = fin.read()
fin.close()
log = re.sub("(?s).*?(Survey contains)", "\\1", log)
return log
def svx(request, survex_file):
# get the basic data from the file given in the URL
dirname = os.path.split(survex_file)[0]
if dirname:
dirname += "/"
nowtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
outputtype = "normal"
form = SvxForm({'filename':survex_file, 'dirname':dirname, 'datetime':nowtime, 'outputtype':outputtype})
# if the form has been returned
difflist = [ ]
logmessage = ""
message = ""
if request.method == 'POST': # If the form has been submitted...
rform = SvxForm(request.POST) #
if rform.is_valid(): # All validation rules pass (how do we check it against the filename and users?)
rcode = rform.cleaned_data['code']
outputtype = rform.cleaned_data['outputtype']
difflist = form.DiffCode(rcode)
print "ssss", rform.data
if "revert" in rform.data:
pass
if "process" in rform.data:
if not difflist:
message = "OUTPUT FROM PROCESSING"
logmessage = form.Process()
print logmessage
else:
message = "SAVE FILE FIRST"
form.data['code'] = rcode
if "save" in rform.data:
print "sssavvving"
if form.SaveCode(rcode):
message = "SAVVVED"
# we will reload later
else:
message = "FAILED TO SAVE"
form.data['code'] = rcode
if "diff" in rform.data:
form.data['code'] = rcode
#process(survex_file)
if 'code' not in form.data:
form.data['code'] = form.GetDiscCode()
if not difflist:
difflist.append("none")
if message:
difflist.insert(0, message)
svxincludes = re.findall('\*include\s+"?(.*?)(?:\.svx)?"?\s*?\n(?i)', form.data['code'])
vmap = {'settings': settings,
'has_3d': os.path.isfile(settings.SURVEX_DATA + survex_file + ".3d"),
'title': survex_file,
'svxincludes': svxincludes,
'difflist': difflist,
'logmessage':logmessage,
'form':form}
if outputtype == "ajax":
return render_to_response('svxfiledifflistonly.html', vmap)
return render_to_response('svxfile.html', vmap)
def Dsvx(request, survex_file):
svx = open(settings.SURVEX_DATA + survex_file + ".svx", "rb")
return HttpResponse(svx, mimetype="text")
def threed(request, survex_file):
process(survex_file)
try:
threed = open(settings.SURVEX_DATA + survex_file + ".3d", "rb")
return HttpResponse(threed, mimetype="model/3d")
except:
log = open(settings.SURVEX_DATA + survex_file + ".log", "rb")
return HttpResponse(log, mimetype="text")
def log(request, survex_file):
process(survex_file)
log = open(settings.SURVEX_DATA + survex_file + ".log", "rb")
return HttpResponse(log, mimetype="text")
def err(request, survex_file):
process(survex_file)
err = open(settings.SURVEX_DATA + survex_file + ".err", "rb")
return HttpResponse(err, mimetype="text")
def process(survex_file):
cwd = os.getcwd()
os.chdir(os.path.split(settings.SURVEX_DATA + survex_file)[0])
os.system(settings.CAVERN + " --log " + settings.SURVEX_DATA + survex_file + ".svx")
os.chdir(cwd)