-from sqlalchemy import Column, ForeignKey
-from sqlalchemy.orm import relation
-from sqlalchemy.types import Integer, Unicode
+#
+# floof/floof/model/users.py
+#
+# Copyright (c) 2009 Scribblr
+#
-from floof.model import meta
+import re
-__all__ = ['User', 'IdentityURL']
+from elixir import *
-class User(meta.TableBase):
- __tablename__ = 'users'
- id = Column(Integer, primary_key=True)
- name = Column(Unicode(length=20), nullable=False)
+from search import GalleryWidget
-class IdentityURL(meta.TableBase):
- __tablename__ = 'identity_urls'
- url = Column(Unicode(length=255), primary_key=True)
- user_id = Column(Integer, ForeignKey('users.id'))
+class User(Entity):
+ name = Field(Unicode(20), unique=True, required=True)
+ display_name = Field(Unicode(20), required=True)
+ uploads = OneToMany('Art')
+ has_many('identity_urls', of_kind='IdentityURL')
+ searches = OneToMany('SavedSearch')
+ # galleries = OneToMany('GalleryWidget')
+ pages = OneToMany('UserPage', inverse="owner")
+ primary_page = OneToOne('UserPage', inverse="owner")
+ relationships = OneToMany('UserRelationship', inverse='user')
+ target_of_relationships = OneToMany('UserRelationship', inverse='target_user')
+
+ @classmethod
+ def is_valid_name(cls, name):
+ """Returns True iff the name is a valid username.
+
+ Only lowercase letters, numbers, and hyphens are allowed.
+
+ Names must also be at least one character long, but no more than 20,
+ and cannot start or end with a hyphen.
+ """
+ return re.match('^[-a-z0-9]{1,20}$', name) \
+ and name[0] != '-' and name[-1] != '-'
+
+
+ def __unicode__(self):
+ return self.name
+
+ def __str__(self):
+ return self.name
+
+ def __init__(self, **kwargs):
+ super(User, self).__init__(**kwargs)
+
+
+
+ # TODO: have this clone a standard starter page
+ self.primary_page = UserPage(owner=self, title="default", visible=True)
+ prepositions = ['by','for','of']
+ for preposition in prepositions:
+ GalleryWidget(page=self.primary_page, string=preposition+":me", owner=self)
+
+ #UserPage.clone_primary_template(self)
+
+
+class IdentityURL(Entity):
+ url = Field(Unicode(255), required=True)
+ user = ManyToOne('User', required=True)
+
+
+from copy import copy
+class UserPage(Entity):
+ default_name = "default"
+
+ ### This was a bit more complex than I thought it would be...
+ ### Sure it probably works ok, but I'd rather duct-tape it for now (above)
+ # @classmethod
+ # def get_primary_template(cls):
+ # return cls.get_by(owner=None, title=cls.default_name)
+ #
+ # @classmethod
+ # def make_primary_template(cls):
+ # if not cls.get_primary_template():
+ # page = cls(owner=None, title=cls.default_name, visible=True)
+ # prepositions = ['by','for','of']
+ # for preposition in prepositions:
+ # GalleryWidget(page=page, string=preposition+":me")
+ #
+ # @classmethod
+ # def clone_primary_template(cls, user):
+ # template = cls.get_primary_template()
+ # new = cls(owner=user, title=template.title)
+ # for gallery in template.galleries:
+ # new.galleries.append(GalleryWidget(user=user, string=gallery.string))
+ #
+ #
+ # session.add(template)
+ # template.user = user
+ # template.id = None
+ # return template
+
+ """A user can have multiple pages, though by default they only have one visible.
+ This is so that they can keep some nice themed pages lying around for special occasions.
+ Page templates that provide familiar interfaces will also be UserPage records. Users will
+ see a panel full of them, and they can choose to clone those template pages to their own page list.
+ If more than one is set to visible, there would be tabs. The primary page is indicated in the user model.
+ """
+
+ owner = ManyToOne('User', inverse="pages")
+ title = Field(String)
+
+ visible = Field(Boolean)
+ galleries = OneToMany('GalleryWidget')
+
+
+class UserRelationshipTypes(object):
+ IS_WATCHING = 1
+
+class UserRelationship(Entity):
+ """Represents some sort of connection between users.
+
+ For the moment, this means "watching". Later, it may mean friending or
+ ignoring.
+
+ XXX: Watching should be made more general than this; it should have the
+ power of an arbitrary query per watched artist without being unintelligible
+ to users.
+ """
+
+ user = ManyToOne('User', required=True)
+ target_user = ManyToOne('User', required=True)
+ type = Field(Integer) # UserRelationshipTypes above
-IdentityURL.user = relation(User, lazy=False, backref="identity_urls")