diff --git a/core/models.py b/core/models.py index 64529f1..08504c0 100644 --- a/core/models.py +++ b/core/models.py @@ -65,6 +65,8 @@ class TroggleImageModel(ImageModel): class Expedition(TroggleModel): year = models.CharField(max_length=20, unique=True) name = models.CharField(max_length=100) + + # these will become min and max dates date_from = models.DateField(blank=True,null=True) date_to = models.DateField(blank=True,null=True) @@ -78,7 +80,19 @@ class Expedition(TroggleModel): def get_absolute_url(self): return urlparse.urljoin(settings.URL_ROOT, reverse('expedition', args=[self.year])) - + 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 + + +class ExpeditionDay(TroggleModel): + expedition = models.ForeignKey("Expedition") + date = models.DateField() # # single Person, can go on many years @@ -168,7 +182,7 @@ class PersonExpedition(TroggleModel): return res class Meta: - ordering = ('expedition',) + ordering = ('-expedition',) #order_with_respect_to = 'expedition' get_latest_by = 'expedition' @@ -242,6 +256,7 @@ class LogbookEntry(TroggleModel): class PersonTrip(TroggleModel): person_expedition = models.ForeignKey(PersonExpedition,null=True) + expeditionday = models.ForeignKey("ExpeditionDay") date = models.DateField() time_underground = models.FloatField(help_text="In decimal hours") logbook_entry = models.ForeignKey(LogbookEntry) diff --git a/core/models_survex.py b/core/models_survex.py index c6eb5b9..f3fc61d 100644 --- a/core/models_survex.py +++ b/core/models_survex.py @@ -77,6 +77,7 @@ class SurvexBlock(models.Model): 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) diff --git a/core/views_logbooks.py b/core/views_logbooks.py index 1ce158e..17c88fd 100644 --- a/core/views_logbooks.py +++ b/core/views_logbooks.py @@ -78,15 +78,9 @@ def GetPersonChronology(personexpedition): a = res.setdefault(persontrip.date, { }) a.setdefault("persontrips", [ ]).append(persontrip) - for personrole in personexpedition.personrole_set.all(): + for personrole in personexpedition.survexpersonrole_set.all(): a = res.setdefault(personrole.survexblock.date, { }) - b = a.setdefault("personroles", { }) - survexpath = personrole.survexblock.survexpath - - if b.get(survexpath): - b[survexpath] += ", " + str(personrole.nrole) - else: - b[survexpath] = str(personrole.nrole) + a.setdefault("personroles", [ ]).append(personrole.survexblock) # build up the tables rdates = res.keys() @@ -96,7 +90,7 @@ def GetPersonChronology(personexpedition): res2 = [ ] for rdate in rdates: persontrips = res[rdate].get("persontrips", []) - personroles = list(res[rdate].get("personroles", {}).items()) + 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]))) diff --git a/media/css/main3.css b/media/css/main3.css index 4d94049..4652486 100644 --- a/media/css/main3.css +++ b/media/css/main3.css @@ -45,7 +45,7 @@ div#content h2 { text-align:center; font-size:200%; - padding-bottom:30px; + Dpadding-bottom:30px; } table.prevnextexpeditions @@ -118,7 +118,7 @@ div.centre img { vertical-align: middle; } h1 { text-align: center; font-size: 210%; display: inline;} h2 { } -h3 { color: #000 text-align:left; border-bottom:thin solid black; margin-bottom:1em; margin-top:1em; font-weight:bold} +h3 { color: #000 text-align:left; Dborder-bottom:thin solid black; margin-bottom:1em; margin-top:1em; font-weight:bold} h4 { color: #0d664c; } h4.navbar {line-height: 0px;} img.onright, div.onright { vertical-align: top; float: right; diff --git a/modelviz.py b/modelviz.py new file mode 100755 index 0000000..e3ada4b --- /dev/null +++ b/modelviz.py @@ -0,0 +1,201 @@ +#!/usr/bin/env python +"""Django model to DOT (Graphviz) converter +by Antonio Cavedoni <antonio@cavedoni.org> + +Make sure your DJANGO_SETTINGS_MODULE is set to your project or +place this script in the same directory of the project and call +the script like this: + +$ python modelviz.py [-h] [-d] <app_label> ... <app_label> > <filename>.dot +$ dot <filename>.dot -Tpng -o <filename>.png + +options: + -h, --help + show this help message and exit. + + -d, --disable_fields + don't show the class member fields. +""" +__version__ = "0.8" +__svnid__ = "$Id: modelviz.py 78 2007-07-15 19:04:47Z verbosus $" +__license__ = "Python" +__author__ = "Antonio Cavedoni <http://cavedoni.com/>" +__contributors__ = [ + "Stefano J. Attardi <http://attardi.org/>", + "limodou <http://www.donews.net/limodou/>", + "Carlo C8E Miron", + "Andre Campos <cahenan@gmail.com>", + "Justin Findlay <jfindlay@gmail.com>", + ] + +import getopt, sys + +from django.core.management import setup_environ + +try: + import settings +except ImportError: + pass +else: + setup_environ(settings) + +from django.template import Template, Context +from django.db import models +from django.db.models import get_models +from django.db.models.fields.related import \ + ForeignKey, OneToOneField, ManyToManyField + +try: + from django.db.models.fields.generic import GenericRelation +except ImportError: + from django.contrib.contenttypes.generic import GenericRelation + +head_template = """ +digraph name { + fontname = "Helvetica" + fontsize = 8 + + node [ + fontname = "Helvetica" + fontsize = 8 + shape = "plaintext" + ] + edge [ + fontname = "Helvetica" + fontsize = 8 + ] + +""" + +body_template = """ + {% for model in models %} + {% for relation in model.relations %} + {{ relation.target }} [label=< + <TABLE BGCOLOR="palegoldenrod" BORDER="0" CELLBORDER="0" CELLSPACING="0"> + <TR><TD COLSPAN="2" CELLPADDING="4" ALIGN="CENTER" BGCOLOR="olivedrab4" + ><FONT FACE="Helvetica Bold" COLOR="white" + >{{ relation.target }}</FONT></TD></TR> + </TABLE> + >] + {{ model.name }} -> {{ relation.target }} + [label="{{ relation.name }}"] {{ relation.arrows }}; + {% endfor %} + {% endfor %} + + {% for model in models %} + {{ model.name }} [label=< + <TABLE BGCOLOR="palegoldenrod" BORDER="0" CELLBORDER="0" CELLSPACING="0"> + <TR><TD COLSPAN="2" CELLPADDING="4" ALIGN="CENTER" BGCOLOR="olivedrab4" + ><FONT FACE="Helvetica Bold" COLOR="white" + >{{ model.name }}</FONT></TD></TR> + + {% if not disable_fields %} + {% for field in model.fields %} + <TR><TD ALIGN="LEFT" BORDER="0" + ><FONT {% if field.blank %}COLOR="#7B7B7B" {% endif %}FACE="Helvetica Bold">{{ field.name }}</FONT + ></TD> + <TD ALIGN="LEFT" + ><FONT {% if field.blank %}COLOR="#7B7B7B" {% endif %}FACE="Helvetica Bold">{{ field.type }}</FONT + ></TD></TR> + {% endfor %} + {% endif %} + </TABLE> + >] + {% endfor %} +""" + +tail_template = """ +} +""" + +def generate_dot(app_labels, **kwargs): + disable_fields = kwargs.get('disable_fields', False) + + dot = head_template + + for app_label in app_labels: + app = models.get_app(app_label) + graph = Context({ + 'name': '"%s"' % app.__name__, + 'disable_fields': disable_fields, + 'models': [] + }) + + for appmodel in get_models(app): + model = { + 'name': appmodel.__name__, + 'fields': [], + 'relations': [] + } + + # model attributes + def add_attributes(): + model['fields'].append({ + 'name': field.name, + 'type': type(field).__name__, + 'blank': field.blank + }) + + for field in appmodel._meta.fields: + add_attributes() + + if appmodel._meta.many_to_many: + for field in appmodel._meta.many_to_many: + add_attributes() + + # relations + def add_relation(extras=""): + _rel = { + 'target': field.rel.to.__name__, + 'type': type(field).__name__, + 'name': field.name, + 'arrows': extras + } + if _rel not in model['relations']: + model['relations'].append(_rel) + + for field in appmodel._meta.fields: + if isinstance(field, ForeignKey): + add_relation() + elif isinstance(field, OneToOneField): + add_relation("[arrowhead=none arrowtail=none]") + + if appmodel._meta.many_to_many: + for field in appmodel._meta.many_to_many: + if isinstance(field, ManyToManyField): + add_relation("[arrowhead=normal arrowtail=normal]") + elif isinstance(field, GenericRelation): + add_relation( + '[style="dotted"] [arrowhead=normal arrowtail=normal]') + graph['models'].append(model) + + t = Template(body_template) + dot += '\n' + t.render(graph) + + dot += '\n' + tail_template + + return dot + +def main(): + try: + opts, args = getopt.getopt(sys.argv[1:], "hd", + ["help", "disable_fields"]) + except getopt.GetoptError, error: + print __doc__ + sys.exit(error) + else: + if not args: + print __doc__ + sys.exit() + + kwargs = {} + for opt, arg in opts: + if opt in ("-h", "--help"): + print __doc__ + sys.exit() + if opt in ("-d", "--disable_fields"): + kwargs['disable_fields'] = True + print generate_dot(args, **kwargs) + +if __name__ == "__main__": + main() diff --git a/parsers/logbooks.py b/parsers/logbooks.py index cc5db5a..ec314b6 100644 --- a/parsers/logbooks.py +++ b/parsers/logbooks.py @@ -91,10 +91,11 @@ def EnterLogIntoDbase(date, place, title, text, trippeople, expedition, logtime_ lookupAttribs={'date':date, 'title':title} nonLookupAttribs={'place':place, 'text':text, 'author':author, 'expedition':expedition, 'cave':cave, 'slug':slugify(title)[:50]} lbo, created=save_carefully(models.LogbookEntry, lookupAttribs, nonLookupAttribs) - + expeditiondate = expedition.get_expedition_date(date) + for tripperson, time_underground in trippersons: lookupAttribs={'person_expedition':tripperson, 'logbook_entry':lbo} - nonLookupAttribs={'time_underground':time_underground, 'date':date, 'is_logbook_entry_author':(tripperson == author)} + nonLookupAttribs={'time_underground':time_underground, 'date':date, 'expeditiondate':expeditiondate, 'is_logbook_entry_author':(tripperson == author)} #print nonLookupAttribs save_carefully(models.PersonTrip, lookupAttribs, nonLookupAttribs) @@ -186,7 +187,7 @@ def Parseloghtml01(year, expedition, txt): tripid = mtripid and mtripid.group(1) or "" tripheader = re.sub("</?(?:[ab]|span)[^>]*>", "", tripheader) - #print [tripheader] + #print " ", [tripheader] #continue tripdate, triptitle, trippeople = tripheader.split("|") @@ -270,7 +271,7 @@ yearlinks = [ ("1994", "1994/log.htm", Parseloghtml01), ("1993", "1993/log.htm", Parseloghtml01), ("1992", "1992/log.htm", Parseloghtml01), - #("1991", "1991/log.htm", Parseloghtml01), + ("1991", "1991/log.htm", Parseloghtml01), ] def SetDatesFromLogbookEntries(expedition): diff --git a/parsers/survex.py b/parsers/survex.py index e9b018d..985d4e5 100644 --- a/parsers/survex.py +++ b/parsers/survex.py @@ -123,8 +123,9 @@ def RecursiveLoad(survexblock, survexfile, fin, textlines): survexblock.date = re.sub("\.", "-", line) expeditions = models.Expedition.objects.filter(year=line[:4]) if expeditions: + assert len(expeditions) == 1 survexblock.expedition = expeditions[0] - + survexblock.expeditiondate = survexblock.expedition.get_expedition_day(survexblock.date) elif re.match("team$(?i)", cmd): mteammember = re.match("(Insts|Notes|Tape|Dog|Useless|Pics|Helper|Disto|Consultant)\s+(.*)$(?i)", line) if mteammember: diff --git a/templates/base.html b/templates/base.html index 1715340..10e670c 100644 --- a/templates/base.html +++ b/templates/base.html @@ -33,6 +33,7 @@ </div> <div class="toolbarlinks"> <a href="{% url survexcaveslist %}">All Cave Survex</a> | + <a href="{% url surveyscansfolders %}">All scans</a> | <a href="{% url survexcavessingle 161 %}">161</a> | <a href="{% url survexcavessingle 204 %}">204</a> | <a href="{% url survexcavessingle 258 %}">258</a> | diff --git a/templates/personexpedition.html b/templates/personexpedition.html index ac6c902..78018db 100644 --- a/templates/personexpedition.html +++ b/templates/personexpedition.html @@ -6,21 +6,20 @@ {% block content %} -<h2>{{personexpedition.person}}: {{personexpedition.expedition}} ({{personexpedition.date_from}} - {{personexpedition.date_to}})</h2> +<h1> + <a href="{{personexpedition.person.get_absolute_url}}">{{personexpedition.person}}</a> : + <a href="{{personexpedition.expedition.get_absolute_url}}">{{personexpedition.expedition}}</a> +</h1> -<h3>{{message}}</h3> +<p>{{message}}</p> -<p><b><a href="{{ personexpedition.expedition.get_absolute_url }}">Main page for expedition: {{personexpedition.expedition}}</a></b></p> -<p><b><a href="{{ personexpedition.person.get_absolute_url }}">Main page for person: {{personexpedition.person}}</a></b></p> - -<p>List of other expos by this person</p> -<p> +<p><b>Other years:</b> {% for otherpersonexpedition in personexpedition.person.personexpedition_set.all %} -{% ifequal otherpersonexpedition personexpedition %} + {% ifequal otherpersonexpedition personexpedition %} | <b>{{otherpersonexpedition.expedition.year}}</b> -{% else %} - | {{ otherpersonexpedition|link }} -{% endifequal %} + {% else %} + | <a href="{{otherpersonexpedition.get_absolute_url}}">{{ otherpersonexpedition.expedition.year }}</a> + {% endifequal %} {% endfor %} </p> @@ -40,8 +39,12 @@ {% endif %} {% if persondate.2 %} - <td class="survexblock"><a href="{% url survexblock persondate.2.0 %}">{{persondate.2.0}}</a></td> - <td class="roles">{{persondate.2.1}}</td> + <td class="survexblock"><a href="{% url svx persondate.2.survexfile.path %}">{{persondate.2}}</a></td> + <td class="roles"> + {% for survexpersonrole in persondate.2.survexpersonrole_set.all %} + {{survexpersonrole.nrole}} + {% endfor %} + </td> {% else %} <td colspan="2"> </td> {% endif %}