diff options
Diffstat (limited to 'chimere/models.py')
| -rw-r--r-- | chimere/models.py | 138 |
1 files changed, 130 insertions, 8 deletions
diff --git a/chimere/models.py b/chimere/models.py index 31ca0b6..30dda7c 100644 --- a/chimere/models.py +++ b/chimere/models.py @@ -25,6 +25,7 @@ import simplejson as json from lxml import etree from PIL import Image from subprocess import Popen, PIPE +from BeautifulSoup import BeautifulSoup from django.conf import settings from django.contrib.gis.db import models @@ -43,13 +44,64 @@ from chimere.widgets import PointField, RouteField, SelectMultipleField, \ from chimere.managers import BaseGeoManager from chimere.utils import KMLManager, OSMManager, ShapefileManager +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) def __unicode__(self): ordering = ["-date"] return self.title @@ -57,6 +109,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 """ @@ -153,10 +209,12 @@ class SubCategory(models.Model): color_theme = models.ForeignKey(ColorTheme, verbose_name=_(u"Color theme"), blank=True, null=True) order = models.IntegerField(_(u"Order")) + dated = models.BooleanField(_(u"Is dated"), default=False) TYPE = (('M', _(u'Marker')), ('R', _(u'Route')), ('B', _(u'Both')),) item_type = models.CharField(_(u"Item type"), max_length=1, choices=TYPE) + description = models.TextField(blank=True, null=True) def __unicode__(self): return u"%s / %s" % (self.category.name, self.name) class Meta: @@ -194,6 +252,24 @@ class SubCategory(models.Model): return [(category, sub_cats) for category, sub_cats \ in sub_categories.items()] + @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 getJSON(self, categories_id=[]): + '''Return a JSON string - mainly used to get description + ''' + items = {'id':self.pk, 'name':json.dumps(self.name), + 'description':json.dumps(self.description) if self.description\ + else ''} + json_string = u'{"pk": %(id)d, "name": %(name)s, '\ + u'"description":%(description)s}' % items + return json_string + IMPORTERS = {'KML':KMLManager, 'OSM':OSMManager, 'SHP':ShapefileManager @@ -312,6 +388,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): @@ -360,6 +438,10 @@ class Marker(GeographicItem): if settings.CHIMERE_DAYS_BEFORE_EVENT: return self.start_date + @property + def short_desc(self): + return shortify(self.description) + class Meta: ordering = ('status', 'name') verbose_name = _(u"Point of interest") @@ -520,17 +602,30 @@ IFRAME_LINKS = { 'youtube':((re.compile(r'youtube.com\/watch\?v=([A-Za-z0-9_-]*)'), re.compile(r'youtu.be\/([A-Za-z0-9_-]*)'), re.compile(r'youtube.com\/embed\/([A-Za-z0-9_-]*)')), - "http://www.youtube.com/embed/%s"), + "http://www.youtube.com/embed/%s"), 'dailymotion':( (re.compile(r'dailymotion.com/video/([A-Za-z0-9]*)_[A-Za-z0-9_-]*'), re.compile(r'dailymotion.com/embed/video/([A-Za-z0-9]*)'), re.compile("http://www.dailymotion.com/embed/video/%s")), - 'http://www.dailymotion.com/embed/video/%s'), + 'http://www.dailymotion.com/embed/video/%s'), 'vimeo':((re.compile(r'vimeo.com/([A-Za-z0-9]*)'), re.compile(r'vimeo.com/video/([A-Za-z0-9]*)')), - "http://player.vimeo.com/video/%s") + "http://player.vimeo.com/video/%s") } +class MultimediaExtension(models.Model): + name = models.CharField(_(u"Extension name"), max_length=6) + multimedia_type = models.ForeignKey(MultimediaType, + verbose_name=_(u"Associated multimedia type"), + related_name='extensions') + + class Meta: + verbose_name = _(u"Multimedia extension") + verbose_name_plural = _(u"Multimedia extensions") + + def __unicode__(self): + return self.name + class MultimediaFile(models.Model): name = models.CharField(_(u"Name"), max_length=150) url = models.URLField(_(u"Url"), max_length=200) @@ -574,7 +669,6 @@ def multimediafile_post_save(sender, **kwargs): multimediafile.save() post_save.connect(multimediafile_post_save, sender=MultimediaFile) - class PictureFile(models.Model): name = models.CharField(_(u"Name"), max_length=150) picture = models.ImageField(_(u"Image"), upload_to='pictures', @@ -606,7 +700,6 @@ def scale_image(max_x, pair): new_y = (float(max_x) / x) * y return (int(max_x), int(new_y)) - IMAGE_EXIF_ORIENTATION_MAP = { 1: 0, 8: 2, @@ -1049,11 +1142,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 @@ -1071,6 +1168,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 ''' @@ -1079,7 +1189,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") @@ -1090,6 +1207,11 @@ class Property(models.Model): return datetime.date(*[int(val) for val in self.value.split('-')]) except: return "" + if self.propertymodel.type == 'C': + try: + return PropertyModelChoice.objects.get(pk=self.value) + except self.DoesNotExist: + return None else: return self.value |
