diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/admin.py | 282 | ||||
-rw-r--r-- | core/forms.py | 242 | ||||
-rw-r--r-- | core/models.py | 1400 | ||||
-rw-r--r-- | core/models_survex.py | 426 | ||||
-rw-r--r-- | core/templatetags/link.py | 18 | ||||
-rw-r--r-- | core/templatetags/survex_markup.py | 102 | ||||
-rw-r--r-- | core/templatetags/wiki_markup.py | 338 | ||||
-rw-r--r-- | core/view_surveys.py | 466 | ||||
-rw-r--r-- | core/views.py | 16 | ||||
-rw-r--r-- | core/views_caves.py | 282 | ||||
-rw-r--r-- | core/views_logbooks.py | 504 | ||||
-rw-r--r-- | core/views_other.py | 564 | ||||
-rw-r--r-- | core/views_survex.py | 634 |
13 files changed, 2637 insertions, 2637 deletions
diff --git a/core/admin.py b/core/admin.py index be4045a..fc43f23 100644 --- a/core/admin.py +++ b/core/admin.py @@ -1,141 +1,141 @@ -from troggle.core.models import *
-from django.contrib import admin
-from django.forms import ModelForm
-import django.forms as forms
-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
-
-
-class TroggleModelAdmin(admin.ModelAdmin):
-
- def save_model(self, request, obj, form, change):
- """overriding admin save to fill the new_since parsing_field"""
- obj.new_since_parsing=True
- obj.save()
-
- class Media:
- js = ('js/jquery.js','js/QM_helper.js')
-
-class RoleInline(admin.TabularInline):
- model = SurvexPersonRole
- extra = 4
-
-class SurvexBlockAdmin(TroggleModelAdmin):
- inlines = (RoleInline,)
-
-class ScannedImageInline(admin.TabularInline):
- model = ScannedImage
- extra = 4
-
-class OtherCaveInline(admin.TabularInline):
- model = OtherCaveName
- extra = 1
-
-class SurveyAdmin(TroggleModelAdmin):
- inlines = (ScannedImageInline,)
- search_fields = ('expedition__year','wallet_number')
-
-class QMsFoundInline(admin.TabularInline):
- model=QM
- fk_name='found_by'
- fields=('number','grade','location_description','comment')#need to add foreignkey to cave part
- extra=1
-
-class PhotoInline(admin.TabularInline):
- model = DPhoto
- exclude = ['is_mugshot' ]
- extra = 1
-
-class PersonTripInline(admin.TabularInline):
- model = PersonTrip
- raw_id_fields = ('personexpedition',)
- extra = 1
-
-#class LogbookEntryAdmin(VersionAdmin):
-class LogbookEntryAdmin(TroggleModelAdmin):
- prepopulated_fields = {'slug':("title",)}
- raw_id_fields = ('cave',)
- search_fields = ('title','expedition__year')
- date_heirarchy = ('date')
- inlines = (PersonTripInline, PhotoInline, QMsFoundInline)
- class Media:
- css = {
- "all": ("css/troggleadmin.css",)
- }
- 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
- raw_id_fields=('found_by','ticked_off_by')
-
-class PersonExpeditionAdmin(TroggleModelAdmin):
- search_fields = ('person__first_name','expedition__year')
-
-class CaveAdmin(TroggleModelAdmin):
- search_fields = ('official_name','kataster_number','unofficial_number')
- inlines = (OtherCaveInline,)
- extra = 4
-
-class EntranceAdmin(TroggleModelAdmin):
- search_fields = ('caveandentrance__cave__kataster_number',)
-
-admin.site.register(DPhoto)
-admin.site.register(Cave, CaveAdmin)
-admin.site.register(Area)
-#admin.site.register(OtherCaveName)
-admin.site.register(CaveAndEntrance)
-admin.site.register(NewSubCave)
-admin.site.register(CaveDescription)
-admin.site.register(Entrance, EntranceAdmin)
-admin.site.register(SurvexBlock, SurvexBlockAdmin)
-admin.site.register(Expedition)
-admin.site.register(Person,PersonAdmin)
-admin.site.register(SurvexPersonRole)
-admin.site.register(PersonExpedition,PersonExpeditionAdmin)
-admin.site.register(LogbookEntry, LogbookEntryAdmin)
-#admin.site.register(PersonTrip)
-admin.site.register(QM, QMAdmin)
-admin.site.register(Survey, SurveyAdmin)
-admin.site.register(ScannedImage)
-
-admin.site.register(SurvexScansFolder)
-admin.site.register(SurvexScanSingle)
-
-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)
+from troggle.core.models import * +from django.contrib import admin +from django.forms import ModelForm +import django.forms as forms +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 + + +class TroggleModelAdmin(admin.ModelAdmin): + + def save_model(self, request, obj, form, change): + """overriding admin save to fill the new_since parsing_field""" + obj.new_since_parsing=True + obj.save() + + class Media: + js = ('js/jquery.js','js/QM_helper.js') + +class RoleInline(admin.TabularInline): + model = SurvexPersonRole + extra = 4 + +class SurvexBlockAdmin(TroggleModelAdmin): + inlines = (RoleInline,) + +class ScannedImageInline(admin.TabularInline): + model = ScannedImage + extra = 4 + +class OtherCaveInline(admin.TabularInline): + model = OtherCaveName + extra = 1 + +class SurveyAdmin(TroggleModelAdmin): + inlines = (ScannedImageInline,) + search_fields = ('expedition__year','wallet_number') + +class QMsFoundInline(admin.TabularInline): + model=QM + fk_name='found_by' + fields=('number','grade','location_description','comment')#need to add foreignkey to cave part + extra=1 + +class PhotoInline(admin.TabularInline): + model = DPhoto + exclude = ['is_mugshot' ] + extra = 1 + +class PersonTripInline(admin.TabularInline): + model = PersonTrip + raw_id_fields = ('personexpedition',) + extra = 1 + +#class LogbookEntryAdmin(VersionAdmin): +class LogbookEntryAdmin(TroggleModelAdmin): + prepopulated_fields = {'slug':("title",)} + raw_id_fields = ('cave',) + search_fields = ('title','expedition__year') + date_heirarchy = ('date') + inlines = (PersonTripInline, PhotoInline, QMsFoundInline) + class Media: + css = { + "all": ("css/troggleadmin.css",) + } + 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 + raw_id_fields=('found_by','ticked_off_by') + +class PersonExpeditionAdmin(TroggleModelAdmin): + search_fields = ('person__first_name','expedition__year') + +class CaveAdmin(TroggleModelAdmin): + search_fields = ('official_name','kataster_number','unofficial_number') + inlines = (OtherCaveInline,) + extra = 4 + +class EntranceAdmin(TroggleModelAdmin): + search_fields = ('caveandentrance__cave__kataster_number',) + +admin.site.register(DPhoto) +admin.site.register(Cave, CaveAdmin) +admin.site.register(Area) +#admin.site.register(OtherCaveName) +admin.site.register(CaveAndEntrance) +admin.site.register(NewSubCave) +admin.site.register(CaveDescription) +admin.site.register(Entrance, EntranceAdmin) +admin.site.register(SurvexBlock, SurvexBlockAdmin) +admin.site.register(Expedition) +admin.site.register(Person,PersonAdmin) +admin.site.register(SurvexPersonRole) +admin.site.register(PersonExpedition,PersonExpeditionAdmin) +admin.site.register(LogbookEntry, LogbookEntryAdmin) +#admin.site.register(PersonTrip) +admin.site.register(QM, QMAdmin) +admin.site.register(Survey, SurveyAdmin) +admin.site.register(ScannedImage) + +admin.site.register(SurvexScansFolder) +admin.site.register(SurvexScanSingle) + +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) diff --git a/core/forms.py b/core/forms.py index ec639b0..7063f23 100644 --- a/core/forms.py +++ b/core/forms.py @@ -1,121 +1,121 @@ -from django.forms import ModelForm
-from models import Cave, Person, PersonExpedition, LogbookEntry, QM, Expedition
-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
-from tinymce.widgets import TinyMCE
-
-#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()#
-
-class CaveForm(forms.Form):
- html = forms.CharField(widget=TinyMCE(attrs={'cols': 80, 'rows': 30}))
-
-def getTripForm(expedition):
-
- class TripForm(forms.Form):
- date = forms.DateField()
- title = forms.CharField(max_length=200)
- caves = [cave.reference() for cave in Cave.objects.all()]
- caves.sort()
- caves = ["-----"] + caves
- cave = forms.ChoiceField([(c, c) for c in caves], required=False)
- location = forms.CharField(max_length=200, required=False)
- caveOrLocation = forms.ChoiceField([("cave", "Cave"), ("location", "Location")], widget = forms.widgets.RadioSelect())
- html = forms.CharField(widget=TinyMCE(attrs={'cols': 80, 'rows': 30}))
-
- def clean(self):
- print dir(self)
- if self.cleaned_data.get("caveOrLocation") == "cave" and not self.cleaned_data.get("cave"):
- self._errors["cave"] = self.error_class(["This field is required"])
- if self.cleaned_data.get("caveOrLocation") == "location" and not self.cleaned_data.get("location"):
- self._errors["location"] = self.error_class(["This field is required"])
- return self.cleaned_data
-
- class PersonTripForm(forms.Form):
- names = [get_name(pe) for pe in PersonExpedition.objects.filter(expedition = expedition)]
- names.sort()
- names = ["-----"] + names
- name = forms.ChoiceField([(n, n) for n in names])
- TU = forms.FloatField(required=False)
- author = forms.BooleanField(required=False)
-
- PersonTripFormSet = formset_factory(PersonTripForm, extra=1)
-
- return PersonTripFormSet, TripForm
-
-def get_name(pe):
- if pe.nickname:
- return pe.nickname
- else:
- return pe.person.first_name
-
-class UploadFileForm(forms.Form):
- title = forms.CharField(max_length=50)
- file = forms.FileField()
- html = forms.CharField(widget=TinyMCE(attrs={'cols': 80, 'rows': 30}))
- lon_utm = forms.FloatField(required=False)
- lat_utm = forms.FloatField(required=False)
- slug = forms.CharField(max_length=50)
- date = forms.DateField(required=False)
-
- caves = [cave.slug for cave in Cave.objects.all()]
- caves.sort()
- caves = ["-----"] + caves
- cave = forms.ChoiceField([(c, c) for c in caves], required=False)
-
- entrance = forms.ChoiceField([("-----", "Please select a cave"), ], required=False)
- qm = forms.ChoiceField([("-----", "Please select a cave"), ], required=False)
-
- expeditions = [e.year for e in Expedition.objects.all()]
- expeditions.sort()
- expeditions = ["-----"] + expeditions
- expedition = forms.ChoiceField([(e, e) for e in expeditions], required=False)
-
- logbookentry = forms.ChoiceField([("-----", "Please select an expedition"), ], required=False)
-
- person = forms.ChoiceField([("-----", "Please select an expedition"), ], required=False)
-
- survey_point = forms.CharField()
-
-
+from django.forms import ModelForm +from models import Cave, Person, PersonExpedition, LogbookEntry, QM, Expedition +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 +from tinymce.widgets import TinyMCE + +#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()# + +class CaveForm(forms.Form): + html = forms.CharField(widget=TinyMCE(attrs={'cols': 80, 'rows': 30})) + +def getTripForm(expedition): + + class TripForm(forms.Form): + date = forms.DateField() + title = forms.CharField(max_length=200) + caves = [cave.reference() for cave in Cave.objects.all()] + caves.sort() + caves = ["-----"] + caves + cave = forms.ChoiceField([(c, c) for c in caves], required=False) + location = forms.CharField(max_length=200, required=False) + caveOrLocation = forms.ChoiceField([("cave", "Cave"), ("location", "Location")], widget = forms.widgets.RadioSelect()) + html = forms.CharField(widget=TinyMCE(attrs={'cols': 80, 'rows': 30})) + + def clean(self): + print dir(self) + if self.cleaned_data.get("caveOrLocation") == "cave" and not self.cleaned_data.get("cave"): + self._errors["cave"] = self.error_class(["This field is required"]) + if self.cleaned_data.get("caveOrLocation") == "location" and not self.cleaned_data.get("location"): + self._errors["location"] = self.error_class(["This field is required"]) + return self.cleaned_data + + class PersonTripForm(forms.Form): + names = [get_name(pe) for pe in PersonExpedition.objects.filter(expedition = expedition)] + names.sort() + names = ["-----"] + names + name = forms.ChoiceField([(n, n) for n in names]) + TU = forms.FloatField(required=False) + author = forms.BooleanField(required=False) + + PersonTripFormSet = formset_factory(PersonTripForm, extra=1) + + return PersonTripFormSet, TripForm + +def get_name(pe): + if pe.nickname: + return pe.nickname + else: + return pe.person.first_name + +class UploadFileForm(forms.Form): + title = forms.CharField(max_length=50) + file = forms.FileField() + html = forms.CharField(widget=TinyMCE(attrs={'cols': 80, 'rows': 30})) + lon_utm = forms.FloatField(required=False) + lat_utm = forms.FloatField(required=False) + slug = forms.CharField(max_length=50) + date = forms.DateField(required=False) + + caves = [cave.slug for cave in Cave.objects.all()] + caves.sort() + caves = ["-----"] + caves + cave = forms.ChoiceField([(c, c) for c in caves], required=False) + + entrance = forms.ChoiceField([("-----", "Please select a cave"), ], required=False) + qm = forms.ChoiceField([("-----", "Please select a cave"), ], required=False) + + expeditions = [e.year for e in Expedition.objects.all()] + expeditions.sort() + expeditions = ["-----"] + expeditions + expedition = forms.ChoiceField([(e, e) for e in expeditions], required=False) + + logbookentry = forms.ChoiceField([("-----", "Please select an expedition"), ], required=False) + + person = forms.ChoiceField([("-----", "Please select an expedition"), ], required=False) + + survey_point = forms.CharField() + + diff --git a/core/models.py b/core/models.py index 1c08a25..c82f448 100644 --- a/core/models.py +++ b/core/models.py @@ -1,700 +1,700 @@ -import urllib, urlparse, string, os, datetime, logging, re
-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.db.models import Min, Max
-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 *
-
-
-def get_related_by_wikilinks(wiki_text):
- found=re.findall(settings.QM_PATTERN,wiki_text)
- res=[]
- for wikilink in found:
- qmdict={'urlroot':settings.URL_ROOT,'cave':wikilink[2],'year':wikilink[1],'number':wikilink[3]}
- try:
- qm=QM.objects.get(found_by__cave__kataster_number = qmdict['cave'],
- found_by__date__year = qmdict['year'],
- number = qmdict['number'])
- res.append(qm)
- except QM.DoesNotExist:
- print 'fail on '+str(wikilink)
-
- return res
-
-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/core/" + 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/core/" + self.object_name().lower() + "/" + str(self.pk))
-
-
- class Meta:
- abstract = True
-
-#
-# single Expedition, usually seen by year
-#
-class Expedition(TroggleModel):
- year = models.CharField(max_length=20, unique=True)
- name = models.CharField(max_length=100)
-
- def __unicode__(self):
- return self.year
-
- class Meta:
- ordering = ('-year',)
- get_latest_by = 'year'
-
- def get_absolute_url(self):
- return urlparse.urljoin(settings.URL_ROOT, reverse('expedition', args=[self.year]))
-
- # construction function. should be moved out
- def get_expedition_day(self, date):
- expeditiondays = self.expeditionday_set.filter(date=date)
- if expeditiondays:
- assert len(expeditiondays) == 1
- return expeditiondays[0]
- res = ExpeditionDay(expedition=self, date=date)
- res.save()
- return res
-
- def day_min(self):
- res = self.expeditionday_set.all()
- return res and res[0] or None
-
- def day_max(self):
- res = self.expeditionday_set.all()
- return res and res[len(res) - 1] or None
-
-
-
-class ExpeditionDay(TroggleModel):
- expedition = models.ForeignKey("Expedition")
- date = models.DateField()
-
- class Meta:
- ordering = ('date',)
-
- def GetPersonTrip(self, personexpedition):
- personexpeditions = self.persontrip_set.filter(expeditionday=self)
- return personexpeditions and personexpeditions[0] or None
-
-
-#
-# single Person, can go on many years
-#
-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ür Hö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
-
-
- 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 surveyedleglength(self):
- return sum([personexpedition.surveyedleglength() for personexpedition in self.personexpedition_set.all()])
-
- def first(self):
- return self.personexpedition_set.order_by('-expedition')[0]
- def last(self):
- return self.personexpedition_set.order_by('expedition')[0]
-
- #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
-
-
-#
-# Person's attenance to one Expo
-#
-class PersonExpedition(TroggleModel):
- expedition = models.ForeignKey(Expedition)
- person = models.ForeignKey(Person)
- slugfield = models.SlugField(max_length=50,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('survexblock'):
- if res and res[-1]['survexpath'] == personrole.survexblock.survexpath:
- res[-1]['roles'] += ", " + str(personrole.role)
- else:
- res.append({'date':personrole.survexblock.date, 'survexpath':personrole.survexblock.survexpath, 'roles':str(personrole.role)})
- return res
-
- class Meta:
- ordering = ('-expedition',)
- #order_with_respect_to = 'expedition'
-
- 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 urlparse.urljoin(settings.URL_ROOT, reverse('personexpedition',kwargs={'first_name':self.person.first_name,'last_name':self.person.last_name,'year':self.expedition.year}))
-
- def surveyedleglength(self):
- survexblocks = [personrole.survexblock for personrole in self.personrole_set.all() ]
- return sum([survexblock.totalleglength for survexblock in set(survexblocks)])
-
- # would prefer to return actual person trips so we could link to first and last ones
- def day_min(self):
- res = self.persontrip_set.aggregate(day_min=Min("expeditionday__date"))
- return res["day_min"]
-
- def day_max(self):
- res = self.persontrip_set.all().aggregate(day_max=Max("expeditionday__date"))
- return res["day_max"]
-
-#
-# Single parsed entry from Logbook
-#
-class LogbookEntry(TroggleModel):
- date = models.DateField()#MJG wants to turn this into a datetime such that multiple Logbook entries on the same day can be ordered.
- expeditionday = models.ForeignKey("ExpeditionDay", null=True)#MJG wants to KILL THIS (redundant information)
- 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
- #MJG wants to KILL THIS, as it is typically redundant with PersonTrip.is_logbook_entry_author, in the rare it was not redundanty and of actually interest it could be added to the text.
- title = models.CharField(max_length=settings.MAX_LOGBOOK_ENTRY_TITLE_LENGTH)
- 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)
- filename= models.CharField(max_length=200,null=True)
-
- class Meta:
- verbose_name_plural = "Logbook Entries"
- # several PersonTrips point in to this object
- ordering = ('-date',)
-
- def isLogbookEntry(self): # Function used in templates
- return True
-
- 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)
-
- def new_QM_number(self):
- """Returns """
- if self.cave:
- nextQMnumber=self.cave.new_QM_number(self.date.year)
- else:
- return none
- return nextQMnumber
-
- def new_QM_found_link(self):
- """Produces a link to a new QM with the next number filled in and this LogbookEntry set as 'found by' """
- return settings.URL_ROOT + r'/admin/core/qm/add/?' + r'found_by=' + str(self.pk) +'&number=' + str(self.new_QM_number())
-
- def DayIndex(self):
- return list(self.expeditionday.logbookentry_set.all()).index(self)
-
-#
-# Single Person going on a trip, which may or may not be written up (accounts for different T/U for people in same logbook entry)
-#
-class PersonTrip(TroggleModel):
- personexpedition = models.ForeignKey("PersonExpedition",null=True)
-
- #expeditionday = models.ForeignKey("ExpeditionDay")#MJG wants to KILL THIS (redundant information)
- #date = models.DateField() #MJG wants to KILL THIS (redundant information)
- time_underground = models.FloatField(help_text="In decimal hours")
- logbook_entry = models.ForeignKey(LogbookEntry)
- is_logbook_entry_author = models.BooleanField()
-
-
- # sequencing by person (difficult to solve locally)
- #persontrip_next = models.ForeignKey('PersonTrip', related_name='pnext', blank=True,null=True)#MJG wants to KILL THIS (and use funstion persontrip_next_auto)
- #persontrip_prev = models.ForeignKey('PersonTrip', related_name='pprev', blank=True,null=True)#MJG wants to KILL THIS(and use funstion persontrip_prev_auto)
-
- def persontrip_next(self):
- futurePTs = PersonTrip.objects.filter(personexpedition = self.personexpedition, logbook_entry__date__gt = self.logbook_entry.date).order_by('logbook_entry__date').all()
- if len(futurePTs) > 0:
- return futurePTs[0]
- else:
- return None
-
- def persontrip_prev(self):
- pastPTs = PersonTrip.objects.filter(personexpedition = self.personexpedition, logbook_entry__date__lt = self.logbook_entry.date).order_by('-logbook_entry__date').all()
- if len(pastPTs) > 0:
- return pastPTs[0]
- else:
- return None
-
- def place(self):
- return self.logbook_entry.cave and self.logbook_entry.cave or self.logbook_entry.place
-
- def __unicode__(self):
- return "%s (%s)" % (self.personexpedition, self.logbook_entry.date)
-
-
-
-##########################################
-# 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
- slug = models.SlugField(max_length=50, unique = True)
- 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)
- url = models.CharField(max_length=200,blank=True,null=True)
-
- #class Meta:
- # unique_together = (("area", "kataster_number"), ("area", "unofficial_number"))
- # FIXME Kataster Areas and CUCC defined sub areas need seperating
-
-
- #href = models.CharField(max_length=100)
-
- def reference(self):
- if self.kataster_number:
- return "%s-%s" % (self.kat_area(), self.kataster_number)
- else:
- return "%s-%s" % (self.kat_area(), self.unofficial_number)
-
- 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 new_QM_number(self, year=datetime.date.today().year):
- """Given a cave and the current year, returns the next QM number."""
- try:
- res=QM.objects.filter(found_by__date__year=year, found_by__cave=self).order_by('-number')[0]
- except IndexError:
- return 1
- return res.number+1
-
- 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 += "–" + prevR
- else:
- prevR = r
- n = 0
- res += r
- if n == 0:
- res += ", " + prevR
- else:
- res += "–" + prevR
- return res
-
-def getCaveByReference(reference):
- areaname, code = reference.split("-", 1)
- print areaname, code
- area = Area.objects.get(short_name = areaname)
- print area
- foundCaves = list(Cave.objects.filter(area = area, kataster_number = code).all()) + list(Cave.objects.filter(area = area, unofficial_number = code).all())
- print list(foundCaves)
- assert len(foundCaves) == 1
- return foundCaves[0]
-
-class OtherCaveName(TroggleModel):
- name = models.CharField(max_length=160)
- cave = models.ForeignKey(Cave)
- def __unicode__(self):
- return unicode(self.name)
-
-
-class Entrance(TroggleModel):
- slug = models.SlugField(max_length=50, unique = True)
- 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.TextField()
- exact_station = models.TextField()
- other_station = models.TextField()
- 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]
-
-
- 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
-
-class CaveDescription(TroggleModel):
- short_name = models.CharField(max_length=50, unique = True)
- long_name = models.CharField(max_length=200, blank=True, null=True)
- description = models.TextField(blank=True,null=True)
- linked_subcaves = models.ManyToManyField("NewSubCave", blank=True,null=True)
- linked_entrances = models.ManyToManyField("Entrance", blank=True,null=True)
- linked_qms = models.ManyToManyField("QM", blank=True,null=True)
-
- def __unicode__(self):
- if self.long_name:
- return unicode(self.long_name)
- else:
- return unicode(self.short_name)
-
- def get_absolute_url(self):
- return urlparse.urljoin(settings.URL_ROOT, reverse('cavedescription', args=(self.short_name,)))
-
- def save(self):
- """
- Overridden save method which stores wikilinks in text as links in database.
- """
- super(CaveDescription, self).save()
- qm_list=get_related_by_wikilinks(self.description)
- for qm in qm_list:
- self.linked_qms.add(qm)
- super(CaveDescription, self).save()
-
-class NewSubCave(TroggleModel):
- name = models.CharField(max_length=200, unique = True)
- def __unicode__(self):
- return unicode(self.name)
-
-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)
- #cave = models.ForeignKey(Cave)
- #expedition = models.ForeignKey(Expedition)
-
- 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)
-
- def __unicode__(self):
- return u"%s %s" % (self.code(), self.grade)
-
- def code(self):
- return u"%s-%s-%s" % (unicode(self.found_by.cave)[6:], self.found_by.date.year, self.number)
-
- 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):
- return u"%s%s%s" % ('[[QM:',self.code(),']]')
-
-photoFileStorage = FileSystemStorage(location=settings.PHOTOS_ROOT, base_url=settings.PHOTOS_URL)
-class DPhoto(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('NewSubCave', 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')
+import urllib, urlparse, string, os, datetime, logging, re +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.db.models import Min, Max +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 * + + +def get_related_by_wikilinks(wiki_text): + found=re.findall(settings.QM_PATTERN,wiki_text) + res=[] + for wikilink in found: + qmdict={'urlroot':settings.URL_ROOT,'cave':wikilink[2],'year':wikilink[1],'number':wikilink[3]} + try: + qm=QM.objects.get(found_by__cave__kataster_number = qmdict['cave'], + found_by__date__year = qmdict['year'], + number = qmdict['number']) + res.append(qm) + except QM.DoesNotExist: + print 'fail on '+str(wikilink) + + return res + +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/core/" + 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/core/" + self.object_name().lower() + "/" + str(self.pk)) + + + class Meta: + abstract = True + +# +# single Expedition, usually seen by year +# +class Expedition(TroggleModel): + year = models.CharField(max_length=20, unique=True) + name = models.CharField(max_length=100) + + def __unicode__(self): + return self.year + + class Meta: + ordering = ('-year',) + get_latest_by = 'year' + + def get_absolute_url(self): + return urlparse.urljoin(settings.URL_ROOT, reverse('expedition', args=[self.year])) + + # construction function. should be moved out + def get_expedition_day(self, date): + expeditiondays = self.expeditionday_set.filter(date=date) + if expeditiondays: + assert len(expeditiondays) == 1 + return expeditiondays[0] + res = ExpeditionDay(expedition=self, date=date) + res.save() + return res + + def day_min(self): + res = self.expeditionday_set.all() + return res and res[0] or None + + def day_max(self): + res = self.expeditionday_set.all() + return res and res[len(res) - 1] or None + + + +class ExpeditionDay(TroggleModel): + expedition = models.ForeignKey("Expedition") + date = models.DateField() + + class Meta: + ordering = ('date',) + + def GetPersonTrip(self, personexpedition): + personexpeditions = self.persontrip_set.filter(expeditionday=self) + return personexpeditions and personexpeditions[0] or None + + +# +# single Person, can go on many years +# +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ür Hö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 + + + 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 surveyedleglength(self): + return sum([personexpedition.surveyedleglength() for personexpedition in self.personexpedition_set.all()]) + + def first(self): + return self.personexpedition_set.order_by('-expedition')[0] + def last(self): + return self.personexpedition_set.order_by('expedition')[0] + + #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 + + +# +# Person's attenance to one Expo +# +class PersonExpedition(TroggleModel): + expedition = models.ForeignKey(Expedition) + person = models.ForeignKey(Person) + slugfield = models.SlugField(max_length=50,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('survexblock'): + if res and res[-1]['survexpath'] == personrole.survexblock.survexpath: + res[-1]['roles'] += ", " + str(personrole.role) + else: + res.append({'date':personrole.survexblock.date, 'survexpath':personrole.survexblock.survexpath, 'roles':str(personrole.role)}) + return res + + class Meta: + ordering = ('-expedition',) + #order_with_respect_to = 'expedition' + + 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 urlparse.urljoin(settings.URL_ROOT, reverse('personexpedition',kwargs={'first_name':self.person.first_name,'last_name':self.person.last_name,'year':self.expedition.year})) + + def surveyedleglength(self): + survexblocks = [personrole.survexblock for personrole in self.personrole_set.all() ] + return sum([survexblock.totalleglength for survexblock in set(survexblocks)]) + + # would prefer to return actual person trips so we could link to first and last ones + def day_min(self): + res = self.persontrip_set.aggregate(day_min=Min("expeditionday__date")) + return res["day_min"] + + def day_max(self): + res = self.persontrip_set.all().aggregate(day_max=Max("expeditionday__date")) + return res["day_max"] + +# +# Single parsed entry from Logbook +# +class LogbookEntry(TroggleModel): + date = models.DateField()#MJG wants to turn this into a datetime such that multiple Logbook entries on the same day can be ordered. + expeditionday = models.ForeignKey("ExpeditionDay", null=True)#MJG wants to KILL THIS (redundant information) + 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 + #MJG wants to KILL THIS, as it is typically redundant with PersonTrip.is_logbook_entry_author, in the rare it was not redundanty and of actually interest it could be added to the text. + title = models.CharField(max_length=settings.MAX_LOGBOOK_ENTRY_TITLE_LENGTH) + 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) + filename= models.CharField(max_length=200,null=True) + + class Meta: + verbose_name_plural = "Logbook Entries" + # several PersonTrips point in to this object + ordering = ('-date',) + + def isLogbookEntry(self): # Function used in templates + return True + + 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) + + def new_QM_number(self): + """Returns """ + if self.cave: + nextQMnumber=self.cave.new_QM_number(self.date.year) + else: + return none + return nextQMnumber + + def new_QM_found_link(self): + """Produces a link to a new QM with the next number filled in and this LogbookEntry set as 'found by' """ + return settings.URL_ROOT + r'/admin/core/qm/add/?' + r'found_by=' + str(self.pk) +'&number=' + str(self.new_QM_number()) + + def DayIndex(self): + return list(self.expeditionday.logbookentry_set.all()).index(self) + +# +# Single Person going on a trip, which may or may not be written up (accounts for different T/U for people in same logbook entry) +# +class PersonTrip(TroggleModel): + personexpedition = models.ForeignKey("PersonExpedition",null=True) + + #expeditionday = models.ForeignKey("ExpeditionDay")#MJG wants to KILL THIS (redundant information) + #date = models.DateField() #MJG wants to KILL THIS (redundant information) + time_underground = models.FloatField(help_text="In decimal hours") + logbook_entry = models.ForeignKey(LogbookEntry) + is_logbook_entry_author = models.BooleanField() + + + # sequencing by person (difficult to solve locally) + #persontrip_next = models.ForeignKey('PersonTrip', related_name='pnext', blank=True,null=True)#MJG wants to KILL THIS (and use funstion persontrip_next_auto) + #persontrip_prev = models.ForeignKey('PersonTrip', related_name='pprev', blank=True,null=True)#MJG wants to KILL THIS(and use funstion persontrip_prev_auto) + + def persontrip_next(self): + futurePTs = PersonTrip.objects.filter(personexpedition = self.personexpedition, logbook_entry__date__gt = self.logbook_entry.date).order_by('logbook_entry__date').all() + if len(futurePTs) > 0: + return futurePTs[0] + else: + return None + + def persontrip_prev(self): + pastPTs = PersonTrip.objects.filter(personexpedition = self.personexpedition, logbook_entry__date__lt = self.logbook_entry.date).order_by('-logbook_entry__date').all() + if len(pastPTs) > 0: + return pastPTs[0] + else: + return None + + def place(self): + return self.logbook_entry.cave and self.logbook_entry.cave or self.logbook_entry.place + + def __unicode__(self): + return "%s (%s)" % (self.personexpedition, self.logbook_entry.date) + + + +########################################## +# 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 + slug = models.SlugField(max_length=50, unique = True) + 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) + url = models.CharField(max_length=200,blank=True,null=True) + + #class Meta: + # unique_together = (("area", "kataster_number"), ("area", "unofficial_number")) + # FIXME Kataster Areas and CUCC defined sub areas need seperating + + + #href = models.CharField(max_length=100) + + def reference(self): + if self.kataster_number: + return "%s-%s" % (self.kat_area(), self.kataster_number) + else: + return "%s-%s" % (self.kat_area(), self.unofficial_number) + + 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 new_QM_number(self, year=datetime.date.today().year): + """Given a cave and the current year, returns the next QM number.""" + try: + res=QM.objects.filter(found_by__date__year=year, found_by__cave=self).order_by('-number')[0] + except IndexError: + return 1 + return res.number+1 + + 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 += "–" + prevR + else: + prevR = r + n = 0 + res += r + if n == 0: + res += ", " + prevR + else: + res += "–" + prevR + return res + +def getCaveByReference(reference): + areaname, code = reference.split("-", 1) + print areaname, code + area = Area.objects.get(short_name = areaname) + print area + foundCaves = list(Cave.objects.filter(area = area, kataster_number = code).all()) + list(Cave.objects.filter(area = area, unofficial_number = code).all()) + print list(foundCaves) + assert len(foundCaves) == 1 + return foundCaves[0] + +class OtherCaveName(TroggleModel): + name = models.CharField(max_length=160) + cave = models.ForeignKey(Cave) + def __unicode__(self): + return unicode(self.name) + + +class Entrance(TroggleModel): + slug = models.SlugField(max_length=50, unique = True) + 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.TextField() + exact_station = models.TextField() + other_station = models.TextField() + 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] + + + 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 + +class CaveDescription(TroggleModel): + short_name = models.CharField(max_length=50, unique = True) + long_name = models.CharField(max_length=200, blank=True, null=True) + description = models.TextField(blank=True,null=True) + linked_subcaves = models.ManyToManyField("NewSubCave", blank=True,null=True) + linked_entrances = models.ManyToManyField("Entrance", blank=True,null=True) + linked_qms = models.ManyToManyField("QM", blank=True,null=True) + + def __unicode__(self): + if self.long_name: + return unicode(self.long_name) + else: + return unicode(self.short_name) + + def get_absolute_url(self): + return urlparse.urljoin(settings.URL_ROOT, reverse('cavedescription', args=(self.short_name,))) + + def save(self): + """ + Overridden save method which stores wikilinks in text as links in database. + """ + super(CaveDescription, self).save() + qm_list=get_related_by_wikilinks(self.description) + for qm in qm_list: + self.linked_qms.add(qm) + super(CaveDescription, self).save() + +class NewSubCave(TroggleModel): + name = models.CharField(max_length=200, unique = True) + def __unicode__(self): + return unicode(self.name) + +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) + #cave = models.ForeignKey(Cave) + #expedition = models.ForeignKey(Expedition) + + 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) + + def __unicode__(self): + return u"%s %s" % (self.code(), self.grade) + + def code(self): + return u"%s-%s-%s" % (unicode(self.found_by.cave)[6:], self.found_by.date.year, self.number) + + 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): + return u"%s%s%s" % ('[[QM:',self.code(),']]') + +photoFileStorage = FileSystemStorage(location=settings.PHOTOS_ROOT, base_url=settings.PHOTOS_URL) +class DPhoto(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('NewSubCave', 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') diff --git a/core/models_survex.py b/core/models_survex.py index efd3022..1bf75ef 100644 --- a/core/models_survex.py +++ b/core/models_survex.py @@ -1,213 +1,213 @@ -from django.db import models
-from django.conf import settings
-import os
-import urlparse
-import re
-from django.core.urlresolvers import reverse
-
-
-###########################################################
-# These will allow browsing and editing of the survex data
-###########################################################
-# Needs to add:
-# Equates
-# reloading
-
-class SurvexDirectory(models.Model):
- path = models.CharField(max_length=200)
- cave = models.ForeignKey('Cave', blank=True, null=True)
- primarysurvexfile = models.ForeignKey('SurvexFile', related_name='primarysurvexfile', blank=True, null=True)
- # could also include files in directory but not referenced
-
- class Meta:
- ordering = ('id',)
-
-class SurvexFile(models.Model):
- path = models.CharField(max_length=200)
- survexdirectory = models.ForeignKey("SurvexDirectory", blank=True, null=True)
- cave = models.ForeignKey('Cave', blank=True, null=True)
-
- class Meta:
- ordering = ('id',)
-
- def exists(self):
- fname = os.path.join(settings.SURVEX_DATA, self.path + ".svx")
- return os.path.isfile(fname)
-
- def OpenFile(self):
- fname = os.path.join(settings.SURVEX_DATA, self.path + ".svx")
- return open(fname)
-
- def SetDirectory(self):
- dirpath = os.path.split(self.path)[0]
- survexdirectorylist = SurvexDirectory.objects.filter(cave=self.cave, path=dirpath)
- if survexdirectorylist:
- self.survexdirectory = survexdirectorylist[0]
- else:
- survexdirectory = SurvexDirectory(path=dirpath, cave=self.cave, primarysurvexfile=self)
- survexdirectory.save()
- self.survexdirectory = survexdirectory
- self.save()
-
-class SurvexEquate(models.Model):
- cave = models.ForeignKey('Cave', blank=True, null=True)
-
-class SurvexStationLookUpManager(models.Manager):
- def lookup(self, name):
- blocknames, sep, stationname = name.rpartition(".")
- return self.get(block = SurvexBlock.objects.lookup(blocknames),
- name = stationname)
-
-class SurvexStation(models.Model):
- name = models.CharField(max_length=20)
- block = models.ForeignKey('SurvexBlock')
- equate = models.ForeignKey('SurvexEquate', blank=True, null=True)
- objects = SurvexStationLookUpManager()
- x = models.FloatField(blank=True, null=True)
- y = models.FloatField(blank=True, null=True)
- z = models.FloatField(blank=True, null=True)
-
-class SurvexLeg(models.Model):
- block = models.ForeignKey('SurvexBlock')
- #title = models.ForeignKey('SurvexTitle')
- stationfrom = models.ForeignKey('SurvexStation', related_name='stationfrom')
- stationto = models.ForeignKey('SurvexStation', related_name='stationto')
- tape = models.FloatField()
- compass = models.FloatField()
- clino = models.FloatField()
-
-
-#
-# Single SurvexBlock
-#
-class SurvexBlockLookUpManager(models.Manager):
- def lookup(self, name):
- blocknames = name.split(".")
- block = SurvexBlock.objects.get(parent=None, survexfile__path="all")
- for blockname in blocknames:
- block = SurvexBlock.objects.get(parent=block, name=blockname)
- return block
-
-class SurvexBlock(models.Model):
- objects = SurvexBlockLookUpManager()
- name = models.CharField(max_length=100)
- parent = models.ForeignKey('SurvexBlock', blank=True, null=True)
- text = models.TextField()
- cave = models.ForeignKey('Cave', blank=True, null=True)
-
- date = models.DateField(blank=True, null=True)
- expeditionday = models.ForeignKey("ExpeditionDay", null=True)
- expedition = models.ForeignKey('Expedition', blank=True, null=True)
-
- survexfile = models.ForeignKey("SurvexFile", blank=True, null=True)
- begin_char = models.IntegerField() # code for where in the survex data files this block sits
- survexpath = models.CharField(max_length=200) # the path for the survex stations
-
- survexscansfolder = models.ForeignKey("SurvexScansFolder", null=True)
- #refscandir = models.CharField(max_length=100)
-
- totalleglength = models.FloatField()
-
- class Meta:
- ordering = ('id',)
-
- def isSurvexBlock(self): # Function used in templates
- return True
-
- def __unicode__(self):
- return self.name and unicode(self.name) or 'no name'
-
- 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)})
- return res
-
- def MakeSurvexStation(self, name):
- ssl = self.survexstation_set.filter(name=name)
- if ssl:
- assert len(ssl) == 1
- return ssl[0]
- ss = SurvexStation(name=name, block=self)
- ss.save()
- return ss
-
- def DayIndex(self):
- return list(self.expeditionday.survexblock_set.all()).index(self)
-
-
-class SurvexTitle(models.Model):
- survexblock = models.ForeignKey('SurvexBlock')
- title = models.CharField(max_length=200)
- cave = models.ForeignKey('Cave', blank=True, null=True)
-
-#
-# member of a SurvexBlock
-#
-ROLE_CHOICES = (
- ('insts','Instruments'),
- ('dog','Other'),
- ('notes','Notes'),
- ('pics','Pictures'),
- ('tape','Tape measure'),
- ('useless','Useless'),
- ('helper','Helper'),
- ('disto','Disto'),
- ('consultant','Consultant'),
- )
-
-class SurvexPersonRole(models.Model):
- survexblock = models.ForeignKey('SurvexBlock')
- nrole = models.CharField(choices=ROLE_CHOICES, max_length=200, blank=True, null=True)
- # increasing levels of precision
- personname = models.CharField(max_length=100)
- person = models.ForeignKey('Person', blank=True, null=True)
- personexpedition = models.ForeignKey('PersonExpedition', blank=True, null=True)
- persontrip = models.ForeignKey('PersonTrip', blank=True, null=True)
- expeditionday = models.ForeignKey("ExpeditionDay", null=True)
-
- def __unicode__(self):
- return unicode(self.person) + " - " + unicode(self.survexblock) + " - " + unicode(self.nrole)
-
-
-class SurvexScansFolder(models.Model):
- fpath = models.CharField(max_length=200)
- walletname = models.CharField(max_length=200)
-
- class Meta:
- ordering = ('walletname',)
-
- def get_absolute_url(self):
- return urlparse.urljoin(settings.URL_ROOT, reverse('surveyscansfolder', kwargs={"path":re.sub("#", "%23", self.walletname)}))
-
-class SurvexScanSingle(models.Model):
- ffile = models.CharField(max_length=200)
- name = models.CharField(max_length=200)
- survexscansfolder = models.ForeignKey("SurvexScansFolder", null=True)
-
- class Meta:
- ordering = ('name',)
-
- def get_absolute_url(self):
- return urlparse.urljoin(settings.URL_ROOT, reverse('surveyscansingle', kwargs={"path":re.sub("#", "%23", self.survexscansfolder.walletname), "file":self.name}))
-
-
-class TunnelFile(models.Model):
- tunnelpath = models.CharField(max_length=200)
- tunnelname = models.CharField(max_length=200)
- bfontcolours = models.BooleanField()
- survexscansfolders = models.ManyToManyField("SurvexScansFolder")
- survexscans = models.ManyToManyField("SurvexScanSingle")
- survexblocks = models.ManyToManyField("SurvexBlock")
- tunnelcontains = models.ManyToManyField("TunnelFile") # case when its a frame type
- filesize = models.IntegerField(default=0)
- npaths = models.IntegerField(default=0)
- survextitles = models.ManyToManyField("SurvexTitle")
-
-
- class Meta:
- ordering = ('tunnelpath',)
-
+from django.db import models +from django.conf import settings +import os +import urlparse +import re +from django.core.urlresolvers import reverse + + +########################################################### +# These will allow browsing and editing of the survex data +########################################################### +# Needs to add: +# Equates +# reloading + +class SurvexDirectory(models.Model): + path = models.CharField(max_length=200) + cave = models.ForeignKey('Cave', blank=True, null=True) + primarysurvexfile = models.ForeignKey('SurvexFile', related_name='primarysurvexfile', blank=True, null=True) + # could also include files in directory but not referenced + + class Meta: + ordering = ('id',) + +class SurvexFile(models.Model): + path = models.CharField(max_length=200) + survexdirectory = models.ForeignKey("SurvexDirectory", blank=True, null=True) + cave = models.ForeignKey('Cave', blank=True, null=True) + + class Meta: + ordering = ('id',) + + def exists(self): + fname = os.path.join(settings.SURVEX_DATA, self.path + ".svx") + return os.path.isfile(fname) + + def OpenFile(self): + fname = os.path.join(settings.SURVEX_DATA, self.path + ".svx") + return open(fname) + + def SetDirectory(self): + dirpath = os.path.split(self.path)[0] + survexdirectorylist = SurvexDirectory.objects.filter(cave=self.cave, path=dirpath) + if survexdirectorylist: + self.survexdirectory = survexdirectorylist[0] + else: + survexdirectory = SurvexDirectory(path=dirpath, cave=self.cave, primarysurvexfile=self) + survexdirectory.save() + self.survexdirectory = survexdirectory + self.save() + +class SurvexEquate(models.Model): + cave = models.ForeignKey('Cave', blank=True, null=True) + +class SurvexStationLookUpManager(models.Manager): + def lookup(self, name): + blocknames, sep, stationname = name.rpartition(".") + return self.get(block = SurvexBlock.objects.lookup(blocknames), + name = stationname) + +class SurvexStation(models.Model): + name = models.CharField(max_length=20) + block = models.ForeignKey('SurvexBlock') + equate = models.ForeignKey('SurvexEquate', blank=True, null=True) + objects = SurvexStationLookUpManager() + x = models.FloatField(blank=True, null=True) + y = models.FloatField(blank=True, null=True) + z = models.FloatField(blank=True, null=True) + +class SurvexLeg(models.Model): + block = models.ForeignKey('SurvexBlock') + #title = models.ForeignKey('SurvexTitle') + stationfrom = models.ForeignKey('SurvexStation', related_name='stationfrom') + stationto = models.ForeignKey('SurvexStation', related_name='stationto') + tape = models.FloatField() + compass = models.FloatField() + clino = models.FloatField() + + +# +# Single SurvexBlock +# +class SurvexBlockLookUpManager(models.Manager): + def lookup(self, name): + blocknames = name.split(".") + block = SurvexBlock.objects.get(parent=None, survexfile__path="all") + for blockname in blocknames: + block = SurvexBlock.objects.get(parent=block, name=blockname) + return block + +class SurvexBlock(models.Model): + objects = SurvexBlockLookUpManager() + name = models.CharField(max_length=100) + parent = models.ForeignKey('SurvexBlock', blank=True, null=True) + text = models.TextField() + cave = models.ForeignKey('Cave', blank=True, null=True) + + date = models.DateField(blank=True, null=True) + expeditionday = models.ForeignKey("ExpeditionDay", null=True) + expedition = models.ForeignKey('Expedition', blank=True, null=True) + + survexfile = models.ForeignKey("SurvexFile", blank=True, null=True) + begin_char = models.IntegerField() # code for where in the survex data files this block sits + survexpath = models.CharField(max_length=200) # the path for the survex stations + + survexscansfolder = models.ForeignKey("SurvexScansFolder", null=True) + #refscandir = models.CharField(max_length=100) + + totalleglength = models.FloatField() + + class Meta: + ordering = ('id',) + + def isSurvexBlock(self): # Function used in templates + return True + + def __unicode__(self): + return self.name and unicode(self.name) or 'no name' + + 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)}) + return res + + def MakeSurvexStation(self, name): + ssl = self.survexstation_set.filter(name=name) + if ssl: + assert len(ssl) == 1 + return ssl[0] + ss = SurvexStation(name=name, block=self) + ss.save() + return ss + + def DayIndex(self): + return list(self.expeditionday.survexblock_set.all()).index(self) + + +class SurvexTitle(models.Model): + survexblock = models.ForeignKey('SurvexBlock') + title = models.CharField(max_length=200) + cave = models.ForeignKey('Cave', blank=True, null=True) + +# +# member of a SurvexBlock +# +ROLE_CHOICES = ( + ('insts','Instruments'), + ('dog','Other'), + ('notes','Notes'), + ('pics','Pictures'), + ('tape','Tape measure'), + ('useless','Useless'), + ('helper','Helper'), + ('disto','Disto'), + ('consultant','Consultant'), + ) + +class SurvexPersonRole(models.Model): + survexblock = models.ForeignKey('SurvexBlock') + nrole = models.CharField(choices=ROLE_CHOICES, max_length=200, blank=True, null=True) + # increasing levels of precision + personname = models.CharField(max_length=100) + person = models.ForeignKey('Person', blank=True, null=True) + personexpedition = models.ForeignKey('PersonExpedition', blank=True, null=True) + persontrip = models.ForeignKey('PersonTrip', blank=True, null=True) + expeditionday = models.ForeignKey("ExpeditionDay", null=True) + + def __unicode__(self): + return unicode(self.person) + " - " + unicode(self.survexblock) + " - " + unicode(self.nrole) + + +class SurvexScansFolder(models.Model): + fpath = models.CharField(max_length=200) + walletname = models.CharField(max_length=200) + + class Meta: + ordering = ('walletname',) + + def get_absolute_url(self): + return urlparse.urljoin(settings.URL_ROOT, reverse('surveyscansfolder', kwargs={"path":re.sub("#", "%23", self.walletname)})) + +class SurvexScanSingle(models.Model): + ffile = models.CharField(max_length=200) + name = models.CharField(max_length=200) + survexscansfolder = models.ForeignKey("SurvexScansFolder", null=True) + + class Meta: + ordering = ('name',) + + def get_absolute_url(self): + return urlparse.urljoin(settings.URL_ROOT, reverse('surveyscansingle', kwargs={"path":re.sub("#", "%23", self.survexscansfolder.walletname), "file":self.name})) + + +class TunnelFile(models.Model): + tunnelpath = models.CharField(max_length=200) + tunnelname = models.CharField(max_length=200) + bfontcolours = models.BooleanField() + survexscansfolders = models.ManyToManyField("SurvexScansFolder") + survexscans = models.ManyToManyField("SurvexScanSingle") + survexblocks = models.ManyToManyField("SurvexBlock") + tunnelcontains = models.ManyToManyField("TunnelFile") # case when its a frame type + filesize = models.IntegerField(default=0) + npaths = models.IntegerField(default=0) + survextitles = models.ManyToManyField("SurvexTitle") + + + class Meta: + ordering = ('tunnelpath',) + diff --git a/core/templatetags/link.py b/core/templatetags/link.py index 63e2dac..cb861ad 100644 --- a/core/templatetags/link.py +++ b/core/templatetags/link.py @@ -1,9 +1,9 @@ -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>")
-
+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>") + diff --git a/core/templatetags/survex_markup.py b/core/templatetags/survex_markup.py index 464a04b..5b9aa36 100644 --- a/core/templatetags/survex_markup.py +++ b/core/templatetags/survex_markup.py @@ -1,52 +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 </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)
+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 </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)
\ No newline at end of file diff --git a/core/templatetags/wiki_markup.py b/core/templatetags/wiki_markup.py index 810634b..4087b12 100644 --- a/core/templatetags/wiki_markup.py +++ b/core/templatetags/wiki_markup.py @@ -1,169 +1,169 @@ -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, DPhoto, LogbookEntry, Cave
-import re, urlparse
-
-register = template.Library()
-
-
-@register.filter()
-def plusone(n):
- return n + 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):
- """
- This is the tag which turns wiki syntax into html. It is intended for long pieces of wiki.
- Hence it splits the wiki into HTML paragraphs based on double line feeds.
- """
- #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. It is intended for short pieces of wiki.
- Hence it is not split the wiki into paragraphs using where it finds double line feeds.
- """
- if autoescape:
- value = conditional_escape(value)
- #deescape doubly escaped characters
- value = re.sub("&(.*?);", r"&\1;", value, re.DOTALL)
- #italics and bold
- value = re.sub("''''([^']+)''''", r"<b><i>\1</i></b>", value, re.DOTALL)
- value = re.sub("'b''([^']+)'''", r"<b>\1</b>", value, re.DOTALL)
- value = re.sub("''([^']+)''", r"<i>\1</i>", value, re.DOTALL)
-
- #make headers
- def headerrepl(matchobj):
- number=len(matchobj.groups()[0])
- num=str(number)
- if number>1:
- return '<h'+num+'>'+matchobj.groups()[1]+'</h'+num+'>'
- else:
- print 'morethanone'
- return matchobj.group()
- value = re.sub(r"(?m)^(=+)([^=]+)(=+)$",headerrepl,value)
-
- #make qm links. this takes a little doing
- qmMatchPattern=settings.QM_PATTERN
- def qmrepl(matchobj):
- """
- A function for replacing wikicode qm links with html qm links.
- Given a matchobj matching a wikilink in the format
- [[QM:C204-1999-24]]
- If the QM does not exist, the function will return a link for creating it.
- """
- qmdict={'urlroot':settings.URL_ROOT,'cave':matchobj.groups()[2],'year':matchobj.groups()[1],'number':matchobj.groups()[3]}
- try:
- qm=QM.objects.get(found_by__cave__kataster_number = qmdict['cave'],
- found_by__date__year = qmdict['year'],
- number = qmdict['number'])
- return r'<a href="%s" id="q%s">%s</a>' % (qm.get_absolute_url(), qm.code, unicode(qm))
- except QM.DoesNotExist: #bother aaron to make him clean up the below code - AC
- try:
- placeholder=LogbookEntry.objects.get(date__year=qmdict['year'],cave__kataster_number=qmdict['cave'], title__icontains='placeholder')
- except LogbookEntry.DoesNotExist:
- placeholder=LogbookEntry(
- date='01-01'+qmdict['year'],
- cave=Cave.objects.get(kataster_number=qmdict['cave']),
- title='placeholder'
- )
- qm=QM(found_by = placeholder, number = qmdict['number'])
- return r'<a class="redtext" href="%s" id="q%s">%s</a>' % (qm.get_absolute_url(), qm.code, unicode(qm))
-
- 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=DPhoto.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 cave links
- value = re.sub("\[\[\s*cave:([^\s]+)\s*\s*\]\]", r'<a href="%scave/\1/">\1</a>' % settings.URL_ROOT, value, re.DOTALL)
- #make people links
- value = re.sub("\[\[\s*person:(.+)\|(.+)\]\]",r'<a href="%sperson/\1/">\2</a>' % settings.URL_ROOT, value, re.DOTALL)
- #make subcave links
- value = re.sub("\[\[\s*subcave:(.+)\|(.+)\]\]",r'<a href="%ssubcave/\1/">\2</a>' % settings.URL_ROOT, value, re.DOTALL)
- #make cavedescription links
- value = re.sub("\[\[\s*cavedescription:(.+)\|(.+)\]\]",r'<a href="%scavedescription/\1/">\2</a>' % settings.URL_ROOT, 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
+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, DPhoto, LogbookEntry, Cave +import re, urlparse + +register = template.Library() + + +@register.filter() +def plusone(n): + return n + 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): + """ + This is the tag which turns wiki syntax into html. It is intended for long pieces of wiki. + Hence it splits the wiki into HTML paragraphs based on double line feeds. + """ + #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. It is intended for short pieces of wiki. + Hence it is not split the wiki into paragraphs using where it finds double line feeds. + """ + if autoescape: + value = conditional_escape(value) + #deescape doubly escaped characters + value = re.sub("&(.*?);", r"&\1;", value, re.DOTALL) + #italics and bold + value = re.sub("''''([^']+)''''", r"<b><i>\1</i></b>", value, re.DOTALL) + value = re.sub("'b''([^']+)'''", r"<b>\1</b>", value, re.DOTALL) + value = re.sub("''([^']+)''", r"<i>\1</i>", value, re.DOTALL) + + #make headers + def headerrepl(matchobj): + number=len(matchobj.groups()[0]) + num=str(number) + if number>1: + return '<h'+num+'>'+matchobj.groups()[1]+'</h'+num+'>' + else: + print 'morethanone' + return matchobj.group() + value = re.sub(r"(?m)^(=+)([^=]+)(=+)$",headerrepl,value) + + #make qm links. this takes a little doing + qmMatchPattern=settings.QM_PATTERN + def qmrepl(matchobj): + """ + A function for replacing wikicode qm links with html qm links. + Given a matchobj matching a wikilink in the format + [[QM:C204-1999-24]] + If the QM does not exist, the function will return a link for creating it. + """ + qmdict={'urlroot':settings.URL_ROOT,'cave':matchobj.groups()[2],'year':matchobj.groups()[1],'number':matchobj.groups()[3]} + try: + qm=QM.objects.get(found_by__cave__kataster_number = qmdict['cave'], + found_by__date__year = qmdict['year'], + number = qmdict['number']) + return r'<a href="%s" id="q%s">%s</a>' % (qm.get_absolute_url(), qm.code, unicode(qm)) + except QM.DoesNotExist: #bother aaron to make him clean up the below code - AC + try: + placeholder=LogbookEntry.objects.get(date__year=qmdict['year'],cave__kataster_number=qmdict['cave'], title__icontains='placeholder') + except LogbookEntry.DoesNotExist: + placeholder=LogbookEntry( + date='01-01'+qmdict['year'], + cave=Cave.objects.get(kataster_number=qmdict['cave']), + title='placeholder' + ) + qm=QM(found_by = placeholder, number = qmdict['number']) + return r'<a class="redtext" href="%s" id="q%s">%s</a>' % (qm.get_absolute_url(), qm.code, unicode(qm)) + + 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=DPhoto.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 cave links + value = re.sub("\[\[\s*cave:([^\s]+)\s*\s*\]\]", r'<a href="%scave/\1/">\1</a>' % settings.URL_ROOT, value, re.DOTALL) + #make people links + value = re.sub("\[\[\s*person:(.+)\|(.+)\]\]",r'<a href="%sperson/\1/">\2</a>' % settings.URL_ROOT, value, re.DOTALL) + #make subcave links + value = re.sub("\[\[\s*subcave:(.+)\|(.+)\]\]",r'<a href="%ssubcave/\1/">\2</a>' % settings.URL_ROOT, value, re.DOTALL) + #make cavedescription links + value = re.sub("\[\[\s*cavedescription:(.+)\|(.+)\]\]",r'<a href="%scavedescription/\1/">\2</a>' % settings.URL_ROOT, 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 diff --git a/core/view_surveys.py b/core/view_surveys.py index 66aa1ed..a6df780 100644 --- a/core/view_surveys.py +++ b/core/view_surveys.py @@ -1,233 +1,233 @@ -from django.conf import settings
-import fileAbstraction
-from django.shortcuts import render_to_response
-from django.http import HttpResponse, Http404
-import os, stat
-import re
-from troggle.core.models import SurvexScansFolder, SurvexScanSingle, SurvexBlock, TunnelFile
-import parsers.surveys
-
-# 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",
- }
-
-# dead
-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})
-
-def surveyscansfolder(request, path):
- #print [ s.walletname for s in SurvexScansFolder.objects.all() ]
- survexscansfolder = SurvexScansFolder.objects.get(walletname=path)
- return render_to_response('survexscansfolder.html', { 'survexscansfolder':survexscansfolder, 'settings': settings })
-
-def surveyscansingle(request, path, file):
- survexscansfolder = SurvexScansFolder.objects.get(walletname=path)
- survexscansingle = SurvexScanSingle.objects.get(survexscansfolder=survexscansfolder, name=file)
- return HttpResponse(content=open(survexscansingle.ffile), mimetype="image/png")
- #return render_to_response('survexscansfolder.html', { 'survexscansfolder':survexscansfolder, 'settings': settings })
-
-def surveyscansfolders(request):
- survexscansfolders = SurvexScansFolder.objects.all()
- return render_to_response('survexscansfolders.html', { 'survexscansfolders':survexscansfolders, 'settings': settings })
-
-
-def tunneldata(request):
- tunnelfiles = TunnelFile.objects.all()
- return render_to_response('tunnelfiles.html', { 'tunnelfiles':tunnelfiles, 'settings': settings })
-
-
-def tunnelfile(request, path):
- tunnelfile = TunnelFile.objects.get(tunnelpath=path)
- tfile = os.path.join(settings.TUNNEL_DATA, tunnelfile.tunnelpath)
- return HttpResponse(content=open(tfile), mimetype="text/plain")
-
-def tunnelfileupload(request, path):
- tunnelfile = TunnelFile.objects.get(tunnelpath=path)
- tfile = os.path.join(settings.TUNNEL_DATA, tunnelfile.tunnelpath)
-
- project, user, password, tunnelversion = request.POST["tunnelproject"], request.POST["tunneluser"], request.POST["tunnelpassword"], request.POST["tunnelversion"]
- print (project, user, tunnelversion)
-
-
- assert len(request.FILES.values()) == 1, "only one file to upload"
-
- uploadedfile = request.FILES.values()[0]
-
- if uploadedfile.field_name != "sketch":
- return HttpResponse(content="Error: non-sketch file uploaded", mimetype="text/plain")
- if uploadedfile.content_type != "text/plain":
- return HttpResponse(content="Error: non-plain content type", mimetype="text/plain")
-
- # could use this to add new files
- if os.path.split(path)[1] != uploadedfile.name:
- return HttpResponse(content="Error: name disagrees", mimetype="text/plain")
-
- orgsize = tunnelfile.filesize # = os.stat(tfile)[stat.ST_SIZE]
-
- ttext = uploadedfile.read()
-
- # could check that the user and projects agree here
-
- fout = open(tfile, "w")
- fout.write(ttext)
- fout.close()
-
- # redo its settings of
- parsers.surveys.SetTunnelfileInfo(tunnelfile)
- tunnelfile.save()
-
- uploadedfile.close()
- message = "File size %d overwritten with size %d" % (orgsize, tunnelfile.filesize)
- return HttpResponse(content=message, mimetype="text/plain")
-
-
-
-
+from django.conf import settings +import fileAbstraction +from django.shortcuts import render_to_response +from django.http import HttpResponse, Http404 +import os, stat +import re +from troggle.core.models import SurvexScansFolder, SurvexScanSingle, SurvexBlock, TunnelFile +import parsers.surveys + +# 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", + } + +# dead +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}) + +def surveyscansfolder(request, path): + #print [ s.walletname for s in SurvexScansFolder.objects.all() ] + survexscansfolder = SurvexScansFolder.objects.get(walletname=path) + return render_to_response('survexscansfolder.html', { 'survexscansfolder':survexscansfolder, 'settings': settings }) + +def surveyscansingle(request, path, file): + survexscansfolder = SurvexScansFolder.objects.get(walletname=path) + survexscansingle = SurvexScanSingle.objects.get(survexscansfolder=survexscansfolder, name=file) + return HttpResponse(content=open(survexscansingle.ffile), mimetype="image/png") + #return render_to_response('survexscansfolder.html', { 'survexscansfolder':survexscansfolder, 'settings': settings }) + +def surveyscansfolders(request): + survexscansfolders = SurvexScansFolder.objects.all() + return render_to_response('survexscansfolders.html', { 'survexscansfolders':survexscansfolders, 'settings': settings }) + + +def tunneldata(request): + tunnelfiles = TunnelFile.objects.all() + return render_to_response('tunnelfiles.html', { 'tunnelfiles':tunnelfiles, 'settings': settings }) + + +def tunnelfile(request, path): + tunnelfile = TunnelFile.objects.get(tunnelpath=path) + tfile = os.path.join(settings.TUNNEL_DATA, tunnelfile.tunnelpath) + return HttpResponse(content=open(tfile), mimetype="text/plain") + +def tunnelfileupload(request, path): + tunnelfile = TunnelFile.objects.get(tunnelpath=path) + tfile = os.path.join(settings.TUNNEL_DATA, tunnelfile.tunnelpath) + + project, user, password, tunnelversion = request.POST["tunnelproject"], request.POST["tunneluser"], request.POST["tunnelpassword"], request.POST["tunnelversion"] + print (project, user, tunnelversion) + + + assert len(request.FILES.values()) == 1, "only one file to upload" + + uploadedfile = request.FILES.values()[0] + + if uploadedfile.field_name != "sketch": + return HttpResponse(content="Error: non-sketch file uploaded", mimetype="text/plain") + if uploadedfile.content_type != "text/plain": + return HttpResponse(content="Error: non-plain content type", mimetype="text/plain") + + # could use this to add new files + if os.path.split(path)[1] != uploadedfile.name: + return HttpResponse(content="Error: name disagrees", mimetype="text/plain") + + orgsize = tunnelfile.filesize # = os.stat(tfile)[stat.ST_SIZE] + + ttext = uploadedfile.read() + + # could check that the user and projects agree here + + fout = open(tfile, "w") + fout.write(ttext) + fout.close() + + # redo its settings of + parsers.surveys.SetTunnelfileInfo(tunnelfile) + tunnelfile.save() + + uploadedfile.close() + message = "File size %d overwritten with size %d" % (orgsize, tunnelfile.filesize) + return HttpResponse(content=message, mimetype="text/plain") + + + + diff --git a/core/views.py b/core/views.py index 337989a..26c2e52 100644 --- a/core/views.py +++ b/core/views.py @@ -1,8 +1,8 @@ -# primary namespace
-
-import view_surveys
-import views_caves
-import views_survex
-import views_logbooks
-import views_other
-
+# primary namespace + +import view_surveys +import views_caves +import views_survex +import views_logbooks +import views_other + diff --git a/core/views_caves.py b/core/views_caves.py index d078338..4a79652 100644 --- a/core/views_caves.py +++ b/core/views_caves.py @@ -1,141 +1,141 @@ -from troggle.core.models import Cave, CaveAndEntrance, Survey, Expedition, QM, CaveDescription
-from troggle.core.forms import CaveForm
-import troggle.core.models as models
-import troggle.settings as settings
-from troggle.helper import login_required_if_public
-
-from django.forms.models import formset_factory
-from django.core.urlresolvers import reverse
-from utils import render_with_context # see views_logbooks for explanation on this.
-from django.http import HttpResponseRedirect
-from django.conf import settings
-import re, urlparse
-from django.shortcuts import get_object_or_404
-
-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 ]
- caves1623 = Cave.objects.filter(area__short_name = "1623")
- caves1626 = Cave.objects.filter(area__short_name = "1626")
- return render_with_context(request,'caveindex.html', {'caves1623': caves1623, 'caves1626': caves1626, 'notablecaves':notablecaves, 'cavepage': True})
-
-def cave(request, cave_id='', offical_name=''):
- cave=getCave(cave_id)
- if cave.non_public and not request.user.is_authenticated():
- return render_with_context(request,'nonpublic.html', {'instance': cave, 'cavepage': True})
- else:
- return render_with_context(request,'cave.html', {'cave': cave, 'cavepage': True})
-
-def caveEntrance(request, slug):
- cave = Cave.objects.get(slug = slug)
- if cave.non_public and not request.user.is_authenticated():
- return render_with_context(request,'nonpublic.html', {'instance': cave})
- else:
- return render_with_context(request,'cave_entrances.html', {'cave': cave})
-def caveDescription(request, slug):
- cave = Cave.objects.get(slug = slug)
- if cave.non_public and not request.user.is_authenticated():
- return render_with_context(request,'nonpublic.html', {'instance': cave})
- else:
- return render_with_context(request,'cave_uground_description.html', {'cave': cave})
-def caveQMs(request, slug):
- cave = Cave.objects.get(slug = slug)
- if cave.non_public and not request.user.is_authenticated():
- return render_with_context(request,'nonpublic.html', {'instance': cave})
- else:
- return render_with_context(request,'cave_qms.html', {'cave': cave})
-def caveLogbook(request, slug):
- cave = Cave.objects.get(slug = slug)
- if cave.non_public and not request.user.is_authenticated():
- return render_with_context(request,'nonpublic.html', {'instance': cave})
- else:
- return render_with_context(request,'cave_logbook.html', {'cave': cave})
-
-def caveSlug(request, slug):
- cave = Cave.objects.get(slug = slug)
- if cave.non_public and not request.user.is_authenticated():
- return render_with_context(request,'nonpublic.html', {'instance': cave})
- else:
- return render_with_context(request,'cave.html', {'cave': cave})
-
-@login_required_if_public
-def editCave(request, slug=None):
- form = CaveForm()
- return render_with_context(request,
- 'editcave.html',
- {'form': form})
-
-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_with_context(request,'qm.html',locals())
-
- except QM.DoesNotExist:
- url=urlparse.urljoin(settings.URL_ROOT, r'/admin/core/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_with_context(request,'entrance.html', {'cave': cave,
- 'entrance': cave_and_ent.entrance,
- 'letter': cave_and_ent.entrance_letter,})
-
-def entranceSlug(request, slug):
- entrance = Entrance.objects.get(slug = slug)
- if entrance.non_public and not request.user.is_authenticated():
- return render_with_context(request,'nonpublic.html', {'instance': entrance})
- else:
- return render_with_context(request,'entranceslug.html', {'entrance': entrance})
-
-def survexblock(request, survexpath):
- survexpath = re.sub("/", ".", survexpath)
- print "jjjjjj", survexpath
- survexblock = models.SurvexBlock.objects.get(survexpath=survexpath)
- #ftext = survexblock.filecontents()
- ftext = survexblock.text
- return render_with_context(request,'survexblock.html', {'survexblock':survexblock, 'ftext':ftext, })
-
-def surveyindex(request):
- surveys=Survey.objects.all()
- expeditions=Expedition.objects.order_by("-year")
- return render_with_context(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_with_context(request,'survey.html', locals())
-
-def cave_description(request, cavedescription_name):
- cave_description = get_object_or_404(CaveDescription, short_name = cavedescription_name)
- return render_with_context(request,'cave_description.html', locals())
-
-def get_entrances(request, caveslug):
- cave = Cave.objects.get(slug = caveslug)
- return render_with_context(request,'options.html', {"items": [(e.entrance.slug, e.entrance.slug) for e in cave.entrances()]})
-
-def get_qms(request, caveslug):
- cave = Cave.objects.get(slug = caveslug)
- return render_with_context(request,'options.html', {"items": [(e.entrance.slug, e.entrance.slug) for e in cave.entrances()]})
+from troggle.core.models import Cave, CaveAndEntrance, Survey, Expedition, QM, CaveDescription +from troggle.core.forms import CaveForm +import troggle.core.models as models +import troggle.settings as settings +from troggle.helper import login_required_if_public + +from django.forms.models import formset_factory +from django.core.urlresolvers import reverse +from utils import render_with_context # see views_logbooks for explanation on this. +from django.http import HttpResponseRedirect +from django.conf import settings +import re, urlparse +from django.shortcuts import get_object_or_404 + +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 ] + caves1623 = Cave.objects.filter(area__short_name = "1623") + caves1626 = Cave.objects.filter(area__short_name = "1626") + return render_with_context(request,'caveindex.html', {'caves1623': caves1623, 'caves1626': caves1626, 'notablecaves':notablecaves, 'cavepage': True}) + +def cave(request, cave_id='', offical_name=''): + cave=getCave(cave_id) + if cave.non_public and not request.user.is_authenticated(): + return render_with_context(request,'nonpublic.html', {'instance': cave, 'cavepage': True}) + else: + return render_with_context(request,'cave.html', {'cave': cave, 'cavepage': True}) + +def caveEntrance(request, slug): + cave = Cave.objects.get(slug = slug) + if cave.non_public and not request.user.is_authenticated(): + return render_with_context(request,'nonpublic.html', {'instance': cave}) + else: + return render_with_context(request,'cave_entrances.html', {'cave': cave}) +def caveDescription(request, slug): + cave = Cave.objects.get(slug = slug) + if cave.non_public and not request.user.is_authenticated(): + return render_with_context(request,'nonpublic.html', {'instance': cave}) + else: + return render_with_context(request,'cave_uground_description.html', {'cave': cave}) +def caveQMs(request, slug): + cave = Cave.objects.get(slug = slug) + if cave.non_public and not request.user.is_authenticated(): + return render_with_context(request,'nonpublic.html', {'instance': cave}) + else: + return render_with_context(request,'cave_qms.html', {'cave': cave}) +def caveLogbook(request, slug): + cave = Cave.objects.get(slug = slug) + if cave.non_public and not request.user.is_authenticated(): + return render_with_context(request,'nonpublic.html', {'instance': cave}) + else: + return render_with_context(request,'cave_logbook.html', {'cave': cave}) + +def caveSlug(request, slug): + cave = Cave.objects.get(slug = slug) + if cave.non_public and not request.user.is_authenticated(): + return render_with_context(request,'nonpublic.html', {'instance': cave}) + else: + return render_with_context(request,'cave.html', {'cave': cave}) + +@login_required_if_public +def editCave(request, slug=None): + form = CaveForm() + return render_with_context(request, + 'editcave.html', + {'form': form}) + +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_with_context(request,'qm.html',locals()) + + except QM.DoesNotExist: + url=urlparse.urljoin(settings.URL_ROOT, r'/admin/core/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_with_context(request,'entrance.html', {'cave': cave, + 'entrance': cave_and_ent.entrance, + 'letter': cave_and_ent.entrance_letter,}) + +def entranceSlug(request, slug): + entrance = Entrance.objects.get(slug = slug) + if entrance.non_public and not request.user.is_authenticated(): + return render_with_context(request,'nonpublic.html', {'instance': entrance}) + else: + return render_with_context(request,'entranceslug.html', {'entrance': entrance}) + +def survexblock(request, survexpath): + survexpath = re.sub("/", ".", survexpath) + print "jjjjjj", survexpath + survexblock = models.SurvexBlock.objects.get(survexpath=survexpath) + #ftext = survexblock.filecontents() + ftext = survexblock.text + return render_with_context(request,'survexblock.html', {'survexblock':survexblock, 'ftext':ftext, }) + +def surveyindex(request): + surveys=Survey.objects.all() + expeditions=Expedition.objects.order_by("-year") + return render_with_context(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_with_context(request,'survey.html', locals()) + +def cave_description(request, cavedescription_name): + cave_description = get_object_or_404(CaveDescription, short_name = cavedescription_name) + return render_with_context(request,'cave_description.html', locals()) + +def get_entrances(request, caveslug): + cave = Cave.objects.get(slug = caveslug) + return render_with_context(request,'options.html', {"items": [(e.entrance.slug, e.entrance.slug) for e in cave.entrances()]}) + +def get_qms(request, caveslug): + cave = Cave.objects.get(slug = caveslug) + return render_with_context(request,'options.html', {"items": [(e.entrance.slug, e.entrance.slug) for e in cave.entrances()]}) diff --git a/core/views_logbooks.py b/core/views_logbooks.py index 007086f..2cf9163 100644 --- a/core/views_logbooks.py +++ b/core/views_logbooks.py @@ -1,252 +1,252 @@ -from django.shortcuts import render_to_response
-from troggle.core.models import Expedition, Person, PersonExpedition, PersonTrip, LogbookEntry, SurvexBlock
-import troggle.core.models as models
-import troggle.settings as settings
-import django.db.models
-from troggle.parsers.logbooks import LoadLogbookForExpedition
-from troggle.parsers.people import GetPersonExpeditionNameLookup
-#from troggle.core.forms import PersonForm, getTripForm, get_name
-from django.core.urlresolvers import reverse
-from django.http import HttpResponseRedirect, HttpResponse
-from django.template import Context, loader
-from utils import render_with_context
-import os.path
-import troggle.parsers.logbooks as logbookparsers
-from django.template.defaultfilters import slugify
-from troggle.helper import login_required_if_public
-import datetime
-
-
-# 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 re
-
-@django.db.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 = 4
- 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_with_context(request,'personindex.html', {'persons': persons, 'personss':personss, 'notablepersons':notablepersons, })
-
-
-def expedition(request, expeditionname):
- expedition = Expedition.objects.get(year=int(expeditionname))
- expeditions = Expedition.objects.all()
- personexpeditiondays = [ ]
- dateditems = list(expedition.logbookentry_set.all()) + list(expedition.survexblock_set.all())
- dates = list(set([item.date for item in dateditems]))
- dates.sort()
- for personexpedition in expedition.personexpedition_set.all():
- prow = [ ]
- for date in dates:
- pcell = { "persontrips": PersonTrip.objects.filter(personexpedition=personexpedition,
- logbook_entry__date=date) }
- pcell["survexblocks"] = set(SurvexBlock.objects.filter(survexpersonrole__personexpedition=personexpedition,
- date = date))
- prow.append(pcell)
- personexpeditiondays.append({"personexpedition":personexpedition, "personrow":prow})
-
- message = ""
- if "reload" in request.GET:
- message = LoadLogbookForExpedition(expedition)
- return render_with_context(request,'expedition.html', {'expedition': expedition, 'expeditions':expeditions, 'personexpeditiondays':personexpeditiondays, 'message':message, 'settings':settings, 'dateditems': dateditems })
-
- 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_with_context(request,'person.html', {'person': person, })
-
-
-def GetPersonChronology(personexpedition):
- res = { }
- for persontrip in personexpedition.persontrip_set.all():
- a = res.setdefault(persontrip.date, { })
- a.setdefault("persontrips", [ ]).append(persontrip)
-
- for personrole in personexpedition.survexpersonrole_set.all():
- a = res.setdefault(personrole.survexblock.date, { })
- a.setdefault("personroles", [ ]).append(personrole.survexblock)
-
- # build up the tables
- rdates = res.keys()
- rdates.sort()
-
-
- res2 = [ ]
- for rdate in rdates:
- persontrips = res[rdate].get("persontrips", [])
- personroles = res[rdate].get("personroles", [])
- for n in range(max(len(persontrips), len(personroles))):
- res2.append(((n == 0 and rdate or "--"), (n < len(persontrips) and persontrips[n]), (n < len(personroles) and personroles[n])))
-
- return res2
-
-
-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)
- personchronology = GetPersonChronology(personexpedition)
- return render_with_context(request,'personexpedition.html', {'personexpedition': personexpedition, 'personchronology':personchronology})
-
-
-def logbookentry(request, date, slug):
- logbookentry = LogbookEntry.objects.filter(date=date, slug=slug)
-
- if len(logbookentry)>1:
- return render_with_context(request, 'object_list.html',{'object_list':logbookentry})
- else:
- logbookentry=logbookentry[0]
- return render_with_context(request, 'logbookentry.html', {'logbookentry': 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_with_context(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_with_context(request,'personform.html', {'form':form,})
-
-
-def experimental(request):
- legsbyexpo = [ ]
- for expedition in Expedition.objects.all():
- survexblocks = expedition.survexblock_set.all()
- survexlegs = [ ]
- survexleglength = 0.0
- for survexblock in survexblocks:
- survexlegs.extend(survexblock.survexleg_set.all())
- survexleglength += survexblock.totalleglength
- legsbyexpo.append((expedition, {"nsurvexlegs":len(survexlegs), "survexleglength":survexleglength}))
- legsbyexpo.reverse()
-
- survexlegs = models.SurvexLeg.objects.all()
- totalsurvexlength = sum([survexleg.tape for survexleg in survexlegs])
- return render_with_context(request, 'experimental.html', { "nsurvexlegs":len(survexlegs), "totalsurvexlength":totalsurvexlength, "legsbyexpo":legsbyexpo })
-
-@login_required_if_public
-def newLogbookEntry(request, expeditionyear, pdate = None, pslug = None):
- expedition = Expedition.objects.get(year=expeditionyear)
- PersonTripFormSet, TripForm = getTripForm(expedition)
- if pslug and pdate:
- previousdate = datetime.date(*[int(x) for x in pdate.split("-")])
- previouslbe = LogbookEntry.objects.get(slug = pslug, date = previousdate, expedition = expedition)
- assert previouslbe.filename
- if request.method == 'POST': # If the form has been submitted...
- tripForm = TripForm(request.POST) # A form bound to the POST data
- personTripFormSet = PersonTripFormSet(request.POST)
- if tripForm.is_valid() and personTripFormSet.is_valid(): # All validation rules pass
- dateStr = tripForm.cleaned_data["date"].strftime("%Y-%m-%d")
- directory = os.path.join(settings.EXPOWEB,
- "years",
- expedition.year,
- "autologbook")
- filename = os.path.join(directory,
- dateStr + "." + slugify(tripForm.cleaned_data["title"])[:50] + ".html")
- if not os.path.isdir(directory):
- os.mkdir(directory)
- if pslug and pdate:
- delLogbookEntry(previouslbe)
- f = open(filename, "w")
- template = loader.get_template('dataformat/logbookentry.html')
- context = Context({'trip': tripForm.cleaned_data,
- 'persons': personTripFormSet.cleaned_data,
- 'date': dateStr,
- 'expeditionyear': expeditionyear})
- f.write(template.render(context))
- f.close()
- print logbookparsers.parseAutoLogBookEntry(filename)
- return HttpResponseRedirect(reverse('expedition', args=[expedition.year])) # Redirect after POST
- else:
- if pslug and pdate:
- if previouslbe.cave:
- tripForm = TripForm(initial={"date": previousdate,
- "title": previouslbe.title,
- "cave": previouslbe.cave.reference(),
- "location": None,
- "caveOrLocation": "cave",
- "html": previouslbe.text})
- else:
- tripForm = TripForm(initial={"date": previousdate,
- "title": previouslbe.title,
- "cave": None,
- "location": previouslbe.place,
- "caveOrLocation": "location",
- "html": previouslbe.text})
- personTripFormSet = PersonTripFormSet(initial=[{"name": get_name(py.personexpedition),
- "TU": py.time_underground,
- "author": py.is_logbook_entry_author}
- for py in previouslbe.persontrip_set.all()])
- else:
- tripForm = TripForm() # An unbound form
- personTripFormSet = PersonTripFormSet()
-
- return render_with_context(request, 'newlogbookentry.html', {
- 'tripForm': tripForm,
- 'personTripFormSet': personTripFormSet,
-
- })
-
-@login_required_if_public
-def deleteLogbookEntry(request, expeditionyear, date = None, slug = None):
- expedition = Expedition.objects.get(year=expeditionyear)
- previousdate = datetime.date(*[int(x) for x in date.split("-")])
- previouslbe = LogbookEntry.objects.get(slug = slug, date = previousdate, expedition = expedition)
- delLogbookEntry(previouslbe)
- return HttpResponseRedirect(reverse('expedition', args=[expedition.year])) # Redirect after POST
-
-def delLogbookEntry(lbe):
- for pt in lbe.persontrip_set.all():
- pt.delete()
- lbe.delete()
- os.remove(lbe.filename)
-
-def get_people(request, expeditionslug):
- exp = Expedition.objects.get(year = expeditionslug)
- return render_with_context(request,'options.html', {"items": [(pe.slug, pe.name) for pe in exp.personexpedition_set.all()]})
-
-def get_logbook_entries(request, expeditionslug):
- exp = Expedition.objects.get(year = expeditionslug)
- return render_with_context(request,'options.html', {"items": [(le.slug, "%s - %s" % (le.date, le.title)) for le in exp.logbookentry_set.all()]})
-
+from django.shortcuts import render_to_response +from troggle.core.models import Expedition, Person, PersonExpedition, PersonTrip, LogbookEntry, SurvexBlock +import troggle.core.models as models +import troggle.settings as settings +import django.db.models +from troggle.parsers.logbooks import LoadLogbookForExpedition +from troggle.parsers.people import GetPersonExpeditionNameLookup +#from troggle.core.forms import PersonForm, getTripForm, get_name +from django.core.urlresolvers import reverse +from django.http import HttpResponseRedirect, HttpResponse +from django.template import Context, loader +from utils import render_with_context +import os.path +import troggle.parsers.logbooks as logbookparsers +from django.template.defaultfilters import slugify +from troggle.helper import login_required_if_public +import datetime + + +# 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 re + +@django.db.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 = 4 + 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_with_context(request,'personindex.html', {'persons': persons, 'personss':personss, 'notablepersons':notablepersons, }) + + +def expedition(request, expeditionname): + expedition = Expedition.objects.get(year=int(expeditionname)) + expeditions = Expedition.objects.all() + personexpeditiondays = [ ] + dateditems = list(expedition.logbookentry_set.all()) + list(expedition.survexblock_set.all()) + dates = list(set([item.date for item in dateditems])) + dates.sort() + for personexpedition in expedition.personexpedition_set.all(): + prow = [ ] + for date in dates: + pcell = { "persontrips": PersonTrip.objects.filter(personexpedition=personexpedition, + logbook_entry__date=date) } + pcell["survexblocks"] = set(SurvexBlock.objects.filter(survexpersonrole__personexpedition=personexpedition, + date = date)) + prow.append(pcell) + personexpeditiondays.append({"personexpedition":personexpedition, "personrow":prow}) + + message = "" + if "reload" in request.GET: + message = LoadLogbookForExpedition(expedition) + return render_with_context(request,'expedition.html', {'expedition': expedition, 'expeditions':expeditions, 'personexpeditiondays':personexpeditiondays, 'message':message, 'settings':settings, 'dateditems': dateditems }) + + 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_with_context(request,'person.html', {'person': person, }) + + +def GetPersonChronology(personexpedition): + res = { } + for persontrip in personexpedition.persontrip_set.all(): + a = res.setdefault(persontrip.date, { }) + a.setdefault("persontrips", [ ]).append(persontrip) + + for personrole in personexpedition.survexpersonrole_set.all(): + a = res.setdefault(personrole.survexblock.date, { }) + a.setdefault("personroles", [ ]).append(personrole.survexblock) + + # build up the tables + rdates = res.keys() + rdates.sort() + + + res2 = [ ] + for rdate in rdates: + persontrips = res[rdate].get("persontrips", []) + personroles = res[rdate].get("personroles", []) + for n in range(max(len(persontrips), len(personroles))): + res2.append(((n == 0 and rdate or "--"), (n < len(persontrips) and persontrips[n]), (n < len(personroles) and personroles[n]))) + + return res2 + + +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) + personchronology = GetPersonChronology(personexpedition) + return render_with_context(request,'personexpedition.html', {'personexpedition': personexpedition, 'personchronology':personchronology}) + + +def logbookentry(request, date, slug): + logbookentry = LogbookEntry.objects.filter(date=date, slug=slug) + + if len(logbookentry)>1: + return render_with_context(request, 'object_list.html',{'object_list':logbookentry}) + else: + logbookentry=logbookentry[0] + return render_with_context(request, 'logbookentry.html', {'logbookentry': 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_with_context(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_with_context(request,'personform.html', {'form':form,}) + + +def experimental(request): + legsbyexpo = [ ] + for expedition in Expedition.objects.all(): + survexblocks = expedition.survexblock_set.all() + survexlegs = [ ] + survexleglength = 0.0 + for survexblock in survexblocks: + survexlegs.extend(survexblock.survexleg_set.all()) + survexleglength += survexblock.totalleglength + legsbyexpo.append((expedition, {"nsurvexlegs":len(survexlegs), "survexleglength":survexleglength})) + legsbyexpo.reverse() + + survexlegs = models.SurvexLeg.objects.all() + totalsurvexlength = sum([survexleg.tape for survexleg in survexlegs]) + return render_with_context(request, 'experimental.html', { "nsurvexlegs":len(survexlegs), "totalsurvexlength":totalsurvexlength, "legsbyexpo":legsbyexpo }) + +@login_required_if_public +def newLogbookEntry(request, expeditionyear, pdate = None, pslug = None): + expedition = Expedition.objects.get(year=expeditionyear) + PersonTripFormSet, TripForm = getTripForm(expedition) + if pslug and pdate: + previousdate = datetime.date(*[int(x) for x in pdate.split("-")]) + previouslbe = LogbookEntry.objects.get(slug = pslug, date = previousdate, expedition = expedition) + assert previouslbe.filename + if request.method == 'POST': # If the form has been submitted... + tripForm = TripForm(request.POST) # A form bound to the POST data + personTripFormSet = PersonTripFormSet(request.POST) + if tripForm.is_valid() and personTripFormSet.is_valid(): # All validation rules pass + dateStr = tripForm.cleaned_data["date"].strftime("%Y-%m-%d") + directory = os.path.join(settings.EXPOWEB, + "years", + expedition.year, + "autologbook") + filename = os.path.join(directory, + dateStr + "." + slugify(tripForm.cleaned_data["title"])[:50] + ".html") + if not os.path.isdir(directory): + os.mkdir(directory) + if pslug and pdate: + delLogbookEntry(previouslbe) + f = open(filename, "w") + template = loader.get_template('dataformat/logbookentry.html') + context = Context({'trip': tripForm.cleaned_data, + 'persons': personTripFormSet.cleaned_data, + 'date': dateStr, + 'expeditionyear': expeditionyear}) + f.write(template.render(context)) + f.close() + print logbookparsers.parseAutoLogBookEntry(filename) + return HttpResponseRedirect(reverse('expedition', args=[expedition.year])) # Redirect after POST + else: + if pslug and pdate: + if previouslbe.cave: + tripForm = TripForm(initial={"date": previousdate, + "title": previouslbe.title, + "cave": previouslbe.cave.reference(), + "location": None, + "caveOrLocation": "cave", + "html": previouslbe.text}) + else: + tripForm = TripForm(initial={"date": previousdate, + "title": previouslbe.title, + "cave": None, + "location": previouslbe.place, + "caveOrLocation": "location", + "html": previouslbe.text}) + personTripFormSet = PersonTripFormSet(initial=[{"name": get_name(py.personexpedition), + "TU": py.time_underground, + "author": py.is_logbook_entry_author} + for py in previouslbe.persontrip_set.all()]) + else: + tripForm = TripForm() # An unbound form + personTripFormSet = PersonTripFormSet() + + return render_with_context(request, 'newlogbookentry.html', { + 'tripForm': tripForm, + 'personTripFormSet': personTripFormSet, + + }) + +@login_required_if_public +def deleteLogbookEntry(request, expeditionyear, date = None, slug = None): + expedition = Expedition.objects.get(year=expeditionyear) + previousdate = datetime.date(*[int(x) for x in date.split("-")]) + previouslbe = LogbookEntry.objects.get(slug = slug, date = previousdate, expedition = expedition) + delLogbookEntry(previouslbe) + return HttpResponseRedirect(reverse('expedition', args=[expedition.year])) # Redirect after POST + +def delLogbookEntry(lbe): + for pt in lbe.persontrip_set.all(): + pt.delete() + lbe.delete() + os.remove(lbe.filename) + +def get_people(request, expeditionslug): + exp = Expedition.objects.get(year = expeditionslug) + return render_with_context(request,'options.html', {"items": [(pe.slug, pe.name) for pe in exp.personexpedition_set.all()]}) + +def get_logbook_entries(request, expeditionslug): + exp = Expedition.objects.get(year = expeditionslug) + return render_with_context(request,'options.html', {"items": [(le.slug, "%s - %s" % (le.date, le.title)) for le in exp.logbookentry_set.all()]}) + diff --git a/core/views_other.py b/core/views_other.py index d840a30..beecc46 100644 --- a/core/views_other.py +++ b/core/views_other.py @@ -1,282 +1,282 @@ -from troggle.core.models import Cave, Expedition, Person, LogbookEntry, PersonExpedition, PersonTrip, DPhoto, QM
-from troggle.core.forms import UploadFileForm
-from django.conf import settings
-from django import forms
-from django.template import loader, Context
-from django.db.models import Q
-import databaseReset
-import re
-from django.http import HttpResponse, HttpResponseRedirect
-from django.core.urlresolvers import reverse
-from utils import render_with_context
-from core.models import *
-from troggle.helper import login_required_if_public
-
-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_with_context(request,'statistics.html', statsDict)
-
-def frontpage(request):
- if request.user.is_authenticated():
- return render_with_context(request,'tasks.html')
-
- expeditions = Expedition.objects.order_by("-year")
- logbookentry = LogbookEntry
- cave = Cave
- photo = DPhoto
- from django.contrib.admin.templatetags import log
- return render_with_context(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"
-
- expeditions = Expedition.objects.order_by("-year")
- totallogbookentries = LogbookEntry.objects.count()
- return render_with_context(request,'index.html', {'expeditions':expeditions, 'all':'all', 'totallogbookentries':totallogbookentries, "message":message})
-
-
-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_with_context(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_with_context(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
-
-def ajax_QM_number(request):
- if request.method=='POST':
- cave=Cave.objects.get(id=request.POST['cave'])
- print cave
- exp=Expedition.objects.get(pk=request.POST['year'])
- print exp
- res=cave.new_QM_number(exp.year)
-
- return HttpResponse(res)
-
-def logbook_entry_suggestions(request):
- """
- Generates a html box with suggestions about what to do with QMs
- in logbook entry text.
- """
- unwiki_QM_pattern=r"(?P<whole>(?P<explorer_code>[ABC]?)(?P<cave>\d*)-?(?P<year>\d\d\d?\d?)-(?P<number>\d\d)(?P<grade>[ABCDXV]?))"
- unwiki_QM_pattern=re.compile(unwiki_QM_pattern)
- #wikilink_QM_pattern=settings.QM_PATTERN
-
- slug=request.POST['slug']
- date=request.POST['date']
- lbo=LogbookEntry.objects.get(slug=slug, date=date)
-
- #unwiki_QMs=re.findall(unwiki_QM_pattern,lbo.text)
- unwiki_QMs=[m.groupdict() for m in unwiki_QM_pattern.finditer(lbo.text)]
-
- print unwiki_QMs
- for qm in unwiki_QMs:
- #try:
- if len(qm['year'])==2:
- if int(qm['year'])<50:
- qm['year']='20'+qm['year']
- else:
- qm['year']='19'+qm['year']
-
- if lbo.date.year!=int(qm['year']):
- try:
- lbo=LogbookEntry.objects.get(date__year=qm['year'],title__icontains="placeholder for QMs in")
- except:
- print "failed to get placeholder for year "+str(qm['year'])
-
- temp_QM=QM(found_by=lbo,number=qm['number'],grade=qm['grade'])
- temp_QM.grade=qm['grade']
- qm['wikilink']=temp_QM.wiki_link()
- #except:
- #print 'failed'
-
- print unwiki_QMs
-
-
- #wikilink_QMs=re.findall(wikilink_QM_pattern,lbo.text)
- attached_QMs=lbo.QMs_found.all()
- unmentioned_attached_QMs=''#not implemented, fill this in by subtracting wiklink_QMs from attached_QMs
-
- #Find unattached_QMs. We only look at the QMs with a proper wiki link.
- #for qm in wikilink_QMs:
- #Try to look up the QM.
-
- print 'got 208'
- any_suggestions=True
- print 'got 210'
- return render_with_context(request,'suggestions.html',
- {
- 'unwiki_QMs':unwiki_QMs,
- 'any_suggestions':any_suggestions
- })
-
-@login_required_if_public
-def newFile(request, pslug = None):
-# if pslug:
-# previousfile = LogbookEntry.objects.get(slug = pslug, date = previousdate, expedition = expedition)
-# assert previousfile.filename
- if request.method == 'POST': # If the form has been submitted...
- tripForm = TripForm(request.POST) # A form bound to the POST data
-# personTripFormSet = PersonTripFormSet(request.POST)
-# if tripForm.is_valid() and personTripFormSet.is_valid(): # All validation rules pass
-# dateStr = tripForm.cleaned_data["date"].strftime("%Y-%m-%d")
-# directory = os.path.join(settings.EXPOWEB,
-# "years",
-# expedition.year,
-# "autologbook")
-# filename = os.path.join(directory,
-# dateStr + "." + slugify(tripForm.cleaned_data["title"])[:50] + ".html")
-# if not os.path.isdir(directory):
-# os.mkdir(directory)
-# if pslug and pdate:
-# delLogbookEntry(previouslbe)
-# f = open(filename, "w")
-# template = loader.get_template('dataformat/logbookentry.html')
-# context = Context({'trip': tripForm.cleaned_data,
-# 'persons': personTripFormSet.cleaned_data,
-# 'date': dateStr,
-# 'expeditionyear': expeditionyear})
-# f.write(template.render(context))
-# f.close()
-# print logbookparsers.parseAutoLogBookEntry(filename)
-# return HttpResponseRedirect(reverse('expedition', args=[expedition.year])) # Redirect after POST
- else:
- if pslug:
- pass
-# if previouslbe.cave:
-# tripForm = TripForm(initial={"date": previousdate,
-# "title": previouslbe.title,
-# "cave": previouslbe.cave.reference(),
-# "location": None,
-# "caveOrLocation": "cave",
-# "html": previouslbe.text})
-# else:
-# tripForm = TripForm(initial={"date": previousdate,
-# "title": previouslbe.title,
-# "cave": None,
-# "location": previouslbe.place,
-# "caveOrLocation": "location",
-# "html": previouslbe.text})
-# personTripFormSet = PersonTripFormSet(initial=[{"name": get_name(py.personexpedition),
-# "TU": py.time_underground,
-# "author": py.is_logbook_entry_author}
-# for py in previouslbe.persontrip_set.all()])
- else:
- fileform = UploadFileForm() # An unbound form
-
- return render_with_context(request, 'editfile.html', {
- 'fileForm': fileform,
-
- })
-
-@login_required_if_public
-def deleteFile(request, expeditionyear, date = None, slug = None):
- expedition = Expedition.objects.get(year=expeditionyear)
- previousdate = datetime.date(*[int(x) for x in date.split("-")])
- previouslbe = LogbookEntry.objects.get(slug = slug, date = previousdate, expedition = expedition)
- delLogbookEntry(previouslbe)
- return HttpResponseRedirect(reverse('expedition', args=[expedition.year])) # Redirect after POST
-
-def delFile(f):
- for pt in lbe.persontrip_set.all():
- pt.delete()
- lbe.delete()
- os.remove(lbe.filename)
+from troggle.core.models import Cave, Expedition, Person, LogbookEntry, PersonExpedition, PersonTrip, DPhoto, QM +from troggle.core.forms import UploadFileForm +from django.conf import settings +from django import forms +from django.template import loader, Context +from django.db.models import Q +import databaseReset +import re +from django.http import HttpResponse, HttpResponseRedirect +from django.core.urlresolvers import reverse +from utils import render_with_context +from core.models import * +from troggle.helper import login_required_if_public + +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_with_context(request,'statistics.html', statsDict) + +def frontpage(request): + if request.user.is_authenticated(): + return render_with_context(request,'tasks.html') + + expeditions = Expedition.objects.order_by("-year") + logbookentry = LogbookEntry + cave = Cave + photo = DPhoto + from django.contrib.admin.templatetags import log + return render_with_context(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" + + expeditions = Expedition.objects.order_by("-year") + totallogbookentries = LogbookEntry.objects.count() + return render_with_context(request,'index.html', {'expeditions':expeditions, 'all':'all', 'totallogbookentries':totallogbookentries, "message":message}) + + +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_with_context(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_with_context(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 + +def ajax_QM_number(request): + if request.method=='POST': + cave=Cave.objects.get(id=request.POST['cave']) + print cave + exp=Expedition.objects.get(pk=request.POST['year']) + print exp + res=cave.new_QM_number(exp.year) + + return HttpResponse(res) + +def logbook_entry_suggestions(request): + """ + Generates a html box with suggestions about what to do with QMs + in logbook entry text. + """ + unwiki_QM_pattern=r"(?P<whole>(?P<explorer_code>[ABC]?)(?P<cave>\d*)-?(?P<year>\d\d\d?\d?)-(?P<number>\d\d)(?P<grade>[ABCDXV]?))" + unwiki_QM_pattern=re.compile(unwiki_QM_pattern) + #wikilink_QM_pattern=settings.QM_PATTERN + + slug=request.POST['slug'] + date=request.POST['date'] + lbo=LogbookEntry.objects.get(slug=slug, date=date) + + #unwiki_QMs=re.findall(unwiki_QM_pattern,lbo.text) + unwiki_QMs=[m.groupdict() for m in unwiki_QM_pattern.finditer(lbo.text)] + + print unwiki_QMs + for qm in unwiki_QMs: + #try: + if len(qm['year'])==2: + if int(qm['year'])<50: + qm['year']='20'+qm['year'] + else: + qm['year']='19'+qm['year'] + + if lbo.date.year!=int(qm['year']): + try: + lbo=LogbookEntry.objects.get(date__year=qm['year'],title__icontains="placeholder for QMs in") + except: + print "failed to get placeholder for year "+str(qm['year']) + + temp_QM=QM(found_by=lbo,number=qm['number'],grade=qm['grade']) + temp_QM.grade=qm['grade'] + qm['wikilink']=temp_QM.wiki_link() + #except: + #print 'failed' + + print unwiki_QMs + + + #wikilink_QMs=re.findall(wikilink_QM_pattern,lbo.text) + attached_QMs=lbo.QMs_found.all() + unmentioned_attached_QMs=''#not implemented, fill this in by subtracting wiklink_QMs from attached_QMs + + #Find unattached_QMs. We only look at the QMs with a proper wiki link. + #for qm in wikilink_QMs: + #Try to look up the QM. + + print 'got 208' + any_suggestions=True + print 'got 210' + return render_with_context(request,'suggestions.html', + { + 'unwiki_QMs':unwiki_QMs, + 'any_suggestions':any_suggestions + }) + +@login_required_if_public +def newFile(request, pslug = None): +# if pslug: +# previousfile = LogbookEntry.objects.get(slug = pslug, date = previousdate, expedition = expedition) +# assert previousfile.filename + if request.method == 'POST': # If the form has been submitted... + tripForm = TripForm(request.POST) # A form bound to the POST data +# personTripFormSet = PersonTripFormSet(request.POST) +# if tripForm.is_valid() and personTripFormSet.is_valid(): # All validation rules pass +# dateStr = tripForm.cleaned_data["date"].strftime("%Y-%m-%d") +# directory = os.path.join(settings.EXPOWEB, +# "years", +# expedition.year, +# "autologbook") +# filename = os.path.join(directory, +# dateStr + "." + slugify(tripForm.cleaned_data["title"])[:50] + ".html") +# if not os.path.isdir(directory): +# os.mkdir(directory) +# if pslug and pdate: +# delLogbookEntry(previouslbe) +# f = open(filename, "w") +# template = loader.get_template('dataformat/logbookentry.html') +# context = Context({'trip': tripForm.cleaned_data, +# 'persons': personTripFormSet.cleaned_data, +# 'date': dateStr, +# 'expeditionyear': expeditionyear}) +# f.write(template.render(context)) +# f.close() +# print logbookparsers.parseAutoLogBookEntry(filename) +# return HttpResponseRedirect(reverse('expedition', args=[expedition.year])) # Redirect after POST + else: + if pslug: + pass +# if previouslbe.cave: +# tripForm = TripForm(initial={"date": previousdate, +# "title": previouslbe.title, +# "cave": previouslbe.cave.reference(), +# "location": None, +# "caveOrLocation": "cave", +# "html": previouslbe.text}) +# else: +# tripForm = TripForm(initial={"date": previousdate, +# "title": previouslbe.title, +# "cave": None, +# "location": previouslbe.place, +# "caveOrLocation": "location", +# "html": previouslbe.text}) +# personTripFormSet = PersonTripFormSet(initial=[{"name": get_name(py.personexpedition), +# "TU": py.time_underground, +# "author": py.is_logbook_entry_author} +# for py in previouslbe.persontrip_set.all()]) + else: + fileform = UploadFileForm() # An unbound form + + return render_with_context(request, 'editfile.html', { + 'fileForm': fileform, + + }) + +@login_required_if_public +def deleteFile(request, expeditionyear, date = None, slug = None): + expedition = Expedition.objects.get(year=expeditionyear) + previousdate = datetime.date(*[int(x) for x in date.split("-")]) + previouslbe = LogbookEntry.objects.get(slug = slug, date = previousdate, expedition = expedition) + delLogbookEntry(previouslbe) + return HttpResponseRedirect(reverse('expedition', args=[expedition.year])) # Redirect after POST + +def delFile(f): + for pt in lbe.persontrip_set.all(): + pt.delete() + lbe.delete() + os.remove(lbe.filename) diff --git a/core/views_survex.py b/core/views_survex.py index b6b5aba..8e7ac1e 100644 --- a/core/views_survex.py +++ b/core/views_survex.py @@ -1,318 +1,318 @@ -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
-
-from troggle.core.models import Expedition, Person, PersonExpedition, PersonTrip, LogbookEntry, Cave
-from troggle.core.models import SurvexBlock, SurvexPersonRole, SurvexFile, SurvexDirectory, SurvexTitle
-from parsers.people import GetPersonExpeditionNameLookup
-
-import troggle.settings as settings
-import parsers.survex
-
-survextemplatefile = """; Locn: Totes Gebirge, Austria - Loser/Augst-Eck Plateau (kataster group 1623)
-; Cave:
-
-*begin [surveyname]
-
-*export [connecting stations]
-
-*title "area title"
-*date 2999.99.99
-*team Insts [Caver]
-*team Insts [Caver]
-*team Notes [Caver]
-*instrument [set number]
-
-;ref.: 2009#NN
-
-*calibrate tape +0.0 ; +ve if tape was too short, -ve if too long
-
-*data normal from to tape compass clino
-1 2 3.90 298 -20
-
-*data passage station left right up down ignoreall
-1 [L] [R] [U] [D] comment
-
-*end [surveyname]"""
-
-
-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 survextemplatefile
- 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):
- # only save if appears valid
- if re.search("\[|\]", rcode):
- return "Error: clean up all []s from the text"
- mbeginend = re.search("(?s)\*begin\s+(\w+).*?\*end\s+(\w+)", rcode)
- if not mbeginend:
- return "Error: no begin/end block here"
- if mbeginend.group(1) != mbeginend.group(2):
- return "Error: mismatching beginend"
-
- fout = open(fname, "w")
- res = fout.write(rcode.encode("latin1"))
- fout.close()
- return "SAVED"
-
- 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]
- 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:
- if request.user.is_authenticated():
- #print "sssavvving"
- message = form.SaveCode(rcode)
- else:
- message = "You do not have authority to save this file"
- if message != "SAVED":
- 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)
-
- #print [ form.data['code'] ]
- svxincludes = re.findall('\*include\s+(\S+)(?i)', form.data['code'] or "")
-
- 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 svxraw(request, survex_file):
- svx = open(os.path.join(settings.SURVEX_DATA, survex_file+".svx"), "rb")
- return HttpResponse(svx, mimetype="text")
-
-
-# The cavern running function
-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)
-
-
-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 identifycavedircontents(gcavedir):
- name = os.path.split(gcavedir)[1]
- subdirs = [ ]
- subsvx = [ ]
- primesvx = None
- for f in os.listdir(gcavedir):
- if name == "204" and (f in ["skel.svx", "template.svx", "204withents.svx"]):
- pass
- elif name == "136" and (f in ["136-noents.svx"]):
- pass
- elif name == "115" and (f in ["115cufix.svx", "115fix.svx"]):
- pass
-
- elif os.path.isdir(os.path.join(gcavedir, f)):
- if f[0] != ".":
- subdirs.append(f)
- elif f[-4:] == ".svx":
- nf = f[:-4]
-
- if nf.lower() == name.lower() or nf[:3] == "all" or (name, nf) in [("144arge", "144"), ("resurvey2005", "145-2005"), ("cucc", "cu115")]:
- if primesvx:
- if nf[:3] == "all":
- assert primesvx[:3] != "all", (name, nf, primesvx, gcavedir, subsvx)
- primesvx = nf
- else:
- assert primesvx[:3] == "all", (name, nf, primesvx, gcavedir, subsvx)
- else:
- primesvx = nf
- else:
- subsvx.append(nf)
- else:
- assert re.match(".*?(?:.3d|.log|.err|.txt|.tmp|.diff|.e?spec|~)$", f), (gcavedir, f)
- subsvx.sort()
- assert primesvx, (gcavedir, subsvx)
- if primesvx:
- subsvx.insert(0, primesvx)
- return subdirs, subsvx
-
-
-
-# direct local non-database browsing through the svx file repositories
-# perhaps should use the database and have a reload button for it
-def survexcaveslist(request):
- cavesdir = os.path.join(settings.SURVEX_DATA, "caves")
- cavesdircontents = { }
-
- onefilecaves = [ ]
- multifilecaves = [ ]
- subdircaves = [ ]
-
- # first sort the file list
- fnumlist = [ (-int(re.match("\d*", f).group(0) or "0"), f) for f in os.listdir(cavesdir) ]
- fnumlist.sort()
-
- # go through the list and identify the contents of each cave directory
- for num, cavedir in fnumlist:
- if cavedir in ["144", "40"]:
- continue
-
- gcavedir = os.path.join(cavesdir, cavedir)
- if os.path.isdir(gcavedir) and cavedir[0] != ".":
- subdirs, subsvx = identifycavedircontents(gcavedir)
- survdirobj = [ ]
-
- for lsubsvx in subsvx:
- survdirobj.append(("caves/"+cavedir+"/"+lsubsvx, lsubsvx))
-
- # caves with subdirectories
- if subdirs:
- subsurvdirs = [ ]
- for subdir in subdirs:
- dsubdirs, dsubsvx = identifycavedircontents(os.path.join(gcavedir, subdir))
- assert not dsubdirs
- lsurvdirobj = [ ]
- for lsubsvx in dsubsvx:
- lsurvdirobj.append(("caves/"+cavedir+"/"+subdir+"/"+lsubsvx, lsubsvx))
- subsurvdirs.append((lsurvdirobj[0], lsurvdirobj[1:]))
- subdircaves.append((cavedir, (survdirobj[0], survdirobj[1:]), subsurvdirs))
-
- # multifile caves
- elif len(survdirobj) > 1:
- multifilecaves.append((survdirobj[0], survdirobj[1:]))
- # single file caves
- else:
- onefilecaves.append(survdirobj[0])
-
- return render_to_response('svxfilecavelist.html', {'settings': settings, "onefilecaves":onefilecaves, "multifilecaves":multifilecaves, "subdircaves":subdircaves })
-
-
-
-
-
-
-# parsing all the survex files of a single cave and showing that it's consistent and can find all the files and people
-# doesn't use recursion. just writes it twice
-def survexcavesingle(request, survex_cave):
- breload = False
- cave = Cave.objects.get(kataster_number=survex_cave)
- if breload:
- parsers.survex.ReloadSurvexCave(survex_cave)
- return render_to_response('svxcavesingle.html', {'settings': settings, "cave":cave })
-
-
-
-
+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 + +from troggle.core.models import Expedition, Person, PersonExpedition, PersonTrip, LogbookEntry, Cave +from troggle.core.models import SurvexBlock, SurvexPersonRole, SurvexFile, SurvexDirectory, SurvexTitle +from parsers.people import GetPersonExpeditionNameLookup + +import troggle.settings as settings +import parsers.survex + +survextemplatefile = """; Locn: Totes Gebirge, Austria - Loser/Augst-Eck Plateau (kataster group 1623) +; Cave: + +*begin [surveyname] + +*export [connecting stations] + +*title "area title" +*date 2999.99.99 +*team Insts [Caver] +*team Insts [Caver] +*team Notes [Caver] +*instrument [set number] + +;ref.: 2009#NN + +*calibrate tape +0.0 ; +ve if tape was too short, -ve if too long + +*data normal from to tape compass clino +1 2 3.90 298 -20 + +*data passage station left right up down ignoreall +1 [L] [R] [U] [D] comment + +*end [surveyname]""" + + +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 survextemplatefile + 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): + # only save if appears valid + if re.search("\[|\]", rcode): + return "Error: clean up all []s from the text" + mbeginend = re.search("(?s)\*begin\s+(\w+).*?\*end\s+(\w+)", rcode) + if not mbeginend: + return "Error: no begin/end block here" + if mbeginend.group(1) != mbeginend.group(2): + return "Error: mismatching beginend" + + fout = open(fname, "w") + res = fout.write(rcode.encode("latin1")) + fout.close() + return "SAVED" + + 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] + 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: + if request.user.is_authenticated(): + #print "sssavvving" + message = form.SaveCode(rcode) + else: + message = "You do not have authority to save this file" + if message != "SAVED": + 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) + + #print [ form.data['code'] ] + svxincludes = re.findall('\*include\s+(\S+)(?i)', form.data['code'] or "") + + 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 svxraw(request, survex_file): + svx = open(os.path.join(settings.SURVEX_DATA, survex_file+".svx"), "rb") + return HttpResponse(svx, mimetype="text") + + +# The cavern running function +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) + + +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 identifycavedircontents(gcavedir): + name = os.path.split(gcavedir)[1] + subdirs = [ ] + subsvx = [ ] + primesvx = None + for f in os.listdir(gcavedir): + if name == "204" and (f in ["skel.svx", "template.svx", "204withents.svx"]): + pass + elif name == "136" and (f in ["136-noents.svx"]): + pass + elif name == "115" and (f in ["115cufix.svx", "115fix.svx"]): + pass + + elif os.path.isdir(os.path.join(gcavedir, f)): + if f[0] != ".": + subdirs.append(f) + elif f[-4:] == ".svx": + nf = f[:-4] + + if nf.lower() == name.lower() or nf[:3] == "all" or (name, nf) in [("144arge", "144"), ("resurvey2005", "145-2005"), ("cucc", "cu115")]: + if primesvx: + if nf[:3] == "all": + assert primesvx[:3] != "all", (name, nf, primesvx, gcavedir, subsvx) + primesvx = nf + else: + assert primesvx[:3] == "all", (name, nf, primesvx, gcavedir, subsvx) + else: + primesvx = nf + else: + subsvx.append(nf) + else: + assert re.match(".*?(?:.3d|.log|.err|.txt|.tmp|.diff|.e?spec|~)$", f), (gcavedir, f) + subsvx.sort() + assert primesvx, (gcavedir, subsvx) + if primesvx: + subsvx.insert(0, primesvx) + return subdirs, subsvx + + + +# direct local non-database browsing through the svx file repositories +# perhaps should use the database and have a reload button for it +def survexcaveslist(request): + cavesdir = os.path.join(settings.SURVEX_DATA, "caves") + cavesdircontents = { } + + onefilecaves = [ ] + multifilecaves = [ ] + subdircaves = [ ] + + # first sort the file list + fnumlist = [ (-int(re.match("\d*", f).group(0) or "0"), f) for f in os.listdir(cavesdir) ] + fnumlist.sort() + + # go through the list and identify the contents of each cave directory + for num, cavedir in fnumlist: + if cavedir in ["144", "40"]: + continue + + gcavedir = os.path.join(cavesdir, cavedir) + if os.path.isdir(gcavedir) and cavedir[0] != ".": + subdirs, subsvx = identifycavedircontents(gcavedir) + survdirobj = [ ] + + for lsubsvx in subsvx: + survdirobj.append(("caves/"+cavedir+"/"+lsubsvx, lsubsvx)) + + # caves with subdirectories + if subdirs: + subsurvdirs = [ ] + for subdir in subdirs: + dsubdirs, dsubsvx = identifycavedircontents(os.path.join(gcavedir, subdir)) + assert not dsubdirs + lsurvdirobj = [ ] + for lsubsvx in dsubsvx: + lsurvdirobj.append(("caves/"+cavedir+"/"+subdir+"/"+lsubsvx, lsubsvx)) + subsurvdirs.append((lsurvdirobj[0], lsurvdirobj[1:])) + subdircaves.append((cavedir, (survdirobj[0], survdirobj[1:]), subsurvdirs)) + + # multifile caves + elif len(survdirobj) > 1: + multifilecaves.append((survdirobj[0], survdirobj[1:])) + # single file caves + else: + onefilecaves.append(survdirobj[0]) + + return render_to_response('svxfilecavelist.html', {'settings': settings, "onefilecaves":onefilecaves, "multifilecaves":multifilecaves, "subdircaves":subdircaves }) + + + + + + +# parsing all the survex files of a single cave and showing that it's consistent and can find all the files and people +# doesn't use recursion. just writes it twice +def survexcavesingle(request, survex_cave): + breload = False + cave = Cave.objects.get(kataster_number=survex_cave) + if breload: + parsers.survex.ReloadSurvexCave(survex_cave) + return render_to_response('svxcavesingle.html', {'settings': settings, "cave":cave }) + + + +
\ No newline at end of file |