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
f759697f
authored
Oct 17, 2010
by
Alex Gaynor
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added support for a custom slugify.
parent
dccc744b
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
59 additions
and
20 deletions
+59
-20
taggit/managers.py
+2
-2
taggit/models.py
+10
-5
taggit/tests/models.py
+27
-2
taggit/tests/tests.py
+20
-11
No files found.
taggit/managers.py
View file @
f759697f
...
@@ -142,10 +142,10 @@ class _TaggableManager(models.Manager):
...
@@ -142,10 +142,10 @@ class _TaggableManager(models.Manager):
name__in
=
str_tags
name__in
=
str_tags
)
)
tag_objs
.
update
(
existing
)
tag_objs
.
update
(
existing
)
for
new_tag
in
str_tags
-
set
(
t
.
name
for
t
in
existing
):
for
new_tag
in
str_tags
-
set
(
t
.
name
for
t
in
existing
):
tag_objs
.
add
(
self
.
through
.
tag_model
()
.
objects
.
create
(
name
=
new_tag
))
tag_objs
.
add
(
self
.
through
.
tag_model
()
.
objects
.
create
(
name
=
new_tag
))
for
tag
in
tag_objs
:
for
tag
in
tag_objs
:
self
.
through
.
objects
.
get_or_create
(
tag
=
tag
,
**
self
.
_lookup_kwargs
())
self
.
through
.
objects
.
get_or_create
(
tag
=
tag
,
**
self
.
_lookup_kwargs
())
...
...
taggit/models.py
View file @
f759697f
...
@@ -2,7 +2,7 @@ import django
...
@@ -2,7 +2,7 @@ import django
from
django.contrib.contenttypes.models
import
ContentType
from
django.contrib.contenttypes.models
import
ContentType
from
django.contrib.contenttypes.generic
import
GenericForeignKey
from
django.contrib.contenttypes.generic
import
GenericForeignKey
from
django.db
import
models
,
IntegrityError
,
transaction
from
django.db
import
models
,
IntegrityError
,
transaction
from
django.template.defaultfilters
import
slugify
from
django.template.defaultfilters
import
slugify
as
default_slugify
from
django.utils.translation
import
ugettext_lazy
as
_
,
ugettext
from
django.utils.translation
import
ugettext_lazy
as
_
,
ugettext
...
@@ -18,7 +18,7 @@ class TagBase(models.Model):
...
@@ -18,7 +18,7 @@ class TagBase(models.Model):
def
save
(
self
,
*
args
,
**
kwargs
):
def
save
(
self
,
*
args
,
**
kwargs
):
if
not
self
.
pk
and
not
self
.
slug
:
if
not
self
.
pk
and
not
self
.
slug
:
self
.
slug
=
s
lug
=
slugify
(
self
.
name
)
self
.
slug
=
s
elf
.
slugify
(
self
.
name
)
if
django
.
VERSION
>=
(
1
,
2
):
if
django
.
VERSION
>=
(
1
,
2
):
from
django.db
import
router
from
django.db
import
router
using
=
kwargs
.
get
(
"using"
)
or
router
.
db_for_write
(
using
=
kwargs
.
get
(
"using"
)
or
router
.
db_for_write
(
...
@@ -39,11 +39,17 @@ class TagBase(models.Model):
...
@@ -39,11 +39,17 @@ class TagBase(models.Model):
return
res
return
res
except
IntegrityError
:
except
IntegrityError
:
transaction
.
savepoint_rollback
(
sid
,
**
trans_kwargs
)
transaction
.
savepoint_rollback
(
sid
,
**
trans_kwargs
)
i
+=
1
self
.
slug
=
self
.
slugify
(
self
.
name
,
i
)
self
.
slug
=
"
%
s_
%
d"
%
(
slug
,
i
)
else
:
else
:
return
super
(
TagBase
,
self
)
.
save
(
*
args
,
**
kwargs
)
return
super
(
TagBase
,
self
)
.
save
(
*
args
,
**
kwargs
)
def
slugify
(
self
,
tag
,
i
=
None
):
slug
=
default_slugify
(
tag
)
if
i
is
not
None
:
slug
+=
"_
%
d"
%
i
return
slug
class
Tag
(
TagBase
):
class
Tag
(
TagBase
):
class
Meta
:
class
Meta
:
verbose_name
=
_
(
"Tag"
)
verbose_name
=
_
(
"Tag"
)
...
@@ -137,4 +143,3 @@ class TaggedItem(GenericTaggedItemBase, TaggedItemBase):
...
@@ -137,4 +143,3 @@ class TaggedItem(GenericTaggedItemBase, TaggedItemBase):
class
Meta
:
class
Meta
:
verbose_name
=
_
(
"Tagged Item"
)
verbose_name
=
_
(
"Tagged Item"
)
verbose_name_plural
=
_
(
"Tagged Items"
)
verbose_name_plural
=
_
(
"Tagged Items"
)
taggit/tests/models.py
View file @
f759697f
from
django.db
import
models
from
django.db
import
models
from
taggit.managers
import
TaggableManager
from
taggit.managers
import
TaggableManager
from
taggit.models
import
TaggedItemBase
,
GenericTaggedItemBase
,
TagBase
from
taggit.models
import
(
TaggedItemBase
,
GenericTaggedItemBase
,
TaggedItem
,
TagBase
,
Tag
)
class
Food
(
models
.
Model
):
class
Food
(
models
.
Model
):
...
@@ -106,7 +107,7 @@ class OfficialHousePet(OfficialPet):
...
@@ -106,7 +107,7 @@ class OfficialHousePet(OfficialPet):
class
Media
(
models
.
Model
):
class
Media
(
models
.
Model
):
tags
=
TaggableManager
()
tags
=
TaggableManager
()
class
Meta
:
class
Meta
:
abstract
=
True
abstract
=
True
...
@@ -115,3 +116,27 @@ class Photo(Media):
...
@@ -115,3 +116,27 @@ class Photo(Media):
class
Movie
(
Media
):
class
Movie
(
Media
):
pass
pass
class
ArticleTag
(
Tag
):
class
Meta
:
proxy
=
True
def
slugify
(
self
,
tag
,
i
=
None
):
slug
=
"category-
%
s"
%
tag
if
i
is
not
None
:
slug
+=
"-
%
d"
%
i
return
slug
class
ArticleTaggedItem
(
TaggedItem
):
class
Meta
:
proxy
=
True
# Basically we want to overide the tag ForeignKey to point at the proxy
# inherited ArticleTag so we can get the right slugify, unfortunately I
# can't seem to figure out how to do this, so we're on hold ATM.
class
Article
(
models
.
Model
):
title
=
models
.
CharField
(
max_length
=
100
)
tags
=
TaggableManager
(
through
=
ArticleTaggedItem
)
taggit/tests/tests.py
View file @
f759697f
...
@@ -12,18 +12,18 @@ from taggit.tests.forms import (FoodForm, DirectFoodForm, CustomPKFoodForm,
...
@@ -12,18 +12,18 @@ from taggit.tests.forms import (FoodForm, DirectFoodForm, CustomPKFoodForm,
from
taggit.tests.models
import
(
Food
,
Pet
,
HousePet
,
DirectFood
,
DirectPet
,
from
taggit.tests.models
import
(
Food
,
Pet
,
HousePet
,
DirectFood
,
DirectPet
,
DirectHousePet
,
TaggedPet
,
CustomPKFood
,
CustomPKPet
,
CustomPKHousePet
,
DirectHousePet
,
TaggedPet
,
CustomPKFood
,
CustomPKPet
,
CustomPKHousePet
,
TaggedCustomPKPet
,
OfficialFood
,
OfficialPet
,
OfficialHousePet
,
TaggedCustomPKPet
,
OfficialFood
,
OfficialPet
,
OfficialHousePet
,
OfficialThroughModel
,
OfficialTag
,
Photo
,
Movie
)
OfficialThroughModel
,
OfficialTag
,
Photo
,
Movie
,
Article
)
from
taggit.utils
import
parse_tags
,
edit_string_for_tags
from
taggit.utils
import
parse_tags
,
edit_string_for_tags
class
BaseTaggingTest
(
object
):
class
BaseTaggingTest
(
object
):
def
assert_tags_equal
(
self
,
qs
,
tags
,
sort
=
True
):
def
assert_tags_equal
(
self
,
qs
,
tags
,
sort
=
True
,
attr
=
"name"
):
got
=
map
(
lambda
tag
:
tag
.
name
,
qs
)
got
=
map
(
lambda
tag
:
getattr
(
tag
,
attr
)
,
qs
)
if
sort
:
if
sort
:
got
.
sort
()
got
.
sort
()
tags
.
sort
()
tags
.
sort
()
self
.
assertEqual
(
got
,
tags
)
self
.
assertEqual
(
got
,
tags
)
def
assert_num_queries
(
self
,
n
,
f
,
*
args
,
**
kwargs
):
def
assert_num_queries
(
self
,
n
,
f
,
*
args
,
**
kwargs
):
original_DEBUG
=
settings
.
DEBUG
original_DEBUG
=
settings
.
DEBUG
settings
.
DEBUG
=
True
settings
.
DEBUG
=
True
...
@@ -61,6 +61,15 @@ class TagModelTestCase(BaseTaggingTransactionTestCase):
...
@@ -61,6 +61,15 @@ class TagModelTestCase(BaseTaggingTransactionTestCase):
yummy
=
self
.
tag_model
.
objects
.
create
(
name
=
"yummy"
)
yummy
=
self
.
tag_model
.
objects
.
create
(
name
=
"yummy"
)
apple
.
tags
.
add
(
yummy
)
apple
.
tags
.
add
(
yummy
)
def
test_slugify
(
self
):
a
=
Article
.
objects
.
create
(
title
=
"django-taggit 1.0 Released"
)
a
.
tags
.
add
(
"awesome"
,
"release"
,
"AWESOME"
)
self
.
assert_tags_equal
(
a
.
tags
.
all
(),
[
"category-awesome"
,
"category-release"
,
"category-awesome-1"
],
attr
=
"slug"
)
class
TagModelDirectTestCase
(
TagModelTestCase
):
class
TagModelDirectTestCase
(
TagModelTestCase
):
food_model
=
DirectFood
food_model
=
DirectFood
tag_model
=
Tag
tag_model
=
Tag
...
@@ -113,7 +122,7 @@ class TaggableManagerTestCase(BaseTaggingTestCase):
...
@@ -113,7 +122,7 @@ class TaggableManagerTestCase(BaseTaggingTestCase):
apple
.
delete
()
apple
.
delete
()
self
.
assert_tags_equal
(
self
.
food_model
.
tags
.
all
(),
[
"green"
])
self
.
assert_tags_equal
(
self
.
food_model
.
tags
.
all
(),
[
"green"
])
def
test_add_queries
(
self
):
def
test_add_queries
(
self
):
apple
=
self
.
food_model
.
objects
.
create
(
name
=
"apple"
)
apple
=
self
.
food_model
.
objects
.
create
(
name
=
"apple"
)
# 1 query to see which tags exist
# 1 query to see which tags exist
...
@@ -121,13 +130,13 @@ class TaggableManagerTestCase(BaseTaggingTestCase):
...
@@ -121,13 +130,13 @@ class TaggableManagerTestCase(BaseTaggingTestCase):
# + 6 queries to create the intermediary things (including SELECTs, to
# + 6 queries to create the intermediary things (including SELECTs, to
# make sure we don't double create.
# make sure we don't double create.
self
.
assert_num_queries
(
10
,
apple
.
tags
.
add
,
"red"
,
"delicious"
,
"green"
)
self
.
assert_num_queries
(
10
,
apple
.
tags
.
add
,
"red"
,
"delicious"
,
"green"
)
pear
=
self
.
food_model
.
objects
.
create
(
name
=
"pear"
)
pear
=
self
.
food_model
.
objects
.
create
(
name
=
"pear"
)
# 1 query to see which tags exist
# 1 query to see which tags exist
# + 4 queries to create the intermeidary things (including SELECTs, to
# + 4 queries to create the intermeidary things (including SELECTs, to
# make sure we dont't double create.
# make sure we dont't double create.
self
.
assert_num_queries
(
5
,
pear
.
tags
.
add
,
"green"
,
"delicious"
)
self
.
assert_num_queries
(
5
,
pear
.
tags
.
add
,
"green"
,
"delicious"
)
self
.
assert_num_queries
(
0
,
pear
.
tags
.
add
)
self
.
assert_num_queries
(
0
,
pear
.
tags
.
add
)
def
test_require_pk
(
self
):
def
test_require_pk
(
self
):
...
@@ -245,7 +254,7 @@ class TaggableManagerTestCase(BaseTaggingTestCase):
...
@@ -245,7 +254,7 @@ class TaggableManagerTestCase(BaseTaggingTestCase):
unicode
(
self
.
taggeditem_model
.
objects
.
all
()[
0
]),
unicode
(
self
.
taggeditem_model
.
objects
.
all
()[
0
]),
"ross tagged with president"
"ross tagged with president"
)
)
def
test_abstract_subclasses
(
self
):
def
test_abstract_subclasses
(
self
):
p
=
Photo
.
objects
.
create
()
p
=
Photo
.
objects
.
create
()
p
.
tags
.
add
(
"outdoors"
,
"pretty"
)
p
.
tags
.
add
(
"outdoors"
,
"pretty"
)
...
@@ -253,7 +262,7 @@ class TaggableManagerTestCase(BaseTaggingTestCase):
...
@@ -253,7 +262,7 @@ class TaggableManagerTestCase(BaseTaggingTestCase):
p
.
tags
.
all
(),
p
.
tags
.
all
(),
[
"outdoors"
,
"pretty"
]
[
"outdoors"
,
"pretty"
]
)
)
m
=
Movie
.
objects
.
create
()
m
=
Movie
.
objects
.
create
()
m
.
tags
.
add
(
"hd"
)
m
.
tags
.
add
(
"hd"
)
self
.
assert_tags_equal
(
self
.
assert_tags_equal
(
...
@@ -340,9 +349,9 @@ class TaggableFormTestCase(BaseTaggingTestCase):
...
@@ -340,9 +349,9 @@ class TaggableFormTestCase(BaseTaggingTestCase):
self
.
assertEqual
(
ff
.
label
,
'categories'
)
self
.
assertEqual
(
ff
.
label
,
'categories'
)
self
.
assertEqual
(
ff
.
help_text
,
u'Add some categories'
)
self
.
assertEqual
(
ff
.
help_text
,
u'Add some categories'
)
self
.
assertEqual
(
ff
.
required
,
False
)
self
.
assertEqual
(
ff
.
required
,
False
)
self
.
assertEqual
(
ff
.
clean
(
""
),
[])
self
.
assertEqual
(
ff
.
clean
(
""
),
[])
tm
=
TaggableManager
()
tm
=
TaggableManager
()
ff
=
tm
.
formfield
()
ff
=
tm
.
formfield
()
self
.
assertRaises
(
ValidationError
,
ff
.
clean
,
""
)
self
.
assertRaises
(
ValidationError
,
ff
.
clean
,
""
)
...
...
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