X-Git-Url: http://git.veekun.com/zzz-floof.git/blobdiff_plain/224a257ade788e1a87aab78032dc3cdc9677cc06..42398bc94b95b5a115396f14c3c1dde6fb6808a5:/floof/model/users.py diff --git a/floof/model/users.py b/floof/model/users.py index f51282c..6643702 100644 --- a/floof/model/users.py +++ b/floof/model/users.py @@ -1,19 +1,125 @@ -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")