Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
CIRCLE
/
django-taggit
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Wiki
Members
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
f64167b8
authored
Dec 08, 2009
by
Alex Gaynor
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added support for querying on tags.
parent
d401839e
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
88 additions
and
3 deletions
+88
-3
taggit/managers.py
+56
-0
taggit/models.py
+1
-1
taggit/tests/models.py
+9
-0
taggit/tests/tests.py
+22
-2
No files found.
taggit/managers.py
View file @
f64167b8
from
django.contrib.contenttypes.models
import
ContentType
from
django.db
import
models
from
django.db.models.fields.related
import
ManyToManyRel
from
django.db.models.query_utils
import
QueryWrapper
from
taggit.models
import
Tag
,
TaggedItem
from
taggit.utils
import
require_instance_manager
class
TaggableRel
(
ManyToManyRel
):
def
__init__
(
self
):
self
.
to
=
TaggedItem
self
.
related_name
=
None
self
.
limit_choices_to
=
{}
self
.
symmetrical
=
True
self
.
multiple
=
True
self
.
through
=
None
class
TaggableManager
(
object
):
def
__init__
(
self
):
self
.
rel
=
TaggableRel
()
self
.
editable
=
False
self
.
unique
=
False
self
.
creates_table
=
False
self
.
db_column
=
None
def
__get__
(
self
,
instance
,
type
):
manager
=
_TaggableManager
()
manager
.
model
=
type
...
...
@@ -14,6 +33,43 @@ class TaggableManager(object):
else
:
manager
.
object_id
=
instance
.
pk
return
manager
def
contribute_to_class
(
self
,
cls
,
name
):
self
.
name
=
self
.
column
=
name
self
.
model
=
cls
cls
.
_meta
.
add_field
(
self
)
setattr
(
cls
,
name
,
self
)
def
save_form_data
(
self
,
instance
,
value
):
pass
def
get_db_prep_lookup
(
self
,
lookup_type
,
value
):
if
lookup_type
!=
"in"
:
raise
ValueError
(
"You can't do lookups other than in on Tags"
)
qs
=
TaggedItem
.
objects
.
filter
(
tag__name__in
=
value
)
.
values_list
(
"pk"
,
flat
=
True
)
sql
,
params
=
qs
.
query
.
as_sql
()
return
QueryWrapper
((
"(
%
s)"
%
sql
),
params
)
def
related_query_name
(
self
):
return
None
def
m2m_reverse_name
(
self
):
return
"id"
def
m2m_column_name
(
self
):
return
"object_id"
def
db_type
(
self
):
return
None
def
m2m_db_table
(
self
):
return
self
.
rel
.
to
.
_meta
.
db_table
def
extra_filters
(
self
,
pieces
,
pos
,
negate
):
if
negate
:
return
[]
prefix
=
"__"
.
join
(
pieces
[:
pos
+
1
])
return
[(
"
%
s__content_type"
%
prefix
,
ContentType
.
objects
.
get_for_model
(
self
.
model
))]
class
_TaggableManager
(
models
.
Manager
):
...
...
taggit/models.py
View file @
f64167b8
...
...
@@ -18,4 +18,4 @@ class TaggedItem(models.Model):
tag
=
models
.
ForeignKey
(
Tag
,
related_name
=
"items"
)
def
__unicode__
(
self
):
return
"
%
s tagged with
%
"
%
(
self
.
content_object
,
self
.
tag
)
return
"
%
s tagged with
%
s
"
%
(
self
.
content_object
,
self
.
tag
)
taggit/tests/models.py
View file @
f64167b8
...
...
@@ -7,3 +7,12 @@ class Food(models.Model):
name
=
models
.
CharField
(
max_length
=
50
)
tags
=
TaggableManager
()
def
__unicode__
(
self
):
return
self
.
name
class
Pet
(
models
.
Model
):
name
=
models
.
CharField
(
max_length
=
50
)
tags
=
TaggableManager
()
taggit/tests/tests.py
View file @
f64167b8
...
...
@@ -2,13 +2,15 @@ from django.test import TestCase
from
taggit.models
import
Tag
from
taggit.tests.forms
import
FoodForm
from
taggit.tests.models
import
Food
from
taggit.tests.models
import
Food
,
Pet
class
BaseTaggingTest
(
TestCase
):
def
assert_tags_equal
(
self
,
qs
,
tags
):
tags
=
Tag
.
objects
.
filter
(
name__in
=
tags
)
self
.
assertEqual
(
list
(
qs
),
list
(
tags
))
class
AddTagTestCase
(
BaseTaggingTest
):
def
test_add_tag
(
self
):
apple
=
Food
.
objects
.
create
(
name
=
"apple"
)
...
...
@@ -29,11 +31,29 @@ class AddTagTestCase(BaseTaggingTest):
self
.
assert_tags_equal
(
Food
.
tags
.
all
(),
[
'green'
,
'red'
])
self
.
assert_tags_equal
(
Food
.
tags
.
most_common
(),
[
'green'
,
'red'
])
apple
.
tags
.
remove
(
'green'
)
self
.
assert_tags_equal
(
apple
.
tags
.
all
(),
[
'red'
])
self
.
assert_tags_equal
(
Food
.
tags
.
all
(),
[
'green'
,
'red'
])
class
LookupByTagTestCase
(
BaseTaggingTest
):
def
test_lookup_by_tag
(
self
):
apple
=
Food
.
objects
.
create
(
name
=
"apple"
)
apple
.
tags
.
add
(
"red"
,
"green"
)
pear
=
Food
.
objects
.
create
(
name
=
"pear"
)
pear
.
tags
.
add
(
"green"
)
self
.
assertEqual
(
list
(
Food
.
objects
.
filter
(
tags__in
=
[
"red"
])),
[
apple
])
self
.
assertEqual
(
list
(
Food
.
objects
.
filter
(
tags__in
=
[
"green"
])),
[
apple
,
pear
])
kitty
=
Pet
.
objects
.
create
(
name
=
"kitty"
)
kitty
.
tags
.
add
(
"fuzzy"
,
"red"
)
dog
=
Pet
.
objects
.
create
(
name
=
"dog"
)
dog
.
tags
.
add
(
"woof"
,
"red"
)
self
.
assertEqual
(
list
(
Food
.
objects
.
filter
(
tags__in
=
[
"red"
])
.
distinct
()),
[
apple
])
class
TaggableFormTestCase
(
BaseTaggingTest
):
def
test_form
(
self
):
self
.
assertEqual
(
FoodForm
.
base_fields
.
keys
(),
[
'name'
,
'tags'
])
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment