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
A prog2-höz tartozó friss repo anyagok itt elérhetőek:
https://git.iit.bme.hu/
Commit
ed8af524
authored
Sep 21, 2014
by
Florian Apolloner
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop'
parents
316ee157
20780f93
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
199 additions
and
107 deletions
+199
-107
CHANGELOG.txt
+4
-0
setup.cfg
+11
-0
setup.py
+1
-1
taggit/__init__.py
+1
-1
taggit/forms.py
+7
-4
taggit/managers.py
+46
-31
taggit/migrations/0001_initial.py
+4
-3
taggit/models.py
+9
-7
taggit/utils.py
+1
-1
taggit/views.py
+1
-2
tests/forms.py
+3
-4
tests/migrations/0001_initial.py
+38
-14
tests/models.py
+10
-2
tests/tests.py
+62
-36
tox.ini
+1
-1
No files found.
CHANGELOG.txt
View file @
ed8af524
Changelog
=========
0.12.2 (21.09.2014)
~~~~~~~~~~~~~~~~~~~
* Fixed 1.7 migrations.
0.12.1 (10.08.2014)
~~~~~~~~~~~~~~~~~~~
* Final (hopefully) fixes for the upcoming Django 1.7 release.
...
...
setup.cfg
View file @
ed8af524
...
...
@@ -3,3 +3,14 @@ license-file = LICENSE
[wheel]
universal=1
[flake8]
# ignore=NONE
# max-line-length=100
# E302: expected 2 blank lines, found 1 [E302]
# E501: line too long
ignore=E501,E302
[isort]
forced_separate=tests,taggit
setup.py
View file @
ed8af524
...
...
@@ -7,7 +7,7 @@ f.close()
setup
(
name
=
'django-taggit'
,
version
=
'0.12.
1
'
,
version
=
'0.12.
2
'
,
description
=
'django-taggit is a reusable Django application for simple tagging.'
,
long_description
=
readme
,
author
=
'Alex Gaynor'
,
...
...
taggit/__init__.py
View file @
ed8af524
VERSION
=
(
0
,
12
,
1
)
VERSION
=
(
0
,
12
,
2
)
taggit/forms.py
View file @
ed8af524
from
__future__
import
unicode_literals
from
django
import
forms
from
django.utils.translation
import
ugettext
as
_
from
django.utils
import
six
from
django.utils.translation
import
ugettext
as
_
from
taggit.utils
import
parse_tags
,
edit_string_for
_tags
from
taggit.utils
import
edit_string_for_tags
,
parse
_tags
class
TagWidget
(
forms
.
TextInput
):
def
render
(
self
,
name
,
value
,
attrs
=
None
):
if
value
is
not
None
and
not
isinstance
(
value
,
six
.
string_types
):
value
=
edit_string_for_tags
([
o
.
tag
for
o
in
value
.
select_related
(
"tag"
)])
value
=
edit_string_for_tags
([
o
.
tag
for
o
in
value
.
select_related
(
"tag"
)])
return
super
(
TagWidget
,
self
)
.
render
(
name
,
value
,
attrs
)
class
TagField
(
forms
.
CharField
):
widget
=
TagWidget
...
...
@@ -21,4 +23,5 @@ class TagField(forms.CharField):
try
:
return
parse_tags
(
value
)
except
ValueError
:
raise
forms
.
ValidationError
(
_
(
"Please provide a comma-separated list of tags."
))
raise
forms
.
ValidationError
(
_
(
"Please provide a comma-separated list of tags."
))
taggit/managers.py
View file @
ed8af524
from
__future__
import
unicode_literals
from
operator
import
attrgetter
from
django
import
VERSION
try
:
from
django.contrib.contenttypes.fields
import
GenericRelation
except
ImportError
:
# django < 1.7
from
django.contrib.contenttypes.generic
import
GenericRelation
from
django.contrib.contenttypes.models
import
ContentType
from
django.db
import
models
,
router
from
django.db.models.fields
import
Field
from
django.db.models.fields.related
import
ManyToManyRel
,
RelatedField
,
add_lazy_relation
from
django.db.models.fields.related
import
(
add_lazy_relation
,
ManyToManyRel
,
RelatedField
)
from
django.db.models.related
import
RelatedObject
from
django.utils
import
six
from
django.utils.text
import
capfirst
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.utils
import
six
from
taggit.forms
import
TagField
from
taggit.models
import
GenericTaggedItemBase
,
TaggedItem
from
taggit.utils
import
require_instance_manager
try
:
from
django.contrib.contenttypes.fields
import
GenericRelation
except
ImportError
:
# django < 1.7
from
django.contrib.contenttypes.generic
import
GenericRelation
try
:
from
django.db.models.related
import
PathInfo
except
ImportError
:
pass
# PathInfo is not used on Django < 1.6
from
taggit.forms
import
TagField
from
taggit.models
import
TaggedItem
,
GenericTaggedItemBase
from
taggit.utils
import
require_instance_manager
def
_model_name
(
model
):
...
...
@@ -102,7 +106,7 @@ class _TaggableManager(models.Manager):
else
'content_object'
)
fk
=
self
.
through
.
_meta
.
get_field
(
fieldname
)
query
=
{
'
%
s__
%
s__in'
%
(
self
.
through
.
tag_relname
(),
fk
.
name
)
:
'
%
s__
%
s__in'
%
(
self
.
through
.
tag_relname
(),
fk
.
name
):
set
(
obj
.
_get_pk_val
()
for
obj
in
instances
)
}
join_table
=
self
.
through
.
_meta
.
db_table
...
...
@@ -110,13 +114,13 @@ class _TaggableManager(models.Manager):
connection
=
connections
[
db
]
qn
=
connection
.
ops
.
quote_name
qs
=
self
.
get_queryset
()
.
using
(
db
)
.
_next_is_sticky
()
.
filter
(
**
query
)
.
extra
(
select
=
{
'_prefetch_related_val'
:
'
%
s.
%
s'
%
(
qn
(
join_table
),
qn
(
source_col
))
select
=
{
'_prefetch_related_val'
:
'
%
s.
%
s'
%
(
qn
(
join_table
),
qn
(
source_col
))
}
)
return
(
qs
,
attrgetter
(
'_prefetch_related_val'
),
attrgetter
(
instance
.
_meta
.
pk
.
name
),
lambda
obj
:
obj
.
_get_pk_val
(
),
False
,
self
.
prefetch_cache_name
)
...
...
@@ -129,12 +133,17 @@ class _TaggableManager(models.Manager):
@require_instance_manager
def
add
(
self
,
*
tags
):
str_tags
=
set
([
t
for
t
in
tags
if
not
isinstance
(
t
,
self
.
through
.
tag_model
())
])
tag_objs
=
set
(
tags
)
-
str_tags
str_tags
=
set
()
tag_objs
=
set
()
for
t
in
tags
:
if
isinstance
(
t
,
self
.
through
.
tag_model
()):
tag_objs
.
add
(
t
)
elif
isinstance
(
t
,
six
.
string_types
):
str_tags
.
add
(
t
)
else
:
raise
ValueError
(
"Cannot add {0} ({1}). Expected {2} or str."
.
format
(
t
,
type
(
t
),
type
(
self
.
through
.
tag_model
())))
# If str_tags has 0 elements Django actually optimizes that to not do a
# query. Malcolm is very smart.
existing
=
self
.
through
.
tag_model
()
.
objects
.
filter
(
...
...
@@ -220,10 +229,12 @@ class _TaggableManager(models.Manager):
class
TaggableManager
(
RelatedField
,
Field
):
_related_name_counter
=
0
def
__init__
(
self
,
verbose_name
=
_
(
"Tags"
),
help_text
=
_
(
"A comma-separated list of tags."
),
through
=
None
,
blank
=
False
,
related_name
=
None
,
to
=
None
,
manager
=
_TaggableManager
):
Field
.
__init__
(
self
,
verbose_name
=
verbose_name
,
help_text
=
help_text
,
blank
=
blank
,
null
=
True
,
serialize
=
False
)
def
__init__
(
self
,
verbose_name
=
_
(
"Tags"
),
help_text
=
_
(
"A comma-separated list of tags."
),
through
=
None
,
blank
=
False
,
related_name
=
None
,
to
=
None
,
manager
=
_TaggableManager
):
Field
.
__init__
(
self
,
verbose_name
=
verbose_name
,
help_text
=
help_text
,
blank
=
blank
,
null
=
True
,
serialize
=
False
)
self
.
through
=
through
or
TaggedItem
self
.
rel
=
TaggableRel
(
self
,
related_name
,
self
.
through
,
to
=
to
)
self
.
swappable
=
False
...
...
@@ -233,12 +244,12 @@ class TaggableManager(RelatedField, Field):
def
__get__
(
self
,
instance
,
model
):
if
instance
is
not
None
and
instance
.
pk
is
None
:
raise
ValueError
(
"
%
s objects need to have a primary key value "
"before you can access their tags."
%
model
.
__name__
)
"before you can access their tags."
%
model
.
__name__
)
manager
=
self
.
manager
(
through
=
self
.
through
,
model
=
model
,
instance
=
instance
,
prefetch_cache_name
=
self
.
name
prefetch_cache_name
=
self
.
name
)
return
manager
...
...
@@ -287,7 +298,6 @@ class TaggableManager(RelatedField, Field):
else
:
self
.
post_through_setup
(
cls
)
def
__lt__
(
self
,
other
):
"""
Required contribute_to_class as Django uses bisect
...
...
@@ -364,7 +374,7 @@ class TaggableManager(RelatedField, Field):
def
extra_filters
(
self
,
pieces
,
pos
,
negate
):
if
negate
or
not
self
.
use_gfk
:
return
[]
prefix
=
"__"
.
join
([
"tagged_items"
]
+
pieces
[:
pos
-
2
])
prefix
=
"__"
.
join
([
"tagged_items"
]
+
pieces
[:
pos
-
2
])
get
=
ContentType
.
objects
.
get_for_model
cts
=
[
get
(
obj
)
for
obj
in
_get_subclasses
(
self
.
model
)]
if
len
(
cts
)
==
1
:
...
...
@@ -378,13 +388,18 @@ class TaggableManager(RelatedField, Field):
else
:
alias_to_join
=
lhs_alias
extra_col
=
self
.
through
.
_meta
.
get_field_by_name
(
'content_type'
)[
0
]
.
column
content_type_ids
=
[
ContentType
.
objects
.
get_for_model
(
subclass
)
.
pk
for
subclass
in
_get_subclasses
(
self
.
model
)]
content_type_ids
=
[
ContentType
.
objects
.
get_for_model
(
subclass
)
.
pk
for
subclass
in
_get_subclasses
(
self
.
model
)]
if
len
(
content_type_ids
)
==
1
:
content_type_id
=
content_type_ids
[
0
]
extra_where
=
" AND
%
s.
%
s =
%%
s"
%
(
qn
(
alias_to_join
),
qn
(
extra_col
))
extra_where
=
" AND
%
s.
%
s =
%%
s"
%
(
qn
(
alias_to_join
),
qn
(
extra_col
))
params
=
[
content_type_id
]
else
:
extra_where
=
" AND
%
s.
%
s IN (
%
s)"
%
(
qn
(
alias_to_join
),
qn
(
extra_col
),
','
.
join
([
'
%
s'
]
*
len
(
content_type_ids
)))
extra_where
=
" AND
%
s.
%
s IN (
%
s)"
%
(
qn
(
alias_to_join
),
qn
(
extra_col
),
','
.
join
([
'
%
s'
]
*
len
(
content_type_ids
)))
params
=
content_type_ids
return
extra_where
,
params
...
...
@@ -461,7 +476,7 @@ def _get_subclasses(model):
for
f
in
model
.
_meta
.
get_all_field_names
():
field
=
model
.
_meta
.
get_field_by_name
(
f
)[
0
]
if
(
isinstance
(
field
,
RelatedObject
)
and
getattr
(
field
.
field
.
rel
,
"parent_link"
,
None
)):
getattr
(
field
.
field
.
rel
,
"parent_link"
,
None
)):
subclasses
.
extend
(
_get_subclasses
(
field
.
model
))
return
subclasses
...
...
taggit/migrations/0001_initial.py
View file @
ed8af524
#
encoding: utf8
#
-*- coding: utf-8 -*-
from
__future__
import
unicode_literals
from
django.db
import
models
,
migrations
...
...
@@ -27,9 +28,9 @@ class Migration(migrations.Migration):
name
=
'TaggedItem'
,
fields
=
[
(
'id'
,
models
.
AutoField
(
verbose_name
=
'ID'
,
serialize
=
False
,
auto_created
=
True
,
primary_key
=
True
)),
(
'tag'
,
models
.
ForeignKey
(
to
=
'taggit.Tag'
,
to_field
=
'id'
)),
(
'object_id'
,
models
.
IntegerField
(
verbose_name
=
'Object id'
,
db_index
=
True
)),
(
'content_type'
,
models
.
ForeignKey
(
to
=
'contenttypes.ContentType'
,
to_field
=
'id'
,
verbose_name
=
'Content type'
)),
(
'content_type'
,
models
.
ForeignKey
(
related_name
=
'taggit_taggeditem_tagged_items'
,
verbose_name
=
'Content type'
,
to
=
'contenttypes.ContentType'
)),
(
'tag'
,
models
.
ForeignKey
(
related_name
=
'taggit_taggeditem_items'
,
to
=
'taggit.Tag'
)),
],
options
=
{
'verbose_name'
:
'Tagged Item'
,
...
...
taggit/models.py
View file @
ed8af524
from
__future__
import
unicode_literals
from
django.contrib.contenttypes.models
import
ContentType
from
django.db
import
IntegrityError
,
models
,
transaction
from
django.db.models.query
import
QuerySet
from
django.template.defaultfilters
import
slugify
as
default_slugify
from
django.utils.encoding
import
python_2_unicode_compatible
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.utils.translation
import
ugettext
try
:
from
django.contrib.contenttypes.fields
import
GenericForeignKey
except
ImportError
:
# django < 1.7
from
django.contrib.contenttypes.generic
import
GenericForeignKey
from
django.db
import
models
,
IntegrityError
,
transaction
from
django.db.models.query
import
QuerySet
from
django.template.defaultfilters
import
slugify
as
default_slugify
from
django.utils.translation
import
ugettext_lazy
as
_
,
ugettext
from
django.utils.encoding
import
python_2_unicode_compatible
try
:
...
...
@@ -59,7 +61,7 @@ class TagBase(models.Model):
except
IntegrityError
:
pass
# Now try to find existing slugs with similar names
slugs
=
set
(
Tag
.
objects
.
filter
(
slug__startswith
=
self
.
slug
)
\
slugs
=
set
(
Tag
.
objects
.
filter
(
slug__startswith
=
self
.
slug
)
.
values_list
(
'slug'
,
flat
=
True
))
i
=
1
while
True
:
...
...
@@ -145,7 +147,7 @@ class GenericTaggedItemBase(ItemBase):
content_object
=
GenericForeignKey
()
class
Meta
:
abstract
=
True
abstract
=
True
@classmethod
def
lookup_kwargs
(
cls
,
instance
):
...
...
taggit/utils.py
View file @
ed8af524
from
__future__
import
unicode_literals
from
django.utils
import
six
from
django.utils.encoding
import
force_text
from
django.utils.functional
import
wraps
from
django.utils
import
six
def
parse_tags
(
tagstring
):
...
...
taggit/views.py
View file @
ed8af524
...
...
@@ -4,7 +4,7 @@ from django.contrib.contenttypes.models import ContentType
from
django.shortcuts
import
get_object_or_404
from
django.views.generic.list
import
ListView
from
taggit.models
import
Tag
gedItem
,
Tag
from
taggit.models
import
Tag
,
TaggedItem
def
tagged_object_list
(
request
,
slug
,
queryset
,
**
kwargs
):
...
...
@@ -18,4 +18,3 @@ def tagged_object_list(request, slug, queryset, **kwargs):
kwargs
[
"extra_context"
]
=
{}
kwargs
[
"extra_context"
][
"tag"
]
=
tag
return
ListView
.
as_view
(
request
,
qs
,
**
kwargs
)
tests/forms.py
View file @
ed8af524
from
__future__
import
unicode_literals
,
absolute_import
from
__future__
import
absolute_import
,
unicode_literals
from
django
import
forms
,
VERSION
from
.models
import
Food
,
DirectFood
,
CustomPKFood
,
OfficialFood
from
.models
import
CustomPKFood
,
DirectFood
,
Food
,
OfficialFood
fields
=
None
if
VERSION
>=
(
1
,
6
):
if
VERSION
>=
(
1
,
6
):
fields
=
'__all__'
...
...
tests/migrations/0001_initial.py
View file @
ed8af524
...
...
@@ -54,7 +54,7 @@ class Migration(migrations.Migration):
migrations
.
CreateModel
(
name
=
'CustomPKHousePet'
,
fields
=
[
(
'custompkpet_ptr'
,
models
.
OneToOneField
(
auto_created
=
True
,
primary_key
=
True
,
serialize
=
False
,
to
=
'tests.CustomPKPet'
)),
(
'custompkpet_ptr'
,
models
.
OneToOneField
(
parent_link
=
True
,
auto_created
=
True
,
primary_key
=
True
,
serialize
=
False
,
to
=
'tests.CustomPKPet'
)),
(
'trained'
,
models
.
BooleanField
(
default
=
False
)),
],
options
=
{
...
...
@@ -84,7 +84,7 @@ class Migration(migrations.Migration):
migrations
.
CreateModel
(
name
=
'DirectHousePet'
,
fields
=
[
(
'directpet_ptr'
,
models
.
OneToOneField
(
auto_created
=
True
,
primary_key
=
True
,
serialize
=
False
,
to
=
'tests.DirectPet'
)),
(
'directpet_ptr'
,
models
.
OneToOneField
(
parent_link
=
True
,
auto_created
=
True
,
primary_key
=
True
,
serialize
=
False
,
to
=
'tests.DirectPet'
)),
(
'trained'
,
models
.
BooleanField
(
default
=
False
)),
],
options
=
{
...
...
@@ -155,7 +155,7 @@ class Migration(migrations.Migration):
migrations
.
CreateModel
(
name
=
'OfficialHousePet'
,
fields
=
[
(
'officialpet_ptr'
,
models
.
OneToOneField
(
auto_created
=
True
,
primary_key
=
True
,
serialize
=
False
,
to
=
'tests.OfficialPet'
)),
(
'officialpet_ptr'
,
models
.
OneToOneField
(
parent_link
=
True
,
auto_created
=
True
,
primary_key
=
True
,
serialize
=
False
,
to
=
'tests.OfficialPet'
)),
(
'trained'
,
models
.
BooleanField
(
default
=
False
)),
],
options
=
{
...
...
@@ -180,8 +180,8 @@ class Migration(migrations.Migration):
fields
=
[
(
'id'
,
models
.
AutoField
(
verbose_name
=
'ID'
,
serialize
=
False
,
auto_created
=
True
,
primary_key
=
True
)),
(
'object_id'
,
models
.
IntegerField
(
verbose_name
=
'Object id'
,
db_index
=
True
)),
(
'content_type'
,
models
.
ForeignKey
(
verbose_name
=
'Content type'
,
to
=
'contenttypes.ContentType'
)),
(
'tag'
,
models
.
ForeignKey
(
to
=
'tests.OfficialTag'
)),
(
'content_type'
,
models
.
ForeignKey
(
related_name
=
'tests_officialthroughmodel_tagged_items'
,
verbose_name
=
'Content type'
,
to
=
'contenttypes.ContentType'
)),
(
'tag'
,
models
.
ForeignKey
(
related_name
=
'tagged_items'
,
to
=
'tests.OfficialTag'
)),
],
options
=
{
'abstract'
:
False
,
...
...
@@ -201,6 +201,30 @@ class Migration(migrations.Migration):
preserve_default
=
True
,
),
migrations
.
CreateModel
(
name
=
'Parent'
,
fields
=
[
(
'id'
,
models
.
AutoField
(
verbose_name
=
'ID'
,
serialize
=
False
,
auto_created
=
True
,
primary_key
=
True
)),
],
options
=
{
},
bases
=
(
models
.
Model
,),
),
migrations
.
CreateModel
(
name
=
'Child'
,
fields
=
[
(
'parent_ptr'
,
models
.
OneToOneField
(
parent_link
=
True
,
auto_created
=
True
,
primary_key
=
True
,
serialize
=
False
,
to
=
'tests.Parent'
)),
],
options
=
{
},
bases
=
(
'tests.parent'
,),
),
migrations
.
AddField
(
model_name
=
'parent'
,
name
=
'tags'
,
field
=
taggit
.
managers
.
TaggableManager
(
to
=
'taggit.Tag'
,
through
=
'taggit.TaggedItem'
,
help_text
=
'A comma-separated list of tags.'
,
verbose_name
=
'Tags'
),
preserve_default
=
True
,
),
migrations
.
CreateModel
(
name
=
'Pet'
,
fields
=
[
(
'id'
,
models
.
AutoField
(
verbose_name
=
'ID'
,
serialize
=
False
,
auto_created
=
True
,
primary_key
=
True
)),
...
...
@@ -213,7 +237,7 @@ class Migration(migrations.Migration):
migrations
.
CreateModel
(
name
=
'HousePet'
,
fields
=
[
(
'pet_ptr'
,
models
.
OneToOneField
(
auto_created
=
True
,
primary_key
=
True
,
serialize
=
False
,
to
=
'tests.Pet'
)),
(
'pet_ptr'
,
models
.
OneToOneField
(
parent_link
=
True
,
auto_created
=
True
,
primary_key
=
True
,
serialize
=
False
,
to
=
'tests.Pet'
)),
(
'trained'
,
models
.
BooleanField
(
default
=
False
)),
],
options
=
{
...
...
@@ -262,7 +286,7 @@ class Migration(migrations.Migration):
migrations
.
AddField
(
model_name
=
'taggedcustompkfood'
,
name
=
'tag'
,
field
=
models
.
ForeignKey
(
to
=
'taggit.Tag'
),
field
=
models
.
ForeignKey
(
related_name
=
'tests_taggedcustompkfood_items'
,
to
=
'taggit.Tag'
),
preserve_default
=
True
,
),
migrations
.
CreateModel
(
...
...
@@ -290,7 +314,7 @@ class Migration(migrations.Migration):
migrations
.
AddField
(
model_name
=
'taggedcustompkpet'
,
name
=
'tag'
,
field
=
models
.
ForeignKey
(
to
=
'taggit.Tag'
),
field
=
models
.
ForeignKey
(
related_name
=
'tests_taggedcustompkpet_items'
,
to
=
'taggit.Tag'
),
preserve_default
=
True
,
),
migrations
.
CreateModel
(
...
...
@@ -318,7 +342,7 @@ class Migration(migrations.Migration):
migrations
.
AddField
(
model_name
=
'taggedfood'
,
name
=
'tag'
,
field
=
models
.
ForeignKey
(
to
=
'taggit.Tag'
),
field
=
models
.
ForeignKey
(
related_name
=
'tests_taggedfood_items'
,
to
=
'taggit.Tag'
),
preserve_default
=
True
,
),
migrations
.
CreateModel
(
...
...
@@ -346,7 +370,7 @@ class Migration(migrations.Migration):
migrations
.
AddField
(
model_name
=
'taggedpet'
,
name
=
'tag'
,
field
=
models
.
ForeignKey
(
to
=
'taggit.Tag'
),
field
=
models
.
ForeignKey
(
related_name
=
'tests_taggedpet_items'
,
to
=
'taggit.Tag'
),
preserve_default
=
True
,
),
migrations
.
CreateModel
(
...
...
@@ -374,7 +398,7 @@ class Migration(migrations.Migration):
migrations
.
AddField
(
model_name
=
'through1'
,
name
=
'tag'
,
field
=
models
.
ForeignKey
(
to
=
'taggit.Tag'
),
field
=
models
.
ForeignKey
(
related_name
=
'tests_through1_items'
,
to
=
'taggit.Tag'
),
preserve_default
=
True
,
),
migrations
.
CreateModel
(
...
...
@@ -402,7 +426,7 @@ class Migration(migrations.Migration):
migrations
.
AddField
(
model_name
=
'through2'
,
name
=
'tag'
,
field
=
models
.
ForeignKey
(
to
=
'taggit.Tag'
),
field
=
models
.
ForeignKey
(
related_name
=
'tests_through2_items'
,
to
=
'taggit.Tag'
),
preserve_default
=
True
,
),
migrations
.
CreateModel
(
...
...
@@ -410,8 +434,8 @@ class Migration(migrations.Migration):
fields
=
[
(
'id'
,
models
.
AutoField
(
verbose_name
=
'ID'
,
serialize
=
False
,
auto_created
=
True
,
primary_key
=
True
)),
(
'object_id'
,
models
.
IntegerField
(
verbose_name
=
'Object id'
,
db_index
=
True
)),
(
'content_type'
,
models
.
ForeignKey
(
verbose_name
=
'Content type'
,
to
=
'contenttypes.ContentType'
)),
(
'tag'
,
models
.
ForeignKey
(
to
=
'taggit.Tag'
)),
(
'content_type'
,
models
.
ForeignKey
(
related_name
=
'tests_throughgfk_tagged_items'
,
verbose_name
=
'Content type'
,
to
=
'contenttypes.ContentType'
)),
(
'tag'
,
models
.
ForeignKey
(
related_name
=
'tagged_items'
,
to
=
'taggit.Tag'
)),
],
options
=
{
'abstract'
:
False
,
...
...
tests/models.py
View file @
ed8af524
...
...
@@ -4,8 +4,8 @@ from django.db import models
from
django.utils.encoding
import
python_2_unicode_compatible
from
taggit.managers
import
TaggableManager
from
taggit.models
import
(
TaggedItemBase
,
GenericTaggedItem
Base
,
TaggedItem
,
TagBase
,
Tag
)
from
taggit.models
import
(
GenericTaggedItemBase
,
Tag
,
Tag
Base
,
TaggedItem
,
TaggedItemBase
)
# Ensure that two TaggableManagers with custom through model are allowed.
...
...
@@ -192,3 +192,11 @@ class CustomManager(models.Model):
pass
tags
=
TaggableManager
(
manager
=
Foo
)
class
Parent
(
models
.
Model
):
tags
=
TaggableManager
()
class
Child
(
Parent
):
pass
tests/tests.py
View file @
ed8af524
from
__future__
import
unicode_literals
,
absolute_import
from
__future__
import
absolute_import
,
unicode_literals
from
unittest
import
TestCase
as
UnitTestCase
try
:
from
unittest
import
skipIf
,
skipUnless
except
:
from
django.utils.unittest
import
skipIf
,
skipUnless
import
django
from
django.conf
import
settings
from
django.core.exceptions
import
ImproperlyConfigured
,
ValidationError
from
django.contrib.contenttypes.models
import
ContentType
from
django.core
import
serializers
from
django.
db
import
connection
from
django.
core.exceptions
import
ImproperlyConfigured
,
ValidationError
from
django.test
import
TestCase
,
TransactionTestCase
from
django.utils
import
six
from
django.utils.encoding
import
force_text
from
django.contrib.contenttypes.models
import
ContentType
from
.forms
import
CustomPKFoodForm
,
DirectFoodForm
,
FoodForm
,
OfficialFoodForm
from
.models
import
(
Article
,
Child
,
CustomManager
,
CustomPKFood
,
CustomPKHousePet
,
CustomPKPet
,
DirectFood
,
DirectHousePet
,
DirectPet
,
Food
,
HousePet
,
Movie
,
OfficialFood
,
OfficialHousePet
,
OfficialPet
,
OfficialTag
,
OfficialThroughModel
,
Pet
,
Photo
,
TaggedCustomPKFood
,
TaggedCustomPKPet
,
TaggedFood
,
TaggedPet
)
from
taggit.managers
import
TaggableManager
,
_TaggableManager
,
_model_name
from
taggit.managers
import
_model_name
,
_TaggableManager
,
TaggableManager
from
taggit.models
import
Tag
,
TaggedItem
from
.forms
import
(
FoodForm
,
DirectFoodForm
,
CustomPKFoodForm
,
OfficialFoodForm
)
from
.models
import
(
Food
,
Pet
,
HousePet
,
DirectFood
,
DirectPet
,
DirectHousePet
,
TaggedFood
,
CustomPKFood
,
CustomPKPet
,
CustomPKHousePet
,
TaggedCustomPKFood
,
OfficialFood
,
OfficialPet
,
OfficialHousePet
,
OfficialThroughModel
,
OfficialTag
,
Photo
,
Movie
,
Article
,
CustomManager
)
from
taggit.utils
import
parse_tags
,
edit_string_for_tag
s
from
taggit.utils
import
edit_string_for_tags
,
parse_tags
try
:
from
unittest
import
skipIf
,
skipUnless
except
ImportError
:
from
django.utils.unittest
import
skipIf
,
skipUnles
s
class
BaseTaggingTest
(
object
):
...
...
@@ -87,6 +88,14 @@ class TagModelTestCase(BaseTaggingTransactionTestCase):
"category-awesome-1"
],
attr
=
"slug"
)
def
test_integers
(
self
):
"""Adding an integer as a tag should raise a ValueError (#237)."""
apple
=
self
.
food_model
.
objects
.
create
(
name
=
"apple"
)
with
self
.
assertRaisesRegexp
(
ValueError
,
(
r"Cannot add 1 \(<(type|class) 'int'>\). "
r"Expected <class 'django.db.models.base.ModelBase'> or str."
)):
apple
.
tags
.
add
(
1
)
class
TagModelDirectTestCase
(
TagModelTestCase
):
food_model
=
DirectFood
tag_model
=
Tag
...
...
@@ -109,7 +118,7 @@ class TaggableManagerTestCase(BaseTaggingTestCase):
def
test_add_tag
(
self
):
apple
=
self
.
food_model
.
objects
.
create
(
name
=
"apple"
)
self
.
assertEqual
(
list
(
apple
.
tags
.
all
()),
[])
self
.
assertEqual
(
list
(
self
.
food_model
.
tags
.
all
()),
[])
self
.
assertEqual
(
list
(
self
.
food_model
.
tags
.
all
()),
[])
apple
.
tags
.
add
(
'green'
)
self
.
assert_tags_equal
(
apple
.
tags
.
all
(),
[
'green'
])
...
...
@@ -150,7 +159,7 @@ class TaggableManagerTestCase(BaseTaggingTestCase):
# make sure we don't double create.
# + 12 on Django 1.6 for save points.
queries
=
22
if
django
.
VERSION
<
(
1
,
6
):
if
django
.
VERSION
<
(
1
,
6
):
queries
-=
12
self
.
assertNumQueries
(
queries
,
apple
.
tags
.
add
,
"red"
,
"delicious"
,
"green"
)
...
...
@@ -160,7 +169,7 @@ class TaggableManagerTestCase(BaseTaggingTestCase):
# make sure we dont't double create.
# + 4 on Django 1.6 for save points.
queries
=
9
if
django
.
VERSION
<
(
1
,
6
):
if
django
.
VERSION
<
(
1
,
6
):
queries
-=
4
self
.
assertNumQueries
(
queries
,
pear
.
tags
.
add
,
"green"
,
"delicious"
)
...
...
@@ -181,7 +190,7 @@ class TaggableManagerTestCase(BaseTaggingTestCase):
def
test_delete_bulk
(
self
):
apple
=
self
.
food_model
.
objects
.
create
(
name
=
"apple"
)
kitty
=
self
.
pet_model
.
objects
.
create
(
pk
=
apple
.
pk
,
name
=
"kitty"
)
kitty
=
self
.
pet_model
.
objects
.
create
(
pk
=
apple
.
pk
,
name
=
"kitty"
)
apple
.
tags
.
add
(
"red"
,
"delicious"
,
"fruit"
)
kitty
.
tags
.
add
(
"feline"
)
...
...
@@ -222,9 +231,9 @@ class TaggableManagerTestCase(BaseTaggingTestCase):
pks
=
self
.
pet_model
.
objects
.
filter
(
tags__name__in
=
[
"fuzzy"
])
model_name
=
self
.
pet_model
.
__name__
self
.
assertQuerysetEqual
(
pks
,
[
'<{0}: kitty>'
.
format
(
model_name
),
'<{0}: cat>'
.
format
(
model_name
)],
ordered
=
False
)
[
'<{0}: kitty>'
.
format
(
model_name
),
'<{0}: cat>'
.
format
(
model_name
)],
ordered
=
False
)
def
test_lookup_bulk
(
self
):
apple
=
self
.
food_model
.
objects
.
create
(
name
=
"apple"
)
...
...
@@ -254,14 +263,14 @@ class TaggableManagerTestCase(BaseTaggingTestCase):
pear
=
self
.
food_model
.
objects
.
create
(
name
=
"pear"
)
pear
.
tags
.
add
(
"green"
,
"delicious"
)
guava
=
self
.
food_model
.
objects
.
create
(
name
=
"guava"
)
self
.
food_model
.
objects
.
create
(
name
=
"guava"
)
pks
=
self
.
food_model
.
objects
.
exclude
(
tags__name__in
=
[
"red"
])
model_name
=
self
.
food_model
.
__name__
self
.
assertQuerysetEqual
(
pks
,
[
'<{0}: pear>'
.
format
(
model_name
),
'<{0}: guava>'
.
format
(
model_name
)],
ordered
=
False
)
[
'<{0}: pear>'
.
format
(
model_name
),
'<{0}: guava>'
.
format
(
model_name
)],
ordered
=
False
)
def
test_similarity_by_tag
(
self
):
"""Test that pears are more similar to apples than watermelons"""
...
...
@@ -293,8 +302,8 @@ class TaggableManagerTestCase(BaseTaggingTestCase):
'
%
s__name'
%
_model_name
(
self
.
pet_model
):
'Spot'
}
self
.
assert_tags_equal
(
self
.
tag_model
.
objects
.
filter
(
**
lookup_kwargs
),
[
'scary'
]
self
.
tag_model
.
objects
.
filter
(
**
lookup_kwargs
),
[
'scary'
]
)
def
test_taggeditem_unicode
(
self
):
...
...
@@ -492,7 +501,7 @@ class TagStringParseTestCase(UnitTestCase):
self
.
assertEqual
(
parse_tags
(
',one two'
),
[
'one two'
])
self
.
assertEqual
(
parse_tags
(
',one two three'
),
[
'one two three'
])
self
.
assertEqual
(
parse_tags
(
'a-one, a-two and a-three'
),
[
'a-one'
,
'a-two and a-three'
])
[
'a-one'
,
'a-two and a-three'
])
def
test_with_double_quoted_multiple_words
(
self
):
"""
...
...
@@ -504,7 +513,7 @@ class TagStringParseTestCase(UnitTestCase):
self
.
assertEqual
(
parse_tags
(
'"one two three'
),
[
'one'
,
'three'
,
'two'
])
self
.
assertEqual
(
parse_tags
(
'"one two"'
),
[
'one two'
])
self
.
assertEqual
(
parse_tags
(
'a-one "a-two and a-three"'
),
[
'a-one'
,
'a-two and a-three'
])
[
'a-one'
,
'a-two and a-three'
])
def
test_with_no_loose_commas
(
self
):
"""
...
...
@@ -523,9 +532,9 @@ class TagStringParseTestCase(UnitTestCase):
Double quotes can contain commas
"""
self
.
assertEqual
(
parse_tags
(
'a-one "a-two, and a-three"'
),
[
'a-one'
,
'a-two, and a-three'
])
[
'a-one'
,
'a-two, and a-three'
])
self
.
assertEqual
(
parse_tags
(
'"two", one, one, two, "one"'
),
[
'one'
,
'two'
])
[
'one'
,
'two'
])
def
test_with_naughty_input
(
self
):
"""
...
...
@@ -540,7 +549,7 @@ class TagStringParseTestCase(UnitTestCase):
self
.
assertEqual
(
parse_tags
(
',,,,,,'
),
[])
self
.
assertEqual
(
parse_tags
(
'",",",",",",","'
),
[
','
])
self
.
assertEqual
(
parse_tags
(
'a-one "a-two" and "a-three'
),
[
'a-one'
,
'a-three'
,
'a-two'
,
'and'
])
[
'a-one'
,
'a-three'
,
'a-two'
,
'and'
])
def
test_recreation_of_tag_list_string_representations
(
self
):
plain
=
Tag
.
objects
.
create
(
name
=
'plain'
)
...
...
@@ -571,3 +580,20 @@ class SouthSupportTests(TestCase):
except
ImproperlyConfigured
as
e
:
exception
=
e
self
.
assertIn
(
"SOUTH_MIGRATION_MODULES"
,
exception
.
args
[
0
])
class
InheritedPrefetchTests
(
TestCase
):
def
test_inherited_tags_with_prefetch
(
self
):
child
=
Child
()
child
.
save
()
child
.
tags
.
add
(
'tag 1'
,
'tag 2'
,
'tag 3'
,
'tag 4'
)
child
=
Child
.
objects
.
get
()
no_prefetch_tags
=
child
.
tags
.
all
()
self
.
assertEquals
(
4
,
no_prefetch_tags
.
count
())
child
=
Child
.
objects
.
prefetch_related
(
'tags'
)
.
get
()
prefetch_tags
=
child
.
tags
.
all
()
self
.
assertEquals
(
4
,
prefetch_tags
.
count
())
self
.
assertEquals
(
set
([
t
.
name
for
t
in
no_prefetch_tags
]),
set
([
t
.
name
for
t
in
prefetch_tags
]))
tox.ini
View file @
ed8af524
...
...
@@ -13,7 +13,7 @@ deps17 =
https://github.com/django/django/archive/stable/1.7.x.zip
#egg=django
commands
=
python
./runtests.py
python
./runtests.py
{posargs}
[testenv:py26-1.4.x]
...
...
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