summaryrefslogtreecommitdiff
path: root/chimere/models.py
diff options
context:
space:
mode:
Diffstat (limited to 'chimere/models.py')
-rw-r--r--chimere/models.py644
1 files changed, 318 insertions, 326 deletions
diff --git a/chimere/models.py b/chimere/models.py
index 825b4c0..cb69684 100644
--- a/chimere/models.py
+++ b/chimere/models.py
@@ -20,16 +20,17 @@
"""
Models description
"""
-import os
+import copy
import datetime
+import json
+import os
import pyexiv2
import re
-import copy
-import simplejson as json
+
from lxml import etree
from PIL import Image
from subprocess import Popen, PIPE
-from BeautifulSoup import BeautifulSoup
+from bs4 import BeautifulSoup
from django import forms
from django.conf import settings
@@ -54,21 +55,21 @@ 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,
+ title = models.CharField(_("Name"), max_length=150)
+ mnemonic = models.CharField(_("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,
+ available = models.BooleanField(_("Available"), default=True)
+ order = models.IntegerField(_("Order"), default=10, blank=True, null=True)
+ template_path = models.CharField(_("Template path"), max_length=150,
blank=True, null=True)
content = models.TextField(blank=True, null=True)
class Meta:
ordering = ["order"]
- verbose_name = _(u"Page")
- verbose_name_plural = _(u"Page")
+ verbose_name = _("Page")
+ verbose_name_plural = _("Page")
- def __unicode__(self):
+ def __str__(self):
return self.title
@@ -107,22 +108,22 @@ def shortify(text):
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,
+ title = models.CharField(_("Name"), max_length=150)
+ available = models.BooleanField(_("Available"))
+ is_front_page = models.NullBooleanField(_("Is front page"), blank=True,
null=True)
- date = models.DateField(_(u"Date"))
+ date = models.DateField(_("Date"))
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)
+ url = models.URLField(_("Url"), max_length=200, blank=True, null=True)
+ areas = SelectMultipleField('Area', verbose_name=_("Associated areas"),
+ blank=True)
class Meta:
ordering = ["-date"]
- verbose_name = _(u"News")
- verbose_name_plural = _(u"News")
+ verbose_name = _("News")
+ verbose_name_plural = _("News")
- def __unicode__(self):
+ def __str__(self):
return self.title
@property
@@ -133,15 +134,15 @@ class News(models.Model):
class TinyUrl(models.Model):
"""Tinyfied version of permalink parameters
"""
- parameters = models.CharField(_(u"Parameters"), max_length=500,
+ parameters = models.CharField(_("Parameters"), max_length=500,
unique=True)
digits = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
base = len(digits)
class Meta:
- verbose_name = _(u"TinyUrl")
+ verbose_name = _("TinyUrl")
- def __unicode__(self):
+ def __str__(self):
return self.parameters
@classmethod
@@ -167,7 +168,7 @@ class TinyUrl(models.Model):
while 1:
idx = n % cls.base
urn = cls.digits[idx] + urn
- n = n / cls.base
+ n = int(n / cls.base)
if n == 0:
break
return urn
@@ -176,31 +177,31 @@ class TinyUrl(models.Model):
class ColorTheme(models.Model):
"""Color theme
"""
- name = models.CharField(_(u"Name"), max_length=150)
+ name = models.CharField(_("Name"), max_length=150)
class Meta:
- verbose_name = _(u"Color theme")
+ verbose_name = _("Color theme")
- def __unicode__(self):
+ def __str__(self):
return self.name
class Color(models.Model):
"""Color
"""
- code = models.CharField(_(u"Code/name"), max_length=200,
- help_text=_(u"HTML code/name"))
- inner_code = models.CharField(_(u"Code/name (inner)"), max_length=200,
- help_text=_(u"HTML code/name"),
+ code = models.CharField(_("Code/name"), max_length=200,
+ help_text=_("HTML code/name"))
+ inner_code = models.CharField(_("Code/name (inner)"), max_length=200,
+ help_text=_("HTML code/name"),
blank=True, null=True)
- order = models.IntegerField(_(u"Order"))
- color_theme = models.ForeignKey(ColorTheme, verbose_name=_(u"Color theme"))
+ order = models.IntegerField(_("Order"))
+ color_theme = models.ForeignKey(ColorTheme, verbose_name=_("Color theme"))
class Meta:
ordering = ["order"]
- verbose_name = _(u"Color")
+ verbose_name = _("Color")
- def __unicode__(self):
+ def __str__(self):
return self.code
@property
@@ -215,96 +216,96 @@ class Color(models.Model):
class Category(models.Model):
"""Category of Point Of Interest (POI)
"""
- name = models.CharField(_(u"Name"), max_length=150)
- available = models.BooleanField(_(u"Available"))
- order = models.IntegerField(_(u"Order"))
+ name = models.CharField(_("Name"), max_length=150)
+ available = models.BooleanField(_("Available"))
+ order = models.IntegerField(_("Order"))
description = models.TextField(blank=True, null=True)
class Meta:
ordering = ["order"]
- verbose_name = _(u"Category")
+ verbose_name = _("Category")
- def __unicode__(self):
+ def __str__(self):
return self.name
class Icon(models.Model):
'''Icon
'''
- name = models.CharField(_(u"Name"), max_length=150)
- image = models.ImageField(_(u"Image"), upload_to='icons',
+ name = models.CharField(_("Name"), max_length=150)
+ image = models.ImageField(_("Image"), upload_to='icons',
height_field='height', width_field='width')
- height = models.IntegerField(_(u"Height"))
- width = models.IntegerField(_(u"Width"))
+ height = models.IntegerField(_("Height"))
+ width = models.IntegerField(_("Width"))
offset_x = models.IntegerField(
- _(u"Offset x"), default=10,
- help_text=_(u"Common value is half the icon width"))
+ _("Offset x"), default=10,
+ help_text=_("Common value is half the icon width"))
offset_y = models.IntegerField(
- _(u"Offset y"), default=20,
- help_text=_(u"Common value is icon height"))
- popup_offset_x = models.IntegerField(_(u"Popup offset x"), default=0,
- help_text=_(u"Common value is 0"))
+ _("Offset y"), default=20,
+ help_text=_("Common value is icon height"))
+ popup_offset_x = models.IntegerField(_("Popup offset x"), default=0,
+ help_text=_("Common value is 0"))
popup_offset_y = models.IntegerField(
- _(u"Popup offset y"), default=20,
- help_text=_(u"Common value is icon height"))
+ _("Popup offset y"), default=20,
+ help_text=_("Common value is icon height"))
- def __unicode__(self):
+ def __str__(self):
return self.name
class Meta:
- verbose_name = _(u"Icon")
+ verbose_name = _("Icon")
class SubCategory(models.Model):
'''Sub-category
'''
- category = models.ForeignKey(Category, verbose_name=_(u"Category"),
+ category = models.ForeignKey(Category, verbose_name=_("Category"),
related_name='subcategories')
- name = models.CharField(_(u"Name"), max_length=150)
- available = models.BooleanField(_(u"Available"), default=True)
- submission = models.BooleanField(_(u"Available for submission"),
+ name = models.CharField(_("Name"), max_length=150)
+ available = models.BooleanField(_("Available"), default=True)
+ submission = models.BooleanField(_("Available for submission"),
default=True)
- TYPE = (('M', _(u'Marker')),
- ('R', _(u'Route')),
- ('P', _(u'Polygon')),
- ('B', _(u'Both')),)
- item_type = models.CharField(_(u"Item type"), max_length=1, choices=TYPE)
- dated = models.BooleanField(_(u"Is dated"), default=False)
+ TYPE = (('M', _('Marker')),
+ ('R', _('Route')),
+ ('P', _('Polygon')),
+ ('B', _('Both')),)
+ item_type = models.CharField(_("Item type"), max_length=1, choices=TYPE)
+ dated = models.BooleanField(_("Is dated"), default=False)
description = models.TextField(blank=True, null=True)
- icon = models.ForeignKey(Icon, verbose_name=_(u"Icon"))
+ icon = models.ForeignKey(Icon, verbose_name=_("Icon"))
hover_icon = models.ForeignKey(
- Icon, verbose_name=_(u"Hover icon"), blank=True, null=True,
+ Icon, verbose_name=_("Hover icon"), blank=True, null=True,
related_name='subcat_hovered')
- color_theme = models.ForeignKey(ColorTheme, verbose_name=_(u"Color theme"),
+ color_theme = models.ForeignKey(ColorTheme, verbose_name=_("Color theme"),
blank=True, null=True,
related_name='subcategories')
- as_layer = models.BooleanField(_(u"Displayed in the layer menu"),
+ as_layer = models.BooleanField(_("Displayed in the layer menu"),
default=False)
- weight_formula = models.TextField(_(u"Weight formula"), default="",
+ weight_formula = models.TextField(_("Weight formula"), default="",
blank=True, null=True)
- routing_warn = models.BooleanField(_(u"Routing warn"), default=False)
- order = models.IntegerField(_(u"Order"), default=1000)
- keywords = models.TextField(_(u"Keywords"), max_length=200,
+ routing_warn = models.BooleanField(_("Routing warn"), default=False)
+ order = models.IntegerField(_("Order"), default=1000)
+ keywords = models.TextField(_("Keywords"), max_length=200,
blank=True, null=True)
min_zoom = models.IntegerField(
- _(u"Minimum zoom for loading details"), blank=True, null=True,
- help_text=_(u"Optimization when too many data have to be displayed. "
- u"Currently available only for route and polygon."))
+ _("Minimum zoom for loading details"), blank=True, null=True,
+ help_text=_("Optimization when too many data have to be displayed. "
+ "Currently available only for route and polygon."))
simplify_tolerance = models.FloatField(
- _(u"Simplify tolerance for lower zoom"), blank=True, null=True,
- help_text=_(u"Only relevant when Minimum zoom is set. Use the "
- u"Douglas-Peucker algorythm to simplify the geometry when "
- u"details is not alvailable. Adjust to your data volume "
- u"and your performance need. 0.0003 is a good starting "
- u"point. Note: typology is not preserved."))
+ _("Simplify tolerance for lower zoom"), blank=True, null=True,
+ help_text=_("Only relevant when Minimum zoom is set. Use the "
+ "Douglas-Peucker algorythm to simplify the geometry when "
+ "details is not alvailable. Adjust to your data volume "
+ "and your performance need. 0.0003 is a good starting "
+ "point. Note: typology is not preserved."))
class Meta:
ordering = ["category", "order"]
- verbose_name = _(u"Sub-category")
- verbose_name_plural = _(u"Sub-categories")
+ verbose_name = _("Sub-category")
+ verbose_name_plural = _("Sub-categories")
- def __unicode__(self):
- return u"%s / %s" % (self.category.name, self.name)
+ def __str__(self):
+ return "%s / %s" % (self.category.name, self.name)
@classmethod
def getAvailable(cls, item_types=None, area_name=None, public=False,
@@ -351,7 +352,7 @@ class SubCategory(models.Model):
cats = []
for cat, subcats in cls.getAvailable(item_types=item_types,
area_name=area_name):
- cats.append((unicode(cat),
+ cats.append((str(cat),
[(subcat.pk, subcat.name) for subcat in subcats]))
return cats
@@ -402,19 +403,19 @@ class SubCategoryUserLimit(models.Model):
SubCategory, related_name='limited_for_user')
user = models.ForeignKey(User, related_name='subcategory_limit_to')
- def __unicode__(self):
- return u"{} / {}".format(self.user, self.subcategory)
+ def __str__(self):
+ return "{} / {}".format(self.user, self.subcategory)
class Meta:
- verbose_name = _(u"Sub-category limit for user")
- verbose_name_plural = _(u"Sub-category limits for users")
+ verbose_name = _("Sub-category limit for user")
+ verbose_name_plural = _("Sub-category limits for users")
-STATUS = (('S', _(u'Submited')),
- ('A', _(u'Available')),
- ('M', _(u'Modified')),
- ('D', _(u'Disabled')),
- ('I', _(u'Imported')))
+STATUS = (('S', _('Submited')),
+ ('A', _('Available')),
+ ('M', _('Modified')),
+ ('D', _('Disabled')),
+ ('I', _('Imported')))
STATUS_DCT = dict(STATUS)
IMPORTERS = {'KML': KMLManager,
@@ -446,60 +447,60 @@ class Importer(models.Model):
'''
Data importer for a specific subcategory
'''
- importer_type = models.CharField(_(u"Importer type"), max_length=4,
+ importer_type = models.CharField(_("Importer type"), max_length=4,
choices=IMPORTER_CHOICES)
- filtr = models.TextField(_(u"Filter"), blank=True, null=True)
- source = models.CharField(_(u"Web address"), max_length=200,
+ filtr = models.TextField(_("Filter"), blank=True, null=True)
+ source = models.CharField(_("Web address"), max_length=200,
blank=True, null=True,
- help_text=_(u"Don't forget the trailing slash"))
+ help_text=_("Don't forget the trailing slash"))
source_file = models.FileField(
- _(u"Source file"), upload_to='import_files', blank=True, null=True)
+ _("Source file"), upload_to='import_files', blank=True, null=True)
source_file_alt = models.FileField(
- _(u"Alt source file"), upload_to='import_files', blank=True, null=True)
- default_name = models.CharField(_(u"Name by default"), max_length=200,
+ _("Alt source file"), upload_to='import_files', blank=True, null=True)
+ default_name = models.CharField(_("Name by default"), max_length=200,
blank=True, null=True)
- srid = models.IntegerField(_(u"SRID"), blank=True, null=True)
- zipped = models.BooleanField(_(u"Zipped file"), default=False)
- overwrite = models.BooleanField(_(u"Overwrite existing data"),
+ srid = models.IntegerField(_("SRID"), blank=True, null=True)
+ zipped = models.BooleanField(_("Zipped file"), default=False)
+ overwrite = models.BooleanField(_("Overwrite existing data"),
default=False)
- get_description = models.BooleanField(_(u"Get description from source"),
+ get_description = models.BooleanField(_("Get description from source"),
default=False)
- default_description = models.TextField(_(u"Default description"),
+ default_description = models.TextField(_("Default description"),
blank=True, null=True)
- origin = models.CharField(_(u"Origin"), max_length=1000,
+ origin = models.CharField(_("Origin"), max_length=1000,
blank=True, null=True)
- license = models.CharField(_(u"License"), max_length=1000,
+ license = models.CharField(_("License"), max_length=1000,
blank=True, null=True)
categories = SelectMultipleField(
- SubCategory, blank=True, null=True,
- verbose_name=_(u"Associated subcategories"))
- state = models.TextField(_(u"State"), blank=True, null=True)
- automatic_update = models.BooleanField(_(u"Automatically updated"),
+ SubCategory, blank=True,
+ verbose_name=_("Associated subcategories"))
+ state = models.TextField(_("State"), blank=True, null=True)
+ automatic_update = models.BooleanField(_("Automatically updated"),
default=False)
- default_status = models.CharField(_(u"Default status"), max_length=1,
+ default_status = models.CharField(_("Default status"), max_length=1,
choices=STATUS, default='I')
default_localisation = PointField(
- _(u"Default localisation"),
+ _("Default localisation"),
srid=settings.CHIMERE_EPSG_DISPLAY_PROJECTION, blank=True, null=True,
widget=HiddenPointChooserWidget)
class Meta:
- verbose_name = _(u"Importer")
+ verbose_name = _("Importer")
- def __unicode__(self):
+ def __str__(self):
vals = [IMPORTER_CHOICES_DICT[self.importer_type],
self.source, self.source_file.name,
- u", ".join([unicode(cat) for cat in self.categories.all()]),
+ ", ".join([str(cat) for cat in self.categories.all()]),
self.default_name]
- return u' %d: %s' % (self.pk, u" - ".join([unicode(v)
- for v in vals if v]))
+ return ' %d: %s' % (self.pk, " - ".join([str(v)
+ for v in vals if v]))
@property
def manager(self):
return IMPORTERS[self.importer_type](self)
def display_categories(self):
- return u"\n".join([cat.name for cat in self.categories.all()])
+ return "\n".join([cat.name for cat in self.categories.all()])
def get_key_category_dict(self):
dct = {}
@@ -519,65 +520,65 @@ class ImporterKeyCategories(models.Model):
"""
Association between key and categories
"""
- importer = models.ForeignKey(Importer, verbose_name=_(u"Importer"),
+ importer = models.ForeignKey(Importer, verbose_name=_("Importer"),
related_name='key_categories')
- category = models.ForeignKey(SubCategory, verbose_name=_(u"Category"))
- key = models.CharField(_(u"Import key"), max_length=200)
+ category = models.ForeignKey(SubCategory, verbose_name=_("Category"))
+ key = models.CharField(_("Import key"), max_length=200)
class Meta:
- verbose_name = _(u"Importer - Key categories")
+ verbose_name = _("Importer - Key categories")
class GeographicItem(models.Model):
categories = SelectMultipleField(SubCategory)
- name = models.TextField(_(u"Name"))
+ name = models.TextField(_("Name"))
submiter_session_key = models.CharField(
- _(u"Submitter session key"), blank=True, null=True, max_length=40)
- submiter_name = models.CharField(_(u"Submitter name or nickname"),
+ _("Submitter session key"), blank=True, null=True, max_length=40)
+ submiter_name = models.CharField(_("Submitter name or nickname"),
blank=True, null=True, max_length=40)
- submiter_email = models.EmailField(_(u"Submitter email"), blank=True,
+ submiter_email = models.EmailField(_("Submitter email"), blank=True,
null=True)
- submiter_comment = models.TextField(_(u"Submitter comment"),
+ submiter_comment = models.TextField(_("Submitter comment"),
max_length=200, blank=True, null=True)
- status = models.CharField(_(u"Status"), max_length=1, choices=STATUS)
- keywords = models.TextField(_(u"Keywords"), max_length=200, blank=True,
+ status = models.CharField(_("Status"), max_length=1, choices=STATUS)
+ keywords = models.TextField(_("Keywords"), max_length=200, blank=True,
null=True)
- import_key = models.CharField(_(u"Import key"), max_length=200,
+ import_key = models.CharField(_("Import key"), max_length=200,
blank=True, null=True)
- import_version = models.IntegerField(_(u"Import version"),
+ import_version = models.IntegerField(_("Import version"),
blank=True, null=True)
- import_source = models.CharField(_(u"Source"), max_length=200,
+ import_source = models.CharField(_("Source"), max_length=200,
blank=True, null=True)
modified_since_import = models.BooleanField(
- _(u"Modified since last import"), default=True)
- not_for_osm = models.BooleanField(_(u"Not to be exported to OSM"),
+ _("Modified since last import"), default=True)
+ not_for_osm = models.BooleanField(_("Not to be exported to OSM"),
default=False)
- origin = models.CharField(_(u"Origin"), max_length=1000,
+ origin = models.CharField(_("Origin"), max_length=1000,
blank=True, null=True)
- license = models.CharField(_(u"License"), max_length=1000,
+ license = models.CharField(_("License"), max_length=1000,
blank=True, null=True)
start_date = models.DateField(
- _(u"Start date"), blank=True, null=True,
- help_text=_(u"Not mandatory. Set it for dated item such as event. "
- u"Format YYYY-MM-DD"))
+ _("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(
- _(u"End date"), blank=True, null=True,
- help_text=_(u"Not mandatory. Set it only if you have a multi-day "
- u"event. Format YYYY-MM-DD"))
+ _("End date"), blank=True, null=True,
+ help_text=_("Not mandatory. Set it only if you have a multi-day "
+ "event. Format YYYY-MM-DD"))
weight = models.FloatField(
- _(u"Weight"), blank=True, null=True,
+ _("Weight"), blank=True, null=True,
help_text=_(
- u"Weight are used for heatmap and clustering. A formula must "
- u"defined in the associated category."))
+ "Weight are used for heatmap and clustering. A formula must "
+ "defined in the associated category."))
normalised_weight = models.FloatField(
- _(u"Normalised weight"), blank=True, null=True,
- help_text=_(u"The weight normalised to be between 0 and 1. "
- u"Automatically recalculated."))
+ _("Normalised weight"), blank=True, null=True,
+ help_text=_("The weight normalised to be between 0 and 1. "
+ "Automatically recalculated."))
class Meta:
abstract = True
- def __unicode__(self):
+ def __str__(self):
return self.name
def __init__(self, *args, **kwargs):
@@ -637,7 +638,7 @@ class GeographicItem(models.Model):
return properties
def setProperty(self, pm, value):
- u"""
+ """
Set a property
"""
if not hasattr(pm, 'pk'):
@@ -678,9 +679,9 @@ class GeographicItem(models.Model):
Save properties
"""
for propertymodel in PropertyModel.objects.filter(available=True):
- val = u""
- if unicode(propertymodel.id) in values:
- val = values[unicode(propertymodel.id)]
+ val = ""
+ if str(propertymodel.id) in values:
+ val = values[str(propertymodel.id)]
self.setProperty(propertymodel, val)
def get_key(self, key):
@@ -740,7 +741,7 @@ class GeographicItem(models.Model):
dct = {}
# get all property even the one not displayed
for pm in PropertyModel.objects.all():
- dct[pm.slug] = unicode(self.getProperty(pm))
+ dct[pm.slug] = str(self.getProperty(pm))
return dct
def calculate_weight(self, formula):
@@ -811,20 +812,20 @@ class Marker(GeographicItem):
'''Marker for a POI
'''
ref_item = models.ForeignKey(
- "Marker", blank=True, null=True, verbose_name=_(u"Reference marker"),
+ "Marker", blank=True, null=True, verbose_name=_("Reference marker"),
related_name='submited_marker')
- point = PointField(_(u"Localisation"),
+ point = PointField(_("Localisation"),
srid=settings.CHIMERE_EPSG_DISPLAY_PROJECTION)
- available_date = models.DateTimeField(_(u"Available Date"), blank=True,
+ available_date = models.DateTimeField(_("Available Date"), blank=True,
null=True) # used by feeds
- description = models.TextField(_(u"Description"), blank=True, null=True)
- is_front_page = models.NullBooleanField(_(u"Is front page"), blank=True,
+ description = models.TextField(_("Description"), blank=True, null=True)
+ is_front_page = models.NullBooleanField(_("Is front page"), blank=True,
null=True)
objects = models.GeoManager()
class Meta:
ordering = ('status', 'name')
- verbose_name = _(u"Point of interest")
+ verbose_name = _("Point of interest")
@property
def multimedia_items(self):
@@ -885,8 +886,8 @@ class Marker(GeographicItem):
'pk': self.id,
'key': "marker-{}".format(self.id),
'name': self.name,
- 'icon_path': unicode(cat.icon.image),
- 'icon_hover_path': unicode(cat.hover_icon.image)
+ 'icon_path': str(cat.icon.image),
+ 'icon_hover_path': str(cat.hover_icon.image)
if cat.hover_icon else '',
'icon_offset_x': cat.icon.offset_x,
'icon_offset_y': cat.icon.offset_y,
@@ -925,8 +926,8 @@ class Marker(GeographicItem):
except SubCategory.DoesNotExist:
continue
cats[item['categories__pk']] = {
- 'icon_path': unicode(cat.icon.image),
- 'icon_hover_path': unicode(cat.hover_icon.image)
+ 'icon_path': str(cat.icon.image),
+ 'icon_hover_path': str(cat.hover_icon.image)
if cat.hover_icon else '',
'icon_offset_x': cat.icon.offset_x,
'icon_offset_y': cat.icon.offset_y,
@@ -1036,26 +1037,26 @@ class Polygon(GeographicItem):
'''Polygon on the map
'''
ref_item = models.ForeignKey(
- "Polygon", blank=True, null=True, verbose_name=_(u"Reference polygon"),
+ "Polygon", blank=True, null=True, verbose_name=_("Reference polygon"),
related_name='submited_polygon')
polygon = PolygonField(
- _(u"Polygon"), srid=settings.CHIMERE_EPSG_DISPLAY_PROJECTION)
+ _("Polygon"), srid=settings.CHIMERE_EPSG_DISPLAY_PROJECTION)
picture = models.ImageField(
- _(u"Image"), upload_to='upload', blank=True, null=True,
+ _("Image"), upload_to='upload', blank=True, null=True,
height_field='height', width_field='width')
- height = models.IntegerField(_(u"Height"), blank=True, null=True)
- width = models.IntegerField(_(u"Width"), blank=True, null=True)
+ height = models.IntegerField(_("Height"), blank=True, null=True)
+ width = models.IntegerField(_("Width"), blank=True, null=True)
color = models.CharField(
- _(u"Color"), max_length=200, help_text=_(u"HTML code/name"),
+ _("Color"), max_length=200, help_text=_("HTML code/name"),
blank=True, null=True)
inner_color = models.CharField(
- _(u"Inner color"), max_length=200,
- help_text=_(u"HTML code/name"), blank=True, null=True)
+ _("Inner color"), max_length=200,
+ help_text=_("HTML code/name"), blank=True, null=True)
objects = models.GeoManager()
class Meta:
ordering = ('status', 'name')
- verbose_name = _(u"Polygon")
+ verbose_name = _("Polygon")
@property
def geom_attr(self):
@@ -1142,7 +1143,7 @@ class AggregatedPolygon(models.Model):
'''
polygon = models.MultiPolygonField()
subcategory = models.ForeignKey(SubCategory)
- status = models.CharField(_(u"Status"), max_length=1, choices=STATUS)
+ status = models.CharField(_("Status"), max_length=1, choices=STATUS)
class Meta:
managed = False
@@ -1180,28 +1181,28 @@ class AggregatedPolygon(models.Model):
'color': color,
'inner_color': inner_color,
'key': "aggpoly-{}".format(self.pk),
- "pk": self.id, "name": u'Aggregated polygon'}}
+ "pk": self.id, "name": 'Aggregated polygon'}}
return json.dumps(attributes)
class MultimediaType(models.Model):
- MEDIA_TYPES = (('A', _(u"Audio")),
- ('V', _(u"Video")),
- ('I', _(u"Image")),
- ('O', _(u"Other")),)
- media_type = models.CharField(_(u"Media type"), max_length=1,
+ MEDIA_TYPES = (('A', _("Audio")),
+ ('V', _("Video")),
+ ('I', _("Image")),
+ ('O', _("Other")),)
+ media_type = models.CharField(_("Media type"), max_length=1,
choices=MEDIA_TYPES)
- name = models.CharField(_(u"Name"), max_length=150)
- mime_type = models.CharField(_(u"Mime type"), max_length=50, blank=True,
+ name = models.CharField(_("Name"), max_length=150)
+ mime_type = models.CharField(_("Mime type"), max_length=50, blank=True,
null=True)
- iframe = models.BooleanField(_(u"Inside an iframe"), default=False)
- available = models.BooleanField(_(u"Available"), default=True)
+ iframe = models.BooleanField(_("Inside an iframe"), default=False)
+ available = models.BooleanField(_("Available"), default=True)
class Meta:
- verbose_name = _(u"Multimedia type")
- verbose_name_plural = _(u"Multimedia types")
+ verbose_name = _("Multimedia type")
+ verbose_name_plural = _("Multimedia types")
- def __unicode__(self):
+ def __str__(self):
return self.name
@classmethod
@@ -1236,26 +1237,26 @@ IFRAME_LINKS = {
class MultimediaExtension(models.Model):
- name = models.CharField(_(u"Extension name"), max_length=6)
+ name = models.CharField(_("Extension name"), max_length=6)
multimedia_type = models.ForeignKey(
- MultimediaType, verbose_name=_(u"Associated multimedia type"),
+ MultimediaType, verbose_name=_("Associated multimedia type"),
related_name='extensions')
class Meta:
- verbose_name = _(u"Multimedia extension")
- verbose_name_plural = _(u"Multimedia extensions")
+ verbose_name = _("Multimedia extension")
+ verbose_name_plural = _("Multimedia extensions")
- def __unicode__(self):
+ def __str__(self):
return self.name
class MultimediaFile(models.Model):
- name = models.CharField(_(u"Name"), max_length=150)
- url = models.URLField(_(u"Url"), max_length=200)
- order = models.IntegerField(_(u"Order"), default=1)
+ name = models.CharField(_("Name"), max_length=150)
+ url = models.URLField(_("Url"), max_length=200)
+ order = models.IntegerField(_("Order"), default=1)
multimedia_type = models.ForeignKey(MultimediaType, blank=True, null=True)
miniature = models.BooleanField(
- _(u"Display inside the description?"),
+ _("Display inside the description?"),
default=settings.CHIMERE_MINIATURE_BY_DEFAULT)
marker = models.ForeignKey(Marker, related_name='multimedia_files',
blank=True, null=True)
@@ -1265,11 +1266,11 @@ class MultimediaFile(models.Model):
blank=True, null=True)
class Meta:
- verbose_name = _(u"Multimedia file")
- verbose_name_plural = _(u"Multimedia files")
+ verbose_name = _("Multimedia file")
+ verbose_name_plural = _("Multimedia files")
- def __unicode__(self):
- return self.name or u""
+ def __str__(self):
+ return self.name or ""
def multimediafile_post_save(sender, **kwargs):
@@ -1320,22 +1321,22 @@ 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',
+ name = models.CharField(_("Name"), max_length=150)
+ picture = models.ImageField(_("Image"), upload_to='pictures',
height_field='height', width_field='width')
- height = models.IntegerField(_(u"Height"), blank=True, null=True)
- width = models.IntegerField(_(u"Width"), blank=True, null=True)
+ height = models.IntegerField(_("Height"), blank=True, null=True)
+ width = models.IntegerField(_("Width"), blank=True, null=True)
miniature = models.BooleanField(
- _(u"Display inside the description?"),
+ _("Display inside the description?"),
default=settings.CHIMERE_MINIATURE_BY_DEFAULT)
thumbnailfile = models.ImageField(
- _(u"Thumbnail"), upload_to='pictures', blank=True, null=True,
+ _("Thumbnail"), upload_to='pictures', blank=True, null=True,
height_field='thumbnailfile_height', width_field='thumbnailfile_width')
- thumbnailfile_height = models.IntegerField(_(u"Thumbnail height"),
+ thumbnailfile_height = models.IntegerField(_("Thumbnail height"),
blank=True, null=True)
- thumbnailfile_width = models.IntegerField(_(u"Thumbnail width"),
+ thumbnailfile_width = models.IntegerField(_("Thumbnail width"),
blank=True, null=True)
- order = models.IntegerField(_(u"Order"), default=1)
+ order = models.IntegerField(_("Order"), default=1)
marker = models.ForeignKey(Marker, related_name='pictures', blank=True,
null=True)
route = models.ForeignKey('Route', related_name='pictures',
@@ -1343,12 +1344,12 @@ class PictureFile(models.Model):
polygon = models.ForeignKey(Polygon, related_name='pictures', blank=True,
null=True)
- def __unicode__(self):
- return self.name or u""
+ def __str__(self):
+ return self.name or ""
class Meta:
- verbose_name = _(u"Picture file")
- verbose_name_plural = _(u"Picture files")
+ verbose_name = _("Picture file")
+ verbose_name_plural = _("Picture files")
def scale_image(max_x, pair):
@@ -1363,8 +1364,6 @@ IMAGE_EXIF_ORIENTATION_MAP = {
6: 4,
}
-PYEXIV2_OLD_API = not hasattr(pyexiv2, 'ImageMetadata')
-
def picturefile_post_save(sender, **kwargs):
if not kwargs['instance']:
@@ -1374,23 +1373,14 @@ def picturefile_post_save(sender, **kwargs):
if kwargs['created']:
filename = picturefile.picture.path
metadata, orientation = None, None
- if PYEXIV2_OLD_API:
- metadata = pyexiv2.Image(filename)
- metadata.readMetadata()
- orientation = metadata['Exif.Image.Orientation'] \
- if 'Exif.Image.Orientation' in metadata.exifKeys() else None
- else:
- metadata = pyexiv2.ImageMetadata(filename)
- metadata.read()
- orientation = metadata['Exif.Image.Orientation'].value \
- if 'Exif.Image.Orientation' in metadata else None
+ metadata = pyexiv2.ImageMetadata(filename)
+ metadata.read()
+ orientation = metadata['Exif.Image.Orientation'].value \
+ if 'Exif.Image.Orientation' in metadata else None
if orientation and orientation in IMAGE_EXIF_ORIENTATION_MAP \
and orientation > 1:
metadata['Exif.Image.Orientation'] = 1
- if PYEXIV2_OLD_API:
- metadata.writeMetadata()
- else:
- metadata.write()
+ metadata.write()
im = Image.open(filename)
im = im.transpose(IMAGE_EXIF_ORIENTATION_MAP[orientation])
im.save(filename)
@@ -1444,20 +1434,20 @@ post_save.connect(picturefile_post_save, sender=PictureFile)
class RouteFile(models.Model):
- name = models.CharField(_(u"Name"), max_length=150)
- raw_file = models.FileField(_(u"Raw file (gpx or kml)"),
+ name = models.CharField(_("Name"), max_length=150)
+ raw_file = models.FileField(_("Raw file (gpx or kml)"),
upload_to='route_files')
simplified_file = models.FileField(
- _(u"Simplified file"), upload_to='route_files', blank=True, null=True)
- TYPE = (('K', _(u'KML')), ('G', _(u'GPX')))
+ _("Simplified file"), upload_to='route_files', blank=True, null=True)
+ TYPE = (('K', _('KML')), ('G', _('GPX')))
file_type = models.CharField(max_length=1, choices=TYPE)
class Meta:
ordering = ('name',)
- verbose_name = _(u"Route file")
- verbose_name_plural = _(u"Route files")
+ verbose_name = _("Route file")
+ verbose_name_plural = _("Route files")
- def __unicode__(self):
+ def __str__(self):
return self.name
def process(self):
@@ -1476,7 +1466,7 @@ class RouteFile(models.Model):
p = Popen(cli_args, stderr=PIPE)
p.wait()
if p.returncode:
- print p.stderr.read()
+ print(p.stderr.read())
# logger.error(p.stderr.read())
else:
self.simplified_file = File(open(output_name))
@@ -1495,34 +1485,34 @@ class RouteFile(models.Model):
if not pt.tag.endswith('trkpt'):
continue
pts.append((pt.get("lon"), pt.get("lat")))
- wkt_tpl = u'LINESTRING(%s)'
- return wkt_tpl % u','.join([u'%s %s' % (pt[0], pt[1])
- for pt in pts])
+ wkt_tpl = 'LINESTRING(%s)'
+ return wkt_tpl % ','.join(['%s %s' % (pt[0], pt[1])
+ for pt in pts])
class Route(GeographicItem):
'''Route on the map
'''
ref_item = models.ForeignKey(
- "Route", blank=True, null=True, verbose_name=_(u"Reference route"),
+ "Route", blank=True, null=True, verbose_name=_("Reference route"),
related_name='submited_route')
- route = RouteField(_(u"Route"),
+ route = RouteField(_("Route"),
srid=settings.CHIMERE_EPSG_DISPLAY_PROJECTION)
associated_file = models.ForeignKey(RouteFile, blank=True, null=True,
- verbose_name=_(u"Associated file"))
+ verbose_name=_("Associated file"))
picture = models.ImageField(
- _(u"Image"), upload_to='upload', blank=True, null=True,
+ _("Image"), upload_to='upload', blank=True, null=True,
height_field='height', width_field='width')
- height = models.IntegerField(_(u"Height"), blank=True, null=True)
- width = models.IntegerField(_(u"Width"), blank=True, null=True)
+ height = models.IntegerField(_("Height"), blank=True, null=True)
+ width = models.IntegerField(_("Width"), blank=True, null=True)
color = models.CharField(
- _(u"Color"), max_length=200, help_text=_(u"HTML code/name"),
+ _("Color"), max_length=200, help_text=_("HTML code/name"),
blank=True, null=True)
objects = models.GeoManager()
class Meta:
ordering = ('status', 'name')
- verbose_name = _(u"Route")
+ verbose_name = _("Route")
@property
def geom_attr(self):
@@ -1632,7 +1622,7 @@ class AggregatedRoute(models.Model):
'''
route = models.MultiLineStringField()
subcategory = models.ForeignKey(SubCategory)
- status = models.CharField(_(u"Status"), max_length=1, choices=STATUS)
+ status = models.CharField(_("Status"), max_length=1, choices=STATUS)
class Meta:
managed = False
@@ -1651,7 +1641,7 @@ class AggregatedRoute(models.Model):
'color': color, 'geometry': geom,
'type': "Feature", "properties": {
'key': "aggroute-{}".format(self.pk),
- "pk": self.id, "name": u'Aggregated route'}}
+ "pk": self.id, "name": 'Aggregated route'}}
return json.dumps(attributes)
@@ -1667,14 +1657,17 @@ class SimpleArea:
"""
Rectangular area of a map (not in the database)
"""
- def __init__(self, area):
+ def __init__(self, area=None):
"""
- Defining upper left corner ans lower right corner from a tuple
+ Defining upper left corner and lower right corner from a tuple
"""
+ if not area:
+ return super(SimpleArea, self).__init__()
assert len(area) == 4
x1, y1, x2, y2 = area
self.upper_left_corner = SimplePoint(x1, y1)
self.lower_right_corner = SimplePoint(x2, y2)
+ return super(SimpleArea, self).__init__()
def isIn(self, area):
"""
@@ -1696,7 +1689,7 @@ class SimpleArea:
subcategory_pks = []
for cat, subcats in SubCategory.getAvailable(area_name=area_name):
for subcat in subcats:
- subcategory_pks.append(unicode(subcat.pk))
+ subcategory_pks.append(str(subcat.pk))
if filter_available:
wheres += ['subcat.available = TRUE', 'cat.available = TRUE']
wheres += ['subcat.id in (%s)' % ",".join(subcategory_pks)]
@@ -1707,8 +1700,8 @@ class SimpleArea:
equal_status = "='%s'" % status[0]
elif status:
equal_status = " in ('%s')" % "','".join(status)
- area = u"ST_GeometryFromText('POLYGON((%f %f,%f %f,%f %f,%f %f, %f %f"\
- u"))', %d)" % (
+ area = "ST_GeometryFromText('POLYGON((%f %f,%f %f,%f %f,%f %f, %f %f"\
+ "))', %d)" % (
self.upper_left_corner.x, self.upper_left_corner.y,
self.lower_right_corner.x, self.upper_left_corner.y,
self.lower_right_corner.x, self.lower_right_corner.y,
@@ -1767,20 +1760,20 @@ class SimpleArea:
return subcats
def getExtent(self):
- return (unicode(self.upper_left_corner.x),
- unicode(self.upper_left_corner.y),
- unicode(self.lower_right_corner.x),
- unicode(self.lower_right_corner.y))
+ return (str(self.upper_left_corner.x),
+ str(self.upper_left_corner.y),
+ str(self.lower_right_corner.x),
+ str(self.lower_right_corner.y))
class Layer(models.Model):
- name = models.CharField(_(u"Name"), max_length=150)
- layer_code = models.TextField(_(u"Layer code"))
+ name = models.CharField(_("Name"), max_length=150)
+ layer_code = models.TextField(_("Layer code"))
extra_js_code = models.TextField(
- _(u"Extra JS code"), blank=True, null=True, default='',
- help_text=_(u"This code is loaded before the layer code."))
+ _("Extra JS code"), blank=True, null=True, default='',
+ help_text=_("This code is loaded before the layer code."))
- def __unicode__(self):
+ def __str__(self):
return self.name
class Meta:
@@ -1790,57 +1783,57 @@ class Layer(models.Model):
class Area(models.Model, SimpleArea):
"""Rectangular area of the map
"""
- name = models.CharField(_(u"Name"), max_length=150)
- urn = models.SlugField(_(u"Area urn"), max_length=50, blank=True,
+ name = models.CharField(_("Name"), max_length=150)
+ urn = models.SlugField(_("Area urn"), max_length=50, blank=True,
unique=True)
- welcome_message = models.TextField(_(u"Welcome message"), blank=True,
+ welcome_message = models.TextField(_("Welcome message"), blank=True,
null=True)
- order = models.IntegerField(_(u"Order"), unique=True)
- available = models.BooleanField(_(u"Available"))
+ order = models.IntegerField(_("Order"), unique=True)
+ available = models.BooleanField(_("Available"))
upper_left_corner = models.PointField(
- _(u"Upper left corner"), default='POINT(0 0)',
+ _("Upper left corner"), default='POINT(0 0)',
srid=settings.CHIMERE_EPSG_DISPLAY_PROJECTION)
lower_right_corner = models.PointField(
- _(u"Lower right corner"), default='POINT(0 0)',
+ _("Lower right corner"), default='POINT(0 0)',
srid=settings.CHIMERE_EPSG_DISPLAY_PROJECTION)
default = models.NullBooleanField(
- _(u"Default area"), help_text=_(u"Only one area is set by default"))
+ _("Default area"), help_text=_("Only one area is set by default"))
layers = SelectMultipleField(Layer, related_name='areas',
through='AreaLayers', blank=True)
default_subcategories = SelectMultipleField(
SubCategory, blank=True,
- verbose_name=_(u"Sub-categories checked by default"))
+ verbose_name=_("Sub-categories checked by default"))
dynamic_categories = models.NullBooleanField(
- _(u"Sub-categories dynamicaly displayed"),
- help_text=_(u"If checked, categories are only displayed in the menu "
- u"if they are available on the current extent."))
+ _("Sub-categories dynamicaly displayed"),
+ help_text=_("If checked, categories are only displayed in the menu "
+ "if they are available on the current extent."))
subcategories = SelectMultipleField(
SubCategory, related_name='areas',
blank=True, db_table='chimere_subcategory_areas',
- verbose_name=_(u"Restricted to theses sub-categories"),
- help_text=_(u"If no sub-category is set all sub-categories are "
- u"available"))
+ verbose_name=_("Restricted to theses sub-categories"),
+ help_text=_("If no sub-category is set all sub-categories are "
+ "available"))
display_category_menu = models.BooleanField(
- _(u"Display category menu"), default=True,
- help_text=_(u"If set to False, category menu will be hide and all "
- u"categories will be always displayed."))
- external_css = models.URLField(_(u"Link to an external CSS"), blank=True,
+ _("Display category menu"), default=True,
+ help_text=_("If set to False, category menu will be hide and all "
+ "categories will be always displayed."))
+ external_css = models.URLField(_("Link to an external CSS"), blank=True,
null=True)
- restrict_to_extent = models.BooleanField(_(u"Restrict to the area extent"),
+ restrict_to_extent = models.BooleanField(_("Restrict to the area extent"),
default=False)
- allow_point_edition = models.BooleanField(_(u"Allow point edition"),
+ allow_point_edition = models.BooleanField(_("Allow point edition"),
default=True)
- allow_route_edition = models.BooleanField(_(u"Allow route edition"),
+ allow_route_edition = models.BooleanField(_("Allow route edition"),
default=True)
- allow_polygon_edition = models.BooleanField(_(u"Allow polygon edition"),
+ allow_polygon_edition = models.BooleanField(_("Allow polygon edition"),
default=True)
extra_map_def = models.TextField(
- _(u"Extra map definition"), blank=True, null=True,
- help_text=_(u"Extra javascript script loaded for this area. "
- u"Carreful! To prevent breaking the map must be valid."))
+ _("Extra map definition"), blank=True, null=True,
+ help_text=_("Extra javascript script loaded for this area. "
+ "Carreful! To prevent breaking the map must be valid."))
objects = models.GeoManager()
- def __unicode__(self):
+ def __str__(self):
return self.name
class Meta:
@@ -1984,8 +1977,8 @@ def get_users_by_area(area):
class AreaLayers(models.Model):
area = models.ForeignKey(Area)
layer = models.ForeignKey(Layer)
- order = models.IntegerField(_(u"Order"))
- default = models.NullBooleanField(_(u"Default layer"))
+ order = models.IntegerField(_("Order"))
+ default = models.NullBooleanField(_("Default layer"))
class Meta:
ordering = ('order',)
@@ -1996,21 +1989,20 @@ class AreaLayers(models.Model):
class PropertyModel(models.Model):
'''Model for a property
'''
- name = models.CharField(_(u"Name"), max_length=150)
- slug = models.SlugField(_(u"Slug"), blank=True, null=True)
- order = models.IntegerField(_(u"Order"))
- available = models.BooleanField(_(u"Available"))
- mandatory = models.BooleanField(_(u"Mandatory"))
+ name = models.CharField(_("Name"), max_length=150)
+ slug = models.SlugField(_("Slug"), blank=True, null=True)
+ order = models.IntegerField(_("Order"))
+ available = models.BooleanField(_("Available"))
+ mandatory = models.BooleanField(_("Mandatory"))
subcategories = SelectMultipleField(
SubCategory, related_name='properties',
- blank=True, verbose_name=_(u"Restricted to theses sub-categories"),
- help_text=_(u"If no sub-category is set all the property applies to "
- u"all sub-categories"))
+ blank=True, verbose_name=_("Restricted to theses sub-categories"),
+ help_text=_("If no sub-category is set all the property applies to "
+ "all sub-categories"))
areas = SelectMultipleField(
- 'Area', verbose_name=_(u"Restrict to theses areas"), blank=True,
- null=True,
- help_text=_(u"If no area is set the property apply to "
- u"all areas"))
+ 'Area', verbose_name=_("Restrict to theses areas"), blank=True,
+ help_text=_("If no area is set the property apply to "
+ "all areas"))
TYPE = (('T', _('Text')),
('L', _('Long text')),
('P', _('Password')),
@@ -2027,13 +2019,13 @@ class PropertyModel(models.Model):
'A': JQueryAutoComplete,
'B': forms.CheckboxInput,
}
- type = models.CharField(_(u"Type"), max_length=1, choices=TYPE)
+ type = models.CharField(_("Type"), max_length=1, choices=TYPE)
class Meta:
ordering = ('order',)
verbose_name = _("Property model")
- def __unicode__(self):
+ def __str__(self):
return self.name
def getAttrName(self):
@@ -2064,41 +2056,41 @@ 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)
+ verbose_name=_("Property model"))
+ value = models.CharField(_("Value"), max_length=150)
+ available = models.BooleanField(_("Available"), default=True)
class Meta:
- verbose_name = _(u"Model property choice")
+ verbose_name = _("Model property choice")
- def __unicode__(self):
- return unicode(self.value)
+ def __str__(self):
+ return str(self.value)
class Property(models.Model):
'''Property for a POI
'''
marker = models.ForeignKey(
- Marker, verbose_name=_(u"Point of interest"), blank=True, null=True)
+ Marker, verbose_name=_("Point of interest"), blank=True, null=True)
polygon = models.ForeignKey(
- Polygon, verbose_name=_(u"Polygon"), blank=True, null=True)
+ Polygon, verbose_name=_("Polygon"), blank=True, null=True)
propertymodel = models.ForeignKey(PropertyModel,
- verbose_name=_(u"Property model"))
- value = models.TextField(_(u"Value"))
+ verbose_name=_("Property model"))
+ value = models.TextField(_("Value"))
- def __unicode__(self):
+ def __str__(self):
if self.propertymodel.type == 'C':
if not self.value:
return ''
try:
- return unicode(PropertyModelChoice.objects.get(
+ return str(PropertyModelChoice.objects.get(
pk=self.value).value)
except (self.DoesNotExist, ValueError):
return ""
- return unicode(self.value)
+ return str(self.value)
class Meta:
- verbose_name = _(u"Property")
+ verbose_name = _("Property")
@property
def python_value(self):