Rearranged user/art relations.
authorEevee <git@veekun.com>
Sat, 5 Dec 2009 02:46:38 +0000 (18:46 -0800)
committerEevee <git@veekun.com>
Sat, 5 Dec 2009 02:46:38 +0000 (18:46 -0800)
Got rid of the base class monkey-patching.  That's frightening.

Added some accessors to Art to get lists of certain types of relationed
users.

Removed the user-list field from the upload page; for now, we assume the
uploader is also the artist.

floof/controllers/art.py
floof/model/art.py
floof/model/relations.py [deleted file]
floof/public/layout.css
floof/templates/art/new.mako
floof/templates/art/show.mako

index 5b347b3..ee1e4ad 100644 (file)
@@ -8,8 +8,8 @@ from floof.lib.base import BaseController, render
 log = logging.getLogger(__name__)
 
 from floof.lib import file_storage as storage
-from floof.model.users import User
-from floof.model import Art, Rating, UserRelation
+from floof.model import Art, Rating, ArtUser
+from floof.model.art import ArtUserType
 from floof.model.comments import Discussion
 from floof.model.users import User, UserRelationship
 
@@ -35,38 +35,6 @@ class ArtUploadForm(Form):
         if field.data == u'':
             raise ValidationError('File is required')
     
-    # Also make this into a general User List field validator
-    """ PLEASE NOTE!  I just realized that I need to have a __str__ method on User
-    to get it to write the usernames back in the form when it redisplays them, since
-    this validator turns them into user objects instead.  This fact actually sounds dangerous
-    to me in the future, since it means I proably shouldn't be changing the data input
-    by the user right here in the validator, or the user will see the post-mangled data instead
-    of what they actually typed.  Hm.
-    
-    One solution to this could be to only look up the users after normal validation is over, 
-    and then manually add validation errors to the form if that fails.  But I think that kind of
-    sucks.  Perhaps the ideology in Formish, where they keep Validation and Conversion as
-    separate tasks, is a better way of doing it?  That way there is less risk of changing the user's
-    input -- you do that at the conversiot stage -- yet it is still encapsulated in the form workflow.
-    Hm.  But that means I'd have to query for the users in the validation step and throw them away,
-    or something equally stupid.  Guess there's no perfect solution here, but I thought it was
-    worth discussing.
-    
-    Btw, this is meant to be used by a field with multi user autocompletion on it (like on stackoverflow tags),
-    so the user should never actually submit anything invalid unless they disable javascript and force it.
-    """
-    def validate_by(self, field):
-        if not field.data:
-            raise ValidationError("Needs at least one creator")
-        user_names = field.data.split()
-        users = []
-        # TODO: Could totally do a filter__in here instead of picking them out individually
-        for user_name in user_names:
-            user = User.get_by(name=user_name)
-            if not user:
-                raise ValidationError("Couldn't find user %s" % user_name)
-            users.append(user)
-        field.data = users
 
 class ArtController(BaseController):
     def __before__(self, id=None):
@@ -127,8 +95,9 @@ class ArtController(BaseController):
         )
         c.art.discussion = Discussion(count=0)
 
-        for artist in c.form.by.data:
-            UserRelation(user=artist, kind="by", creator=c.user, art=c.art)
+        # For the moment, cheerfully assume that people are uploading their own
+        # art
+        ArtUser(art=c.art, user=c.user, type=ArtUserType.BY)
 
 
         try:
index 8989e8f..ea6d6ee 100644 (file)
@@ -4,7 +4,6 @@
 #   Copyright (c) 2009 Scribblr
 #
 
-# from elixir import Entity, Field, Integer, Unicode
 from elixir import *
 import elixir
 
@@ -12,12 +11,9 @@ from pylons import config
 
 from floof.lib.file_storage import get_path, save_file
 from floof.lib.dbhelpers import find_or_create, update_or_create
-import floof.model.comments
+from floof.model.users import User
 
 
-# Note: Art is the most important class.  To keep its size down, and to better organize the source code,
-# other modules will mix into it automatically by adding to its __bases__.
-
 class Art(Entity):
     title = Field(Unicode(120))
     original_filename = Field(Unicode(120))
@@ -28,8 +24,36 @@ class Art(Entity):
     tags = OneToMany('Tag')
     discussion = ManyToOne('Discussion')
 
-    user_relations = OneToMany('UserRelation')
+    art_users = OneToMany('ArtUser')
 
     @property
     def file_path(self):
         return get_path("art", self.hash)
+
+    # Associated users
+    # XXX ok these could stand to do the filtering sql-side
+    @property
+    def artists(self):
+        return (au.user for au in self.art_users if au.type == ArtUserType.BY)
+
+    @property
+    def recipients(self):
+        return (au.user for au in self.art_users if au.type == ArtUserType.FOR)
+
+    @property
+    def participants(self):
+        return (au.user for au in self.art_users if au.type == ArtUserType.OF)
+
+
+class ArtUserType(object):
+    BY = 1
+    FOR = 2
+    OF = 3
+
+class ArtUser(Entity):
+    art = ManyToOne('Art', required=True)
+    user = ManyToOne('User', required=True)
+    type = Field(Integer, required=True)  # ArtUserType
+
+    # TODO: admin log ought to remember who confirmed the relation.
+    #       (tag history will remember who proposed it)
diff --git a/floof/model/relations.py b/floof/model/relations.py
deleted file mode 100644 (file)
index a6fe020..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-from elixir import *
-from art import Art
-
-
-class UserRelation(Entity):
-    user = ManyToOne("User")
-    art = ManyToOne("Art")
-    kind = Field(String) # by for of
-    creator = ManyToOne("User")
-    confirmed_by_related_user = Field(Boolean)
-
-    # it is useful to record which authority figure on a given artwork
-    # confirmed the validity of this relation.
-    confirmed_by_authority = ManyToOne("User")
-    
-    def __init__(self, **kwargs):
-        super(UserRelation, self).__init__(**kwargs)
-        assert self.user and self.art and self.kind and self.creator
-        
-        if self.creator == self.user:
-            self.confirmed_by_related_user = True
-        # TODO: implement authorities
-        # if self.creator in self.art.authorities
-        #     self.confirmed_by_authority = self.creator
-
-    def __unicode__(self):
-        return "%s: %s" % (self.kind, self.related_user)
-
-
-class RelationMixin(object):
-    def add_relation(creator, kind, user):
-        return UserRelation(art=self, creator=creator, kind=kind, user=user)
-
-Art.__bases__ += (RelationMixin,)
index bc7056e..7a7308b 100644 (file)
@@ -16,6 +16,7 @@ body { font-family: sans-serif; font-size: 12px; }
 
 /*** Common bits and pieces ***/
 h1 { margin: 0.5em 0 0.25em; font-size: 2em; border-bottom: 1px solid #404040; text-shadow: #a0a0a0 1px 1px 1px; }
+h2 { margin: 0.5em 0 0.25em; font-size: 1.5em; border-bottom: 1px dotted #606060; text-shadow: #a0a0a0 1px 1px 1px; }
 
 a { color: #647cc4; font-weight: bold; text-decoration: none; pointer: cursor; }
 a:visited { color: #48598e; }
index 4204700..2b18b42 100644 (file)
@@ -1,18 +1,11 @@
 <%inherit file="/base.mako" />
 
 <h1>Add New Art</h1>
-<p>Now: Upload a file.  Later: Supply a link?  Not exclusive to uploading.</p>
-
-## Todo: write some macros to make outputting form fields easier.
-
 ${h.form(h.url('create_art'), multipart=True)}
 
-${normal_field(c.form.by)}
+## Todo: write some macros to make outputting form fields easier.
 ${normal_field(c.form.file)}
 
-
-##Artist: ${h.text('artist')}
-##${h.file('file')}
 ${h.submit(None, 'Upload!')}
 ${h.end_form()}
 
index a38806d..bf14dff 100644 (file)
@@ -34,8 +34,12 @@ ${h.end_form()}
 
 <h2>Relations</h2>
 <ul>
-% for relation in c.art.user_relations:
-<li>${relation.kind}: ${relation.user}
+% for label, relations in (('Artist', c.art.artists), \
+                               ('Recipient', c.art.recipients), \
+                               ('Participant', c.art.participants)):
+% for user in relations:
+<li>${label}: ${user.name}
+% endfor
 % endfor
 </ul>