summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/admin.py12
-rw-r--r--core/models.py107
-rw-r--r--core/models_survex.py5
-rw-r--r--core/randSent.py32
-rw-r--r--core/views_logbooks.py48
-rw-r--r--core/views_other.py20
-rw-r--r--media/js/QM_helper.js20
-rw-r--r--parsers/subcaves.py15
-rw-r--r--urls.py7
9 files changed, 154 insertions, 112 deletions
diff --git a/core/admin.py b/core/admin.py
index 1b6b550..d25a154 100644
--- a/core/admin.py
+++ b/core/admin.py
@@ -9,11 +9,16 @@ from django.core import serializers
from core.views_other import downloadLogbook
#from troggle.reversion.admin import VersionAdmin #django-reversion version control
-#overriding admin save so we have the new since parsing field
+
class TroggleModelAdmin(admin.ModelAdmin):
+
def save_model(self, request, obj, form, change):
+ """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 = PersonRole
@@ -33,7 +38,8 @@ class SurveyAdmin(TroggleModelAdmin):
class QMsFoundInline(admin.TabularInline):
model=QM
fk_name='found_by'
-
+ fields=('number','grade','location_description','comment')#need to add foreignkey to cave part
+
class PhotoInline(admin.TabularInline):
model = Photo
exclude = ['is_mugshot' ]
@@ -61,6 +67,8 @@ class LogbookEntryAdmin(TroggleModelAdmin):
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
diff --git a/core/models.py b/core/models.py
index 0889f16..1424f40 100644
--- a/core/models.py
+++ b/core/models.py
@@ -18,8 +18,8 @@ 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):
- """This class is for adding fields and methods which all of our models will have."""
new_since_parsing = models.BooleanField(default=False, editable=False)
non_public = models.BooleanField(default=False)
def object_name(self):
@@ -29,10 +29,22 @@ class TroggleModel(models.Model):
return urlparse.urljoin(settings.URL_ROOT, "/admin/core/" + self.object_name().lower() + "/" + str(self.pk))
class Meta:
- abstract = True
+ 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
class Expedition(TroggleModel):
- """Represents a caving expedition"""
year = models.CharField(max_length=20, unique=True)
name = models.CharField(max_length=100)
date_from = models.DateField(blank=True,null=True)
@@ -49,16 +61,15 @@ class Expedition(TroggleModel):
#return settings.URL_ROOT + "/expedition/%s" % self.year
return urlparse.urljoin(settings.URL_ROOT, reverse('expedition',args=[self.year]))
+
# lose these two functions (inelegant, and we may create a file with the dates that we can load from)
def GuessDateFrom(self):
- """Returns the date of the first logbook entry in the expedition"""
try:
return self.logbookentry_set.order_by('date')[0].date
except IndexError:
pass
- def GuessDateTo(self):
- """Returns the date of the last logbook entry in the expedition"""
+ def GuessDateTo(self): # returns the date of the last logbook entry in the expedition
try:
return self.logbookentry_set.order_by('date')[-1].date
except IndexError:
@@ -79,27 +90,42 @@ class Expedition(TroggleModel):
date+=datetime.timedelta(days=1)
return res
+
+
+
class Person(TroggleModel):
- """Represents a person, also used as the profile model"""
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) #obsolete, remove soon
+ mug_shot = models.CharField(max_length=100, blank=True,null=True)
blurb = models.TextField(blank=True,null=True)
- orderref = models.CharField(max_length=200) # for alphabetic
+ #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"
+ verbose_name_plural = "People"
+ class Meta:
ordering = ('orderref',) # "Wookey" makes too complex for: ('last_name', 'first_name')
def __unicode__(self):
if self.last_name:
return "%s %s" % (self.first_name, self.last_name)
return self.first_name
+
+# Below are no longer needed. Use {{ person.personexpedition_set.all.0.expedition }} for Firstexpedition, and {{ person.personexpedition_set.latest.expedition }} for Lastexpedition
+ # these ought to be possible by piping through |min in the template, or getting the first of an ordered list
+# def Firstexpedition(self):
+# return self.personexpedition_set.order_by('expedition')[0]
+# def Lastexpedition(self):
+# return self.personexpedition_set.order_by('-expedition')[0]
def notability(self):
notability = Decimal(0)
@@ -110,9 +136,18 @@ class Person(TroggleModel):
def bisnotable(self):
return self.notability() > Decimal(1)/Decimal(3)
+
+ #def Sethref(self):
+ #if self.last_name:
+ #self.href = self.first_name.lower() + "_" + self.last_name.lower()
+ #self.orderref = self.last_name + " " + self.first_name
+ #else:
+ # self.href = self.first_name.lower()
+ #self.orderref = self.first_name
+ #self.notability = 0.0 # set temporarily
+
class PersonExpedition(TroggleModel):
- """"""
expedition = models.ForeignKey(Expedition)
person = models.ForeignKey(Person)
date_from = models.DateField(blank=True,null=True)
@@ -199,9 +234,8 @@ class PersonExpedition(TroggleModel):
return urlparse.urljoin(settings.URL_ROOT, reverse('personexpedition',kwargs={'first_name':self.person.first_name,'last_name':self.person.last_name,'year':self.expedition.year}))
class LogbookEntry(TroggleModel):
- """Represents trips of all kinds. This is the central model of Troggle."""
date = models.DateField()
- expedition = models.ForeignKey(Expedition,blank=True,null=True)
+ expedition = models.ForeignKey(Expedition,blank=True,null=True) # yes this is double-
author = models.ForeignKey(PersonExpedition,blank=True,null=True) # the person who writes it up doesn't have to have been on the trip.
# Re: the above- so this field should be "typist" or something, not "author". - AC 15 jun 09
title = models.CharField(max_length=200)
@@ -211,7 +245,9 @@ class LogbookEntry(TroggleModel):
slug = models.SlugField(max_length=50)
class Meta:
- verbose_name_plural = "Logbook Entries"
+ verbose_name_plural = "Logbook Entries"
+ # several PersonTrips point in to this object
+ class Meta:
ordering = ('-date',)
def get_absolute_url(self):
@@ -226,6 +262,18 @@ class LogbookEntry(TroggleModel):
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())
+
class PersonTrip(TroggleModel):
person_expedition = models.ForeignKey(PersonExpedition,null=True)
@@ -246,6 +294,9 @@ class PersonTrip(TroggleModel):
else:
return self.logbook_entry.place
+ #persontrip_next = models.ForeignKey('PersonTrip', related_name='pnext', blank=True,null=True)
+ #persontrip_prev = models.ForeignKey('PersonTrip', related_name='pprev', blank=True,null=True)
+
def __unicode__(self):
return "%s %s (%s)" % (self.person_expedition, self.place(), self.date())
@@ -261,6 +312,7 @@ class PersonTrip(TroggleModel):
except:
return
+# def get_persons_previous_trip(self):
#
# move following classes into models_cave
#
@@ -336,7 +388,15 @@ class Cave(TroggleModel):
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():
@@ -373,13 +433,6 @@ class Cave(TroggleModel):
res += "–" + prevR
return res
- def nextQMnumber(self, year=datetime.date.today().year):
- """
- Given a cave and the current year, returns the next QM number.
- """
- res=QM.objects.filter(found_by__date__year=year, found_by__cave=self).order_by('-number')[0]
- return res.number+1
-
class OtherCaveName(TroggleModel):
name = models.CharField(max_length=160)
cave = models.ForeignKey(Cave)
@@ -506,7 +559,7 @@ class QM(TroggleModel):
#"Number","Grade","Area","Description","Page reference","Nearest station","Completion description","Comment"
found_by = models.ForeignKey(LogbookEntry, related_name='QMs_found',blank=True, null=True )
ticked_off_by = models.ForeignKey(LogbookEntry, related_name='QMs_ticked_off',null=True,blank=True)
- number = models.IntegerField(help_text="this is the sequential number in the year")
+ number = models.IntegerField(help_text="this is the sequential number in the year", )
GRADE_CHOICES=(
('A', 'A: Large obvious lead'),
('B', 'B: Average lead'),
@@ -522,9 +575,7 @@ class QM(TroggleModel):
area = models.CharField(max_length=100,blank=True,null=True)
completion_description = models.TextField(blank=True,null=True)
comment=models.TextField(blank=True,null=True)
- #the below are unneeded- instead use the date fields of the QM's trips
- #dateFound = models.DateField(blank=True)
- #dateKilled = models.DateField(blank=True)
+
def __unicode__(self):
QMnumber=str(self.found_by.cave)+'-'+str(self.found_by.date.year)+"-"+str(self.number)+self.grade
return str(QMnumber)
@@ -546,7 +597,7 @@ class QM(TroggleModel):
return res
photoFileStorage = FileSystemStorage(location=settings.PHOTOS_ROOT, base_url=settings.PHOTOS_URL)
-class Photo(ImageModel, TroggleModel):
+class Photo(TroggleImageModel):
caption = models.CharField(max_length=1000,blank=True,null=True)
contains_logbookentry = models.ForeignKey(LogbookEntry,blank=True,null=True)
contains_person = models.ManyToManyField(Person,blank=True,null=True)
@@ -578,7 +629,7 @@ def get_scan_path(instance, filename):
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(ImageModel, TroggleModel):
+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)
diff --git a/core/models_survex.py b/core/models_survex.py
index cf339f9..7c8d27e 100644
--- a/core/models_survex.py
+++ b/core/models_survex.py
@@ -31,7 +31,10 @@ class SurvexBlock(models.Model):
ordering = ('date', 'survexpath')
def __unicode__(self):
- return unicode(self.name)
+ if self.name:
+ return unicode(self.name)
+ else:
+ return 'no name'
def filecontents(self):
f = os.path.join(settings.SURVEX_DATA, self.begin_file)
diff --git a/core/randSent.py b/core/randSent.py
deleted file mode 100644
index efcc005..0000000
--- a/core/randSent.py
+++ /dev/null
@@ -1,32 +0,0 @@
-import troggle.settings as settings
-from django import forms
-from troggle.core.models import LogbookEntry
-import random
-import re
-
-def weighted_choice(lst):
- n = random.uniform(0,1)
- for item, weight in lst:
- if n < weight:
- break
- n = n - weight
- return item
-
-def randomLogbookSentence():
- randSent={}
-
- # needs to handle empty logbooks without crashing
-
- #Choose a random logbook entry
- randSent['entry']=LogbookEntry.objects.order_by('?')[0]
-
- #Choose again if there are no sentances (this happens if it is a placeholder entry)
- while len(re.findall('[A-Z].*?\.',randSent['entry'].text))==0:
- randSent['entry']=LogbookEntry.objects.order_by('?')[0]
-
- #Choose a random sentence from that entry. Store the sentence as randSent['sentence'], and the number of that sentence in the entry as randSent['number']
- sentenceList=re.findall('[A-Z].*?\.',randSent['entry'].text)
- randSent['number']=random.randrange(0,len(sentenceList))
- randSent['sentence']=sentenceList[randSent['number']]
-
- return randSent
diff --git a/core/views_logbooks.py b/core/views_logbooks.py
index b504b35..13bf0d1 100644
--- a/core/views_logbooks.py
+++ b/core/views_logbooks.py
@@ -5,12 +5,13 @@ from django.db import models
from troggle.parsers.logbooks import LoadLogbookForExpedition
from troggle.parsers.people import GetPersonExpeditionNameLookup
from troggle.core.forms import PersonForm
-from django.core.urlresolvers import reverse
+from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
+# Django uses Context, not RequestContext when you call render_to_response. We always want to use RequestContext, so that django adds the context from settings.TEMPLATE_CONTEXT_PROCESSORS. This way we automatically get necessary settings variables passed to each template. So we use a custom method, render_response instead of render_to_response. Hopefully future Django releases will make this unnecessary.
+from troggle.alwaysUseRequestContext import render_response
-from utils import render_with_context
-
+import search
import re
@models.permalink #this allows the nice get_absolute_url syntax we are using
@@ -36,7 +37,7 @@ def personindex(request):
if person.bisnotable():
notablepersons.append(person)
- return render_with_context(request,'personindex.html', {'persons': persons, 'personss':personss, 'notablepersons':notablepersons, })
+ return render_response(request,'personindex.html', {'persons': persons, 'personss':personss, 'notablepersons':notablepersons, })
def expedition(request, expeditionname):
year = int(expeditionname)
@@ -48,7 +49,7 @@ def expedition(request, expeditionname):
message = LoadLogbookForExpedition(expedition)
#message = str(GetPersonExpeditionNameLookup(expedition).keys())
logbookentries = expedition.logbookentry_set.order_by('date')
- return render_with_context(request,'expedition.html', {'expedition': expedition, 'expedition_next':expedition_next, 'expedition_prev':expedition_prev, 'logbookentries':logbookentries, 'message':message, })
+ return render_response(request,'expedition.html', {'expedition': expedition, 'expedition_next':expedition_next, 'expedition_prev':expedition_prev, 'logbookentries':logbookentries, 'message':message, })
def get_absolute_url(self):
return ('expedition', (expedition.year))
@@ -63,47 +64,22 @@ def person(request, first_name='', last_name='', ):
person.save()
return HttpResponseRedirect(reverse('profiles_select_profile'))
- return render_with_context(request,'person.html', {'person': person, })
-
- def get_absolute_url(self):
- return settings.URL_ROOT + self.first_name + '_' + self.last_name
-
-#def person(request, name):
-# person = Person.objects.get(href=name)
-#
+ return render_response(request,'person.html', {'person': person, })
def personexpedition(request, first_name='', last_name='', year=''):
person = Person.objects.get(first_name = first_name, last_name = last_name)
expedition = Expedition.objects.get(year=year)
personexpedition = person.personexpedition_set.get(expedition=expedition)
- return render_with_context(request,'personexpedition.html', {'personexpedition': personexpedition, })
-
-def newQMlink(logbookentry):
- biggestQMnumber=0
- if logbookentry.cave:
- for log in logbookentry.cave.logbookentry_set.all():
- try:
- biggestQMnumberInLog = logbookentry.QMs_found.order_by('-number')[0].number
- except IndexError:
- biggestQMnumberInLog = 0
- if biggestQMnumberInLog > biggestQMnumber:
- biggestQMnumber = biggestQMnumberInLog
- else:
- return None
-
-
-
- nextQMnumber=biggestQMnumber+1
- return settings.URL_ROOT + r'/admin/expo/qm/add/?' + r'found_by=' + str(logbookentry.pk) +'&number=' + str(nextQMnumber)
+ return render_response(request,'personexpedition.html', {'personexpedition': personexpedition, })
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})
+ return render_response(request, 'object_list.html',{'object_list':logbookentry})
else:
logbookentry=logbookentry[0]
- return render_with_context(request, 'logbookentry.html', {'logbookentry': logbookentry, 'newQMlink':newQMlink(logbookentry)})
+ return render_response(request, 'logbookentry.html', {'logbookentry': logbookentry})
def logbookSearch(request, extra):
query_string = ''
@@ -113,11 +89,11 @@ def logbookSearch(request, extra):
entry_query = search.get_query(query_string, ['text','title',])
found_entries = LogbookEntry.objects.filter(entry_query)
- return render_with_context(request,'logbooksearch.html',
+ return render_response(request,'logbooksearch.html',
{ 'query_string': query_string, 'found_entries': found_entries, })
#context_instance=RequestContext(request))
def personForm(request,pk):
person=Person.objects.get(pk=pk)
form=PersonForm(instance=person)
- return render_with_context(request,'personform.html', {'form':form,}) \ No newline at end of file
+ return render_response(request,'personform.html', {'form':form,}) \ No newline at end of file
diff --git a/core/views_other.py b/core/views_other.py
index 07a4a75..4a10a53 100644
--- a/core/views_other.py
+++ b/core/views_other.py
@@ -23,15 +23,9 @@ def stats(request):
return render_with_context(request,'statistics.html', statsDict)
def frontpage(request):
- message = "no test message" #reverse('personn', kwargs={"name":"hkjhjh"})
- if "reloadexpos" in request.GET:
- message = LoadPersonsExpos()
- message = "Reloaded personexpos"
- if "reloadsurvex" in request.POST:
- message = LoadAllSurvexBlocks()
- message = "Reloaded survexblocks"
+ if request.user.is_authenticated:
+ return render_with_context(request,'tasks.html')
- #'randSent':randSent.randomLogbookSentence(),
expeditions = Expedition.objects.order_by("-year")
logbookentry = LogbookEntry
cave = Cave
@@ -153,3 +147,13 @@ def ajax_test(request):
def eyecandy(request):
return render_with_context(request,'eyecandy.html', {})
+
+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) \ No newline at end of file
diff --git a/media/js/QM_helper.js b/media/js/QM_helper.js
new file mode 100644
index 0000000..785d193
--- /dev/null
+++ b/media/js/QM_helper.js
@@ -0,0 +1,20 @@
+ $(document).ready(function(){
+
+$('.number:first').append("<a href='javascript:void(0)' class='next_qm_link'>get next number</a>");
+
+new_qm_link=function(e){
+if ($('#id_cave:first')[0].value != "")
+{
+
+$.post('/newqmnumber/',{'cave':$('#id_cave')[0].value,'year':$('#id_expedition')[0].value}, function(data){
+ $('#id_QMs_found-0-number')[0].value=data;
+});
+}
+else {
+alert('Please choose a cave and try again.')
+};
+};
+
+$('.next_qm_link').bind("click", new_qm_link);
+
+ }); \ No newline at end of file
diff --git a/parsers/subcaves.py b/parsers/subcaves.py
index c3acc4d..bdd64a1 100644
--- a/parsers/subcaves.py
+++ b/parsers/subcaves.py
@@ -37,7 +37,20 @@ def importSubcaves(cave):
logging.info("Added " + unicode(newSubcave) + " to " + unicode(cave))
except IOError:
logging.info("Subcave import couldn't open "+subcaveFilePath)
-
+
+def getLinksInSubcaveDescription(subcave):
+ pattern='<a href=\"(.*?)\">(.*?)</a>'
+ if subcave.description:
+ return re.findall(pattern,subcave.description)
+ else:
+ return []
+
+def getLinksInAllSubcaves():
+ bigList=[]
+ for subcave in Subcave.objects.all():
+ bigList+=getLinksInSubcaveDescription(subcave)
+ return bigList
+
def importAllSubcaves():
for cave in Cave.objects.all():
importSubcaves(cave)
diff --git a/urls.py b/urls.py
index a3686ae..e6dcaa5 100644
--- a/urls.py
+++ b/urls.py
@@ -1,5 +1,5 @@
from django.conf.urls.defaults import *
-import troggle.settings as settings
+from django.conf import settings
from core.views import * # flat import
from core.views_caves import *
@@ -18,7 +18,7 @@ urlpatterns = patterns('',
url(r'^caves/?$', views_caves.caveindex, name="caveindex"),
url(r'^people/?$', views_logbooks.personindex, name="personindex"),
-
+ url(r'^newqmnumber/?$', views_other.ajax_QM_number, ),
#(r'^person/(?P<person_id>\d*)/?$', views_logbooks.person),
url(r'^person/(?P<first_name>[A-Z]*[a-z\-\']*)[^a-zA-Z]*(?P<last_name>[a-z\-\']*[^a-zA-Z]*[A-Z]*[a-z\-]*)/?', views_logbooks.person, name="person"),
#url(r'^person/(\w+_\w+)$', views_logbooks.person, name="person"),
@@ -70,8 +70,7 @@ urlpatterns = patterns('',
url(r'^eyecandy$', views_other.eyecandy),
(r'^admin/doc/?', include('django.contrib.admindocs.urls')),
- (r'^admin/(.*)/?', admin.site.root),
- #url(r'^admin/', include(admin.site.urls),name="admin"),
+ (r'^admin/', include(admin.site.urls)),
(r'^accounts/', include('registration.urls')),
(r'^profiles/', include('profiles.urls')),