diff options
Diffstat (limited to 'chimere/models.py')
-rw-r--r-- | chimere/models.py | 169 |
1 files changed, 158 insertions, 11 deletions
diff --git a/chimere/models.py b/chimere/models.py index 827a0e7..c393cba 100644 --- a/chimere/models.py +++ b/chimere/models.py @@ -25,6 +25,8 @@ import simplejson as json from lxml import etree from PIL import Image from subprocess import Popen, PIPE +from BeautifulSoup import BeautifulSoup + from django import forms from django.conf import settings from django.contrib import admin @@ -45,13 +47,64 @@ from chimere.managers import BaseGeoManager from chimere.utils import KMLManager, OSMManager, ShapefileManager, \ GeoRSSManager, CSVManager +class Page(models.Model): + """Simple extra pages + """ + title = models.CharField(_(u"Name"), max_length=150) + mnemonic = models.CharField(_(u"Mnemonic"), max_length=10, blank=True, + null=True) + available = models.BooleanField(_(u"Available"), default=True) + order = models.IntegerField(_(u"Order"), default=10, blank=True, null=True) + template_path = models.CharField(_(u"Template path"), max_length=150, + blank=True, null=True) + content = models.TextField(blank=True, null=True) + def __unicode__(self): + ordering = ["order"] + return self.title + class Meta: + verbose_name = _(u"Page") + verbose_name_plural = _(u"Page") + +def page_post_save(sender, **kwargs): + if not kwargs['instance']: + return + page = kwargs['instance'] + if not page.mnemonic: + page.mnemonic = defaultfilters.slugify(page.title) + page.save() +post_save.connect(page_post_save, sender=Page) + +def shortify(text): + if not text: + return '' + if len(text) <= settings.CHIMERE_SHORT_DESC_LENGTH: + return text + desc = text[:settings.CHIMERE_SHORT_DESC_LENGTH] + short_desc = "" + # find a correct opportunity to cut + for idx, c in enumerate(reversed(desc)): + if c == '>': + break + if c == '<': + short_desc = desc[:-(idx+1)] + break + if not short_desc: + for idx, c in enumerate(reversed(desc)): + if c == ' ' or c == '\n': + short_desc = desc[:-(idx+1)] + break + return BeautifulSoup(short_desc).prettify() + class News(models.Model): """News of the site """ title = models.CharField(_(u"Name"), max_length=150) available = models.BooleanField(_(u"Available")) + is_front_page = models.NullBooleanField(_(u"Is front page"), blank=True, + null=True) date = models.DateField(_(u"Date"), auto_now_add=True) content = models.TextField() + url = models.URLField(_(u"Url"), max_length=200, blank=True, null=True) areas = SelectMultipleField('Area', verbose_name=_(u"Associated areas"), blank=True, null=True) def __unicode__(self): @@ -61,6 +114,10 @@ class News(models.Model): verbose_name = _(u"News") verbose_name_plural = _(u"News") + @property + def short_desc(self): + return shortify(self.content) + class TinyUrl(models.Model): """Tinyfied version of permalink parameters """ @@ -156,14 +213,21 @@ class SubCategory(models.Model): available = models.BooleanField(_(u"Available"), default=True) submission = models.BooleanField(_(u"Available for submission"), default=True) - icon = models.ForeignKey(Icon, verbose_name=_(u"Icon")) - color_theme = models.ForeignKey(ColorTheme, verbose_name=_(u"Color theme"), - blank=True, null=True) - order = models.IntegerField(_(u"Order"), default=1000) TYPE = (('M', _(u'Marker')), ('R', _(u'Route')), ('B', _(u'Both')),) item_type = models.CharField(_(u"Item type"), max_length=1, choices=TYPE) + dated = models.BooleanField(_(u"Is dated"), default=False) + description = models.TextField(blank=True, null=True) + icon = models.ForeignKey(Icon, verbose_name=_(u"Icon")) + hover_icon = models.ForeignKey(Icon, verbose_name=_(u"Hover icon"), + blank=True, null=True, related_name='subcat_hovered') + color_theme = models.ForeignKey(ColorTheme, verbose_name=_(u"Color theme"), + blank=True, null=True) + as_layer = models.BooleanField(_(u"Displayed in the layer menu"), + default=False) + routing_warn = models.BooleanField(_(u"Routing warn"), default=False) + order = models.IntegerField(_(u"Order"), default=1000) def __unicode__(self): return u"%s / %s" % (self.category.name, self.name) class Meta: @@ -207,6 +271,32 @@ class SubCategory(models.Model): subcategories = sorted(subcategories, key=get_cat_order) return subcategories + @classmethod + def getAvailableTuples(cls, area_name=None): + cats = [] + for cat, subcats in cls.getAvailable(area_name=area_name): + cats.append((unicode(cat), + [(subcat.pk, subcat.name) for subcat in subcats])) + return cats + + def getJSONDict(self): + items = {'id':self.pk, 'name':self.name, + 'description':self.description if self.description\ + else '', + 'icon':{'url':self.icon.image.url, + 'width':self.icon.image.width, + 'height':self.icon.image.height} + } + if self.hover_icon: + items['icon_hover'] = {'url':self.hover_icon.image.url} + return items + + def getJSON(self, categories_id=[]): + '''Return a JSON string - mainly used to get description + ''' + json_string = json.dumps(self.getJSONDict()) + return json_string + IMPORTERS = {'KML':KMLManager, 'OSM':OSMManager, 'SHP':ShapefileManager, @@ -338,6 +428,10 @@ class GeographicItem(models.Model): def properties(cls): return [pm for pm in PropertyModel.objects.filter(available=True)] + @classmethod + def all_properties(cls): + return [pm for pm in PropertyModel.objects.all()] + def property_setter(cls, propertymodel): def setter(self, value): marker = self @@ -360,6 +454,8 @@ class Marker(GeographicItem): route = models.ForeignKey(u"Route", blank=True, null=True, related_name='associated_marker') description = models.TextField(_(u"Description"), blank=True, null=True) + is_front_page = models.NullBooleanField(_(u"Is front page"), blank=True, + null=True) objects = models.GeoManager() def __unicode__(self): @@ -368,7 +464,7 @@ class Marker(GeographicItem): def __init__(self, *args, **kwargs): super(Marker, self).__init__(*args, **kwargs) # add read attributes for properties - for pm in self.properties(): + for pm in self.all_properties(): attr_name = pm.getAttrName() if not hasattr(self, attr_name): val = '' @@ -412,6 +508,10 @@ class Marker(GeographicItem): return self.start_date @property + def short_desc(self): + return shortify(self.description) + + @property def geometry(self): return self.point.wkt @@ -467,6 +567,18 @@ class Marker(GeographicItem): if len(properties) > 1: for property in properties[1:]: property.delete() + if pm.type == 'C' and value: + try: + value = str(int(value)) + except ValueError: + choice = PropertyModelChoice.objects.filter(propertymodel=pm, + value=value) + if choice.count(): + value = choice.all()[0].pk + else: + choice = PropertyModelChoice.objects.create(value=value, + propertymodel=pm) + value = choice.pk # new property if not properties: new_property = Property.objects.create(marker=self, @@ -498,12 +610,18 @@ class Marker(GeographicItem): items = {'id':self.id, 'name':json.dumps(self.name), 'geometry':self.point.geojson, 'icon_path':cat.icon.image, + 'icon_hover_path':cat.hover_icon.image \ + if cat.hover_icon else '', 'icon_width':cat.icon.image.width, - 'icon_height':cat.icon.image.height,} + 'icon_height':cat.icon.image.height, + 'category_name':json.dumps(cat.name)} jsons.append(u'{"type":"Feature", "geometry":%(geometry)s, '\ u'"properties":{"pk": %(id)d, "name": %(name)s, '\ - u'"icon_path":"%(icon_path)s", "icon_width":%(icon_width)d, '\ - u'"icon_height":%(icon_height)d}}' % items) + u'"icon_path":"%(icon_path)s", '\ + u'"icon_hover_path":"%(icon_hover_path)s", '\ + u'"icon_width":%(icon_width)d, '\ + u'"icon_height":%(icon_height)d, '\ + u'"category_name":%(category_name)s}}' % items) return ",".join(jsons) @property @@ -1337,11 +1455,15 @@ class PropertyModel(models.Model): TYPE = (('T', _('Text')), ('L', _('Long text')), ('P', _('Password')), - ('D', _("Date"))) + ('D', _("Date")), + ('C', _("Choices")), + ) TYPE_WIDGET = {'T':forms.TextInput, 'L':TextareaWidget, 'P':forms.PasswordInput, - 'D':DatePickerWidget} + 'D':DatePickerWidget, + 'C':forms.Select + } type = models.CharField(_(u"Type"), max_length=1, choices=TYPE) def __unicode__(self): return self.name @@ -1359,6 +1481,19 @@ class PropertyModel(models.Model): ''' return 'property_%d_%d' % (self.order, self.id) +class PropertyModelChoice(models.Model): + '''Choices for property model + ''' + propertymodel = models.ForeignKey(PropertyModel, related_name='choices', + verbose_name=_(u"Property model")) + value = models.CharField(_(u"Value"), max_length=150) + available = models.BooleanField(_(u"Available"), default=True) + def __unicode__(self): + return unicode(self.value) + + class Meta: + verbose_name = _(u"Model property choice") + class Property(models.Model): '''Property for a POI ''' @@ -1367,7 +1502,14 @@ class Property(models.Model): verbose_name=_(u"Property model")) value = models.TextField(_(u"Value")) def __unicode__(self): - return "%s : %s" % (str(self.propertymodel), self.value) + if self.propertymodel.type == 'C': + try: + return unicode(PropertyModelChoice.objects.get( + pk=self.value).value) + except self.DoesNotExist: + return "" + return unicode(self.value) + class Meta: verbose_name = _(u"Property") @@ -1378,6 +1520,11 @@ class Property(models.Model): return datetime.date(*[int(val) for val in self.value.split('-')]) except: return "" + if self.propertymodel.type == 'C' and self.value: + try: + return PropertyModelChoice.objects.get(pk=self.value) + except self.DoesNotExist: + return None else: return self.value |