diff options
Diffstat (limited to 'chimere/main/models.py')
| -rw-r--r-- | chimere/main/models.py | 121 |
1 files changed, 79 insertions, 42 deletions
diff --git a/chimere/main/models.py b/chimere/main/models.py index f633b3f..093918b 100644 --- a/chimere/main/models.py +++ b/chimere/main/models.py @@ -20,6 +20,8 @@ """ Models description """ +from datetime import datetime, timedelta + from django.utils.translation import ugettext_lazy as _ from django.contrib.gis.db import models @@ -27,8 +29,7 @@ from django.contrib.gis.gdal import SpatialReference from django.contrib import admin from chimere import settings -from chimere.main.widgets import PointField, RouteField, \ - ManyToManyField_NoSyncdb +from chimere.main.widgets import PointField, RouteField, SelectMultipleField class News(models.Model): """News of the site @@ -42,6 +43,7 @@ class News(models.Model): return self.title class Meta: verbose_name = _("News") + verbose_name_plural = _("News") class TinyUrl(models.Model): """Tinyfied version of permalink parameters @@ -122,6 +124,8 @@ class Icon(models.Model): name = models.CharField(_("Name"), max_length=150) image = models.ImageField(_("Image"), upload_to='icons', height_field='height', width_field='width') + height = models.IntegerField(_("Height")) + width = models.IntegerField(_("Width")) def __unicode__(self): return self.name class Meta: @@ -133,8 +137,7 @@ class SubCategory(models.Model): category = models.ForeignKey(Category, verbose_name=_("Category")) name = models.CharField(_("Name"), max_length=150) available = models.BooleanField(_("Available")) - areas = models.ManyToManyField('Area', related_name='areas', - blank=True, null=True) + areas = SelectMultipleField('Area', related_name='areas', blank=True) icon = models.ForeignKey(Icon, verbose_name=_("Icon")) color_theme = models.ForeignKey(ColorTheme, verbose_name=_("Color theme"), blank=True, null=True) @@ -163,8 +166,8 @@ class SubCategory(models.Model): if area_name: area = Area.objects.get(urn=area_name) # if there some restrictions with categories limit them - if area.subcategories.count(): - sub_ids = [sub.id for sub in area.subcategories.all()] + if area.subcategory_set.count(): + sub_ids = [sub.id for sub in area.subcategory_set.all()] # if no area is defined for a category don't filter it sub_ids += [sub.id for sub in subcategories if not sub.areas.count()] @@ -183,10 +186,12 @@ class Marker(models.Model): '''Marker for a POI ''' name = models.CharField(_("Name"), max_length=150) - subcategory = models.ForeignKey(SubCategory, verbose_name=_("Subcategory")) - point = PointField(_("Localisation")) + categories = SelectMultipleField(SubCategory) + point = PointField(_("Localisation"), srid=settings.EPSG_DISPLAY_PROJECTION) picture = models.ImageField(_("Image"), upload_to='upload', blank=True, - height_field='height', width_field='width') + null=True, height_field='height', width_field='width') + height = models.IntegerField(_("Height"), blank=True, null=True) + width = models.IntegerField(_("Width"), blank=True, null=True) STATUS = (('S', _('Submited')), ('A', _('Available')), ('D', _('Disabled')),) @@ -194,13 +199,23 @@ class Marker(models.Model): for key, label in STATUS: STATUS_DCT[key] = label status = models.CharField(_("Status"), max_length=1, choices=STATUS) + if settings.DAYS_BEFORE_EVENT: + start_date = models.DateField(_("Start date"), blank=True, null=True, +help_text=_("Not mandatory. Set it for dated item such as event. \ +Format YYYY-MM-DD")) + end_date = models.DateField(_("End date"), blank=True, null=True, +help_text=_("Not mandatory. Set it only if you have a multi-day event. \ +Format YYYY-MM-DD")) + if 'chimere.rss' in settings.INSTALLED_APPS: + available_date = models.DateTimeField(_("Available Date"), blank=True, + null=True) objects = models.GeoManager() def __unicode__(self): return self.name class Meta: - ordering = ('subcategory__category', 'subcategory', 'status', 'name') + ordering = ('status', 'name') verbose_name = _("Point of interest") def getLatitude(self): @@ -236,31 +251,44 @@ class Marker(models.Model): properties.append(property) return properties - def getGeoJSON(self): + def getGeoJSON(self, categories_id=[]): '''Return a GeoJSON string ''' - return """{"type":"Feature", "geometry":%(geometry)s, \ + jsons = [] + for cat in self.categories.all(): + if categories_id and cat.id not in categories_id: + continue + jsons.append("""{"type":"Feature", "geometry":%(geometry)s, \ "properties":{"pk": %(id)d, "name": "%(name)s", \ "icon_path":"%(icon_path)s", "icon_width":%(icon_width)d, \ "icon_height":%(icon_height)d}}""" % {'id':self.id, 'name':self.name, -'icon_path':self.subcategory.icon.image, 'geometry':self.point.geojson, -'icon_width':self.subcategory.icon.image.width, -'icon_height':self.subcategory.icon.image.height,} +'icon_path':cat.icon.image, 'geometry':self.point.geojson, +'icon_width':cat.icon.image.width, 'icon_height':cat.icon.image.height,}) + return ",".join(jsons) class Route(models.Model): '''Route on the map ''' name = models.CharField(_("Name"), max_length=150) - subcategory = models.ForeignKey(SubCategory, verbose_name=_("Subcategory")) - route = RouteField(_("Route")) + categories = SelectMultipleField(SubCategory) + route = RouteField(_("Route"), srid=settings.EPSG_DISPLAY_PROJECTION) picture = models.ImageField(_("Image"), upload_to='upload', blank=True, - height_field='height', width_field='width') + null=True, height_field='height', width_field='width') + height = models.IntegerField(_("Height"), blank=True, null=True) + width = models.IntegerField(_("Width"), blank=True, null=True) STATUS = (('S', _('Submited')), ('A', _('Available')), ('D', _('Disabled')),) STATUS_DCT = {} for key, label in STATUS: STATUS_DCT[key] = label + if settings.DAYS_BEFORE_EVENT: + start_date = models.DateField(_("Start date"), blank=True, null=True, +help_text=_("Not mandatory. Set it for dated item such as event. \ +Format YYYY-MM-DD")) + end_date = models.DateField(_("End date"), blank=True, null=True, +help_text=_("Not mandatory. Set it only if you have a multi-day event. \ +Format YYYY-MM-DD")) status = models.CharField(_("Status"), max_length=1, choices=STATUS) objects = models.GeoManager() @@ -268,7 +296,7 @@ class Route(models.Model): return self.name class Meta: - ordering = ('subcategory__category', 'subcategory', 'status', 'name') + ordering = ('status', 'name') verbose_name = _("Route") def getProperty(self, propertymodel, safe=None): @@ -304,6 +332,22 @@ class Route(models.Model): "color":"%(color)s"}}""" % {'id':self.id, 'name':self.name, 'color':color, 'geometry':self.route.geojson,} +def getDateCondition(): + ''' + Return an SQL condition for apparition of dates + ''' + if not settings.DAYS_BEFORE_EVENT: + return "" + now = datetime.now().strftime('%Y-%m-%d') + after = (datetime.now() + timedelta(settings.DAYS_BEFORE_EVENT) + ).strftime('%Y-%m-%d') + date_condition = " and %(alias)s.start_date is null or " + date_condition += "(%(alias)s.start_date >= '" + now + "' and " + date_condition += "%(alias)s.start_date <='" + after + "')" + date_condition += " or (%(alias)s.start_date <='" + now + "' and " + date_condition += "%(alias)s.end_date >='" + now + "') " + return date_condition + class SimplePoint: """ Point in the map (not in the database) @@ -352,39 +396,35 @@ class SimpleArea: self.upper_left_corner.x, self.upper_left_corner.y, settings.EPSG_DISPLAY_PROJECTION ) + date_condition = getDateCondition() sql_main = '''select subcat.id as id, subcat.category_id as category_id, subcat.name as name, subcat.available as available, subcat.icon_id as icon_id, subcat.color_theme_id as color_theme_id, subcat.order as order, subcat.item_type as item_type from main_subcategory subcat inner join main_category cat on cat.id=subcat.category_id''' sql = sql_main + ''' -inner join main_marker mark on mark.subcategory_id=subcat.id - and ST_Contains(%s, mark.point)''' % area +inner join main_marker mark on ST_Contains(%s, mark.point)''' % area if equal_status: sql += ' and mark.status' + equal_status + sql += date_condition % {'alias':'mark'} + sql += ''' +inner join main_marker_categories mc on mc.subcategory_id=subcat.id and +mc.marker_id=mark.id''' if filter_available: sql += ' where subcat.available = TRUE and cat.available = TRUE' - print sql - # django > 1.1 - #subcats = SubCategory.objects.raw(sql) - from django.db import connection, transaction - cursor = connection.cursor() - cursor.execute(sql, []) - subcats = set() - for r in cursor.fetchall(): - subcats.add(SubCategory.objects.get(id=r[0])) + subcats = set(SubCategory.objects.raw(sql)) sql = sql_main + ''' -inner join main_route rt on rt.subcategory_id=subcat.id -and (ST_Intersects(%s, rt.route) or ST_Contains(%s, rt.route))''' % (area, area) +inner join main_route rt on (ST_Intersects(%s, rt.route) or +ST_Contains(%s, rt.route))''' % (area, area) if equal_status: sql += ' and rt.status' + equal_status + sql += date_condition % {'alias':'rt'} + sql += ''' +inner join main_route_categories rc on rc.subcategory_id=subcat.id and +rc.route_id=rt.id''' if filter_available: sql += ' where subcat.available = TRUE and cat.available = TRUE' - # django > 1.1 - #subcats += SubCategory.objects.raw(sql) - cursor.execute(sql, []) - for r in cursor.fetchall(): - subcats.add(SubCategory.objects.get(id=r[0])) + subcats.union(SubCategory.objects.raw(sql)) return subcats class Area(models.Model, SimpleArea): @@ -393,15 +433,12 @@ class Area(models.Model, SimpleArea): name = models.CharField(_("Name"), max_length=150) urn = models.SlugField(_("Area urn"), max_length=50, blank=True, unique=True) - subcategories = ManyToManyField_NoSyncdb(SubCategory, - related_name='subcategories', blank=True, null=True, - db_table=u'subcategory_areas') order = models.IntegerField(_("Order")) available = models.BooleanField(_("Available")) upper_left_corner = models.PointField(_("Upper left corner"), - default='POINT(0 0)') + default='POINT(0 0)', srid=settings.EPSG_DISPLAY_PROJECTION) lower_right_corner = models.PointField(_("Lower right corner"), - default='POINT(0 0)') + default='POINT(0 0)', srid=settings.EPSG_DISPLAY_PROJECTION) objects = models.GeoManager() def __unicode__(self): |
