diff options
author | Étienne Loks <etienne.loks@iggdrasil.net> | 2016-09-22 23:06:12 +0200 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2016-09-22 23:06:12 +0200 |
commit | 8a8f25e156367807d174bbe858e8f66416306001 (patch) | |
tree | 001e62218954de6391f83e2436de816cc6c7a48a /chimere/models.py | |
parent | 792fed91a5c0c218ede19b01d5d818730193a6b2 (diff) | |
download | Chimère-8a8f25e156367807d174bbe858e8f66416306001.tar.bz2 Chimère-8a8f25e156367807d174bbe858e8f66416306001.zip |
Going to python3 and Django 1.8!
Diffstat (limited to 'chimere/models.py')
-rw-r--r-- | chimere/models.py | 644 |
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): |