diff options
author | Jessica Tallon <jessica@megworld.co.uk> | 2014-10-09 19:20:13 +0100 |
---|---|---|
committer | Jessica Tallon <jessica@megworld.co.uk> | 2014-10-09 19:20:13 +0100 |
commit | ed48454558a91961b6e03fc51b8a4bf785d48d1e (patch) | |
tree | 792294c842fe5643a2d8f66be366805f621d4ece /mediagoblin/db/models.py | |
parent | 9a1fc423ac298c2ddf078d91ea1302c135285781 (diff) | |
parent | c0434db46910e891313495b5ae94cbbe1dd08058 (diff) | |
download | mediagoblin-ed48454558a91961b6e03fc51b8a4bf785d48d1e.tar.lz mediagoblin-ed48454558a91961b6e03fc51b8a4bf785d48d1e.tar.xz mediagoblin-ed48454558a91961b6e03fc51b8a4bf785d48d1e.zip |
Merge branch 'location'
Add Location model which holds textual, geolocation coordiantes
or postal addresses. This migrates data off Image model metadata
onto the general Location model. It also adds the ability for location
to be set on MediaEntry, User, MediaComment and Collection models.
The geolocation plugin has been updated so that the location can be displayed
in more general places rather than explicitely on the MediaEntry view.
If GPS coordiantes are set for the User the profile page will also have the
OSM provided by the geolocation plugin.
Diffstat (limited to 'mediagoblin/db/models.py')
-rw-r--r-- | mediagoblin/db/models.py | 116 |
1 files changed, 112 insertions, 4 deletions
diff --git a/mediagoblin/db/models.py b/mediagoblin/db/models.py index 0069c85a..b1bdba88 100644 --- a/mediagoblin/db/models.py +++ b/mediagoblin/db/models.py @@ -45,6 +45,79 @@ import six _log = logging.getLogger(__name__) +class Location(Base): + """ Represents a physical location """ + __tablename__ = "core__locations" + + id = Column(Integer, primary_key=True) + name = Column(Unicode) + + # GPS coordinates + position = Column(MutationDict.as_mutable(JSONEncoded)) + address = Column(MutationDict.as_mutable(JSONEncoded)) + + @classmethod + def create(cls, data, obj): + location = cls() + location.unserialize(data) + location.save() + obj.location = location.id + return location + + def serialize(self, request): + location = {"objectType": "place"} + + if self.name is not None: + location["name"] = self.name + + if self.position: + location["position"] = self.position + + if self.address: + location["address"] = self.address + + return location + + def unserialize(self, data): + if "name" in data: + self.name = data["name"] + + self.position = {} + self.address = {} + + # nicer way to do this? + if "position" in data: + # TODO: deal with ISO 9709 formatted string as position + if "altitude" in data["position"]: + self.position["altitude"] = data["position"]["altitude"] + + if "direction" in data["position"]: + self.position["direction"] = data["position"]["direction"] + + if "longitude" in data["position"]: + self.position["longitude"] = data["position"]["longitude"] + + if "latitude" in data["position"]: + self.position["latitude"] = data["position"]["latitude"] + + if "address" in data: + if "formatted" in data["address"]: + self.address["formatted"] = data["address"]["formatted"] + + if "streetAddress" in data["address"]: + self.address["streetAddress"] = data["address"]["streetAddress"] + + if "locality" in data["address"]: + self.address["locality"] = data["address"]["locality"] + + if "region" in data["address"]: + self.address["region"] = data["address"]["region"] + + if "postalCode" in data["address"]: + self.address["postalCode"] = data["addresss"]["postalCode"] + + if "country" in data["address"]: + self.address["country"] = data["address"]["country"] class User(Base, UserMixin): """ @@ -71,6 +144,8 @@ class User(Base, UserMixin): bio = Column(UnicodeText) # ?? uploaded = Column(Integer, default=0) upload_limit = Column(Integer) + location = Column(Integer, ForeignKey("core__locations.id")) + get_location = relationship("Location", lazy="joined") activity = Column(Integer, ForeignKey("core__activity_intermediators.id")) @@ -175,9 +250,18 @@ class User(Base, UserMixin): user.update({"summary": self.bio}) if self.url: user.update({"url": self.url}) + if self.location: + user.update({"location": self.get_location.seralize(request)}) return user + def unserialize(self, data): + if "summary" in data: + self.bio = data["summary"] + + if "location" in data: + Location.create(data, self) + class Client(Base): """ Model representing a client - Used for API Auth @@ -265,6 +349,8 @@ class MediaEntry(Base, MediaEntryMixin): # or use sqlalchemy.types.Enum? license = Column(Unicode) file_size = Column(Integer, default=0) + location = Column(Integer, ForeignKey("core__locations.id")) + get_location = relationship("Location", lazy="joined") fail_error = Column(Unicode) fail_metadata = Column(JSONEncoded) @@ -476,6 +562,9 @@ class MediaEntry(Base, MediaEntryMixin): if self.license: context["license"] = self.license + if self.location: + context["location"] = self.get_location.serialize(request) + if show_comments: comments = [ comment.serialize(request) for comment in self.get_comments()] @@ -504,6 +593,9 @@ class MediaEntry(Base, MediaEntryMixin): if "license" in data: self.license = data["license"] + if "location" in data: + Licence.create(data["location"], self) + return True class FileKeynames(Base): @@ -629,6 +721,8 @@ class MediaComment(Base, MediaCommentMixin): author = Column(Integer, ForeignKey(User.id), nullable=False) created = Column(DateTime, nullable=False, default=datetime.datetime.now) content = Column(UnicodeText, nullable=False) + location = Column(Integer, ForeignKey("core__locations.id")) + get_location = relationship("Location", lazy="joined") # Cascade: Comments are owned by their creator. So do the full thing. # lazy=dynamic: People might post a *lot* of comments, @@ -666,6 +760,9 @@ class MediaComment(Base, MediaCommentMixin): "author": author.serialize(request) } + if self.location: + context["location"] = self.get_location.seralize(request) + return context def unserialize(self, data): @@ -692,6 +789,10 @@ class MediaComment(Base, MediaCommentMixin): self.media_entry = media.id self.content = data["content"] + + if "location" in data: + Location.create(data["location"], self) + return True @@ -710,6 +811,9 @@ class Collection(Base, CollectionMixin): index=True) description = Column(UnicodeText) creator = Column(Integer, ForeignKey(User.id), nullable=False) + location = Column(Integer, ForeignKey("core__locations.id")) + get_location = relationship("Location", lazy="joined") + # TODO: No of items in Collection. Badly named, can we migrate to num_items? items = Column(Integer, default=0) @@ -889,9 +993,8 @@ class ProcessingNotification(Notification): 'polymorphic_identity': 'processing_notification' } -with_polymorphic( - Notification, - [ProcessingNotification, CommentNotification]) +# the with_polymorphic call has been moved to the bottom above MODELS +# this is because it causes conflicts with relationship calls. class ReportBase(Base): """ @@ -1243,6 +1346,10 @@ class Activity(Base, ActivityMixin): self.updated = datetime.datetime.now() super(Activity, self).save(*args, **kwargs) +with_polymorphic( + Notification, + [ProcessingNotification, CommentNotification]) + MODELS = [ User, MediaEntry, Tag, MediaTag, MediaComment, Collection, CollectionItem, MediaFile, FileKeynames, MediaAttachmentFile, ProcessingMetaData, @@ -1250,7 +1357,8 @@ MODELS = [ CommentSubscription, ReportBase, CommentReport, MediaReport, UserBan, Privilege, PrivilegeUserAssociation, RequestToken, AccessToken, NonceTimestamp, - Activity, ActivityIntermediator, Generator] + Activity, ActivityIntermediator, Generator, + Location] """ Foundations are the default rows that are created immediately after the tables |