2 # floof/floof/model/art.py
4 # Copyright (c) 2009 Scribblr
7 # from elixir import Entity, Field, Integer, Unicode
11 from pylons
import config
13 from floof
.lib
.file_storage
import get_path
, save_file
14 from floof
.lib
.dbhelpers
import find_or_create
, update_or_create
15 import floof
.model
.comments
18 title
= Field(Unicode(120))
19 original_filename
= Field(Unicode(120))
20 hash = Field(String
, unique
=True, required
=True)
22 uploader
= ManyToOne('User', required
=True)
23 tags
= OneToMany('Tag')
24 discussion
= ManyToOne('Discussion')
26 user_relations
= OneToMany('UserRelation')
29 def set_file(self
, file):
30 self
.hash = save_file("art", file)
31 self
.original_filename
= file.filename
33 file = property(get_path
, set_file
)
37 return get_path("art", self
.hash)
40 def add_tags(self
, tags
, user
):
41 for text
in tags
.split():
44 tagtext
= TagText
.get_by(text
=text
[1:])
46 tag
= Tag
.get_by(art
=self
, tagger
=user
, tagtext
=tagtext
)
48 elixir
.session
.delete(tag
)
52 raise "Long Tag!" # can we handle this more gracefully?
53 # sqlite seems happy to store strings much longer than the supplied limit...
55 # elixir should really have its own find_or_create.
56 tagtext
= find_or_create(TagText
, text
=text
)
57 tag
= find_or_create(Tag
, art
=self
, tagger
=user
, tagtext
=tagtext
)
62 def rate(self
, score
, user
):
63 return update_or_create(Rating
, {"rater":user
, "art":self
}, {"score":score
})
65 def user_score(self
, user
):
66 rating
= Rating
.get_by(rater
=user
, art
=self
)
71 def __unicode__(self
):
72 return self
.get_path()
76 # look into how ondelete works. This just sets a database property.
77 art
= ManyToOne('Art', ondelete
='cascade')
78 tagger
= ManyToOne('User', ondelete
='cascade')
79 tagtext
= ManyToOne('TagText')
81 def __unicode__(self
):
84 return unicode(self
.tagtext
)
87 class TagText(Entity
):
88 text
= Field(Unicode(50)) # gotta enforce this somehow
89 tags
= OneToMany('Tag')
91 def __unicode__(self
):
96 art
= ManyToOne('Art', ondelete
='cascade')
97 rater
= ManyToOne('User', ondelete
='cascade')
98 score
= Field(Integer
)
100 options
= {-1:"sucks", 0:"undecided", 1:"good", 2:"great"}
103 Rating
.reverse_options
= dict (zip(Rating
.options
.values(), Rating
.options
.keys()))
107 class UserRelation(Entity
):
108 user
= ManyToOne("User")
109 art
= ManyToOne("Art")
110 kind
= Field(String
) # by for of
111 creator
= ManyToOne("User")
112 confirmed_by_related_user
= Field(Boolean
)
114 # it is useful to record which authority figure on a given artwork
115 # confirmed the validity of this relation.
116 confirmed_by_authority
= ManyToOne("User")
118 def __init__(self
, **kwargs
):
119 super(UserRelation
, self
).__init__(**kwargs
)
120 assert self
.user
and self
.art
and self
.kind
and self
.creator
122 if self
.creator
== self
.user
:
123 self
.confirmed_by_related_user
= True
124 # TODO: implement authorities
125 # if self.creator in self.art.authorities
126 # self.confirmed_by_authority = self.creator
128 def __unicode__(self
):
129 return "%s: %s" %
(self
.kind
, self
.related_user
)
133 # class CharacterRelation(Entity):