GithubHelp home page GithubHelp logo

jazzband / django-taggit Goto Github PK

View Code? Open in Web Editor NEW
3.3K 65.0 623.0 1.06 MB

Simple tagging for django

Home Page: https://django-taggit.readthedocs.io

License: BSD 3-Clause "New" or "Revised" License

Python 99.94% HTML 0.06%

django-taggit's Introduction

django-taggit

Jazzband Supported Python versions Supported Django versions GitHub Actions https://codecov.io/gh/jazzband/django-taggit/coverage.svg?branch=master

This is a Jazzband project. By contributing you agree to abide by the Contributor Code of Conduct and follow the guidelines.

django-taggit a simpler approach to tagging with Django. Add "taggit" to your INSTALLED_APPS then just add a TaggableManager to your model and go:

from django.db import models

from taggit.managers import TaggableManager


class Food(models.Model):
    # ... fields here

    tags = TaggableManager()

Then you can use the API like so:

>>> apple = Food.objects.create(name="apple")
>>> apple.tags.add("red", "green", "delicious")
>>> apple.tags.all()
[<Tag: red>, <Tag: green>, <Tag: delicious>]
>>> apple.tags.remove("green")
>>> apple.tags.all()
[<Tag: red>, <Tag: delicious>]
>>> Food.objects.filter(tags__name__in=["red"])
[<Food: apple>, <Food: cherry>]

Tags will show up for you automatically in forms and the admin.

django-taggit requires Django 3.2 or greater.

For more info check out the documentation. And for questions about usage or development you can create an issue on Github (if your question is about usage please add the question tag).

django-taggit's People

Contributors

9nix00 avatar alex avatar apollo13 avatar atombrella avatar auvipy avatar blueyed avatar carljm avatar collinanderson avatar entequak avatar frankwiles avatar frewsxcv avatar hesoka05 avatar hramezani avatar idanz avatar izquierdo avatar jdufresne avatar jezdez avatar jwhitlock avatar kaedroho avatar kminkov avatar mx-moth avatar nemesifier avatar null-none avatar pre-commit-ci[bot] avatar prydie avatar rtpg avatar sergeyklay avatar soulshake avatar steverecio avatar xordoquy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-taggit's Issues

m2m queries failing

error:

'TaggableManager' object has no attribute 'm2m_target_field_name'

from:

django.db.models.sql.query.py line 1286

steps to recreate:

models:

  • User - from django.contrib.auth.models
  • Link - has foreign key for User and has a field tags (TaggableManager)

code:

u = User.objects.get(pk=1)
t = Link.objects.filter(user=u).values_list('tags__name', flat=true).distinct().order_by('tags__name')

Issue Adding Multiple TaggableManagers to a Model (or) through parameter does not respect related_name

I can't get a custom through field to validate with multiple TaggableManagers on a Model

# -- models.py
from django.db import models
from taggit.managers import TaggableManager
from taggit.models import Tag

class TaggedSkills(models.Model):
   a = models.ForeignKey("ModelA")
   tag = models.ForeignKey(Tag, related_name="%(class)s_skills")

class TaggedInterests(models.Model):
   a = models.ForeignKey("ModelA")
   tag = models.ForeignKey(Tag, related_name="%(class)s_interests")

class TaggedLimitations(models.Model):
   a = models.ForeignKey("ModelA")
   tag = models.ForeignKey(Tag, related_name="%(class)s_limitations")

class ModelA(models.Model):

   skills = TaggableManager(through=TaggedSkills)
   interests = TaggableManager(through=TaggedInterests)
   limitations = TaggableManager(through=TaggedLimitations)

Running

$ manage.py validate
Error: One or more models did not validate:
a.modela: Accessor for m2m field 'skills' clashes with related m2m field 'Tag.modela_set'. Add a related_name argument to the definition for 'skills'.
a.modela: Accessor for m2m field 'skills' clashes with related m2m field 'Tag.modela_set'. Add a related_name argument to the definition for 'skills'.
a.modela: Accessor for m2m field 'interests' clashes with related m2m field 'Tag.modela_set'. Add a related_name argument to the definition for 'interests'.
a.modela: Accessor for m2m field 'interests' clashes with related m2m field 'Tag.modela_set'. Add a related_name argument to the definition for 'interests'.
a.modela: Accessor for m2m field 'limitations' clashes with related m2m field 'Tag.modela_set'. Add a related_name argument to the definition for 'limitations'.
a.modela: Accessor for m2m field 'limitations' clashes with related m2m field 'Tag.modela_set'. Add a related_name argument to the definition for 'limitations'.

similar_objects query slow in MySQL for large data sets (suggested fix included)

I've created a branch (https://github.com/joshmaker/django-taggit) that resolves performance issues that we were having on our MySQL database when making similar_object queries.

First, I added a parameter that allows users to pass a limit to the query.

Having to pull thousands of tagged items was a major performance bottle neck.

Second, I broke the actual query itself into two separate queries.

The old method with a subquery prevented MySQL from using an index and resulted in a much slower query. (In my tests, one 140ms query vs two 5ms queries)

Attribute Error on models with ManyToMany or GenericRelation

If a model has a ManyToMany or a GenericRelationship an error is thrown. It took me a while to figure out what was throwing it as I was messing with taggit on an existing large project. Once I found it I tested it on a brand new application. Adding either of the fields makes it throw the following error. I'll be working on a fix after lunch but just a heads up.

Unhandled exception in thread started by <function inner_run at 0x1007b2938>
Traceback (most recent call last):
  File "/Library/Python/2.6/site-packages/django/core/management/commands/runserver.py", line 48, in inner_run
    self.validate(display_num_errors=True)
  File "/Library/Python/2.6/site-packages/django/core/management/base.py", line 249, in validate
    num_errors = get_validation_errors(s, app)
  File "/Library/Python/2.6/site-packages/django/core/management/validation.py", line 28, in get_validation_errors
    for (app_name, error) in get_app_errors().items():
  File "/Library/Python/2.6/site-packages/django/db/models/loading.py", line 131, in get_app_errors
    self._populate()
  File "/Library/Python/2.6/site-packages/django/db/models/loading.py", line 58, in _populate
    self.load_app(app_name, True)
  File "/Library/Python/2.6/site-packages/django/db/models/loading.py", line 74, in load_app
    models = import_module('.models', app_name)
  File "/Library/Python/2.6/site-packages/django/utils/importlib.py", line 35, in import_module
    __import__(name)
  File "/Users/maple/Projects/test/food/models.py", line 6, in <module>
    class Fruit(models.Model):
  File "/Library/Python/2.6/site-packages/django/db/models/base.py", line 92, in __new__
    new_class.add_to_class(obj_name, obj)
  File "/Library/Python/2.6/site-packages/django/db/models/base.py", line 213, in add_to_class
    value.contribute_to_class(cls, name)
  File "/Library/Python/2.6/site-packages/taggit/managers.py", line 42, in contribute_to_class
    cls._meta.add_field(self)
  File "/Library/Python/2.6/site-packages/django/db/models/options.py", line 150, in add_field
    self.local_many_to_many.insert(bisect(self.local_many_to_many, field), field)
  File "/Library/Python/2.6/site-packages/django/db/models/fields/__init__.py", line 102, in __cmp__
    return cmp(self.creation_counter, other.creation_counter)
AttributeError: 'TaggableManager' object has no attribute 'creation_counter'

DjangoUnicodeDecodeError when deleting tag

Deleting tag from admin causes DjangoUnicodeDecodeError : 'ascii' codec can't decode byte 0xc4 in position 5: ordinal not in range(128). You passed in <TaggedItem: [Bad Unicode data]> (<class 'taggit.models.TaggedItem'>)

Changing 36 line of taggit/models.py from:
return "%s tagged with %s" % (self.content_object, self.tag)
to:
return u"%s tagged with %s" % (self.content_object, self.tag)
solves this error.

attname attribute

I'm getting AttributeError: 'TaggableManager' object has no attribute 'attname' on all my models using a TaggableManager while trying to migrate an app to south. You seen this?

South doesn't know how to handle tags

Because of the way TaggableManager() contributes_to_class, it's causing migrations to fail whenever it's added to an app. Using south 0.6.2, also failed using development version.

cleifer@cleifer-laptop:~/blah/$ ./manage.py startmigration myapp add_some_status --auto

Parsing field: content
Parsing field: status
Parsing field: pub_date
Parsing field: comment_status
Parsing field: tags
Parsing field: content
Parsing field: status
Parsing field: pub_date
Parsing field: comment_status
Parsing field: content
Parsing field: status
Parsing field: pub_date
Parsing field: comment_status
Parsing field: title
Parsing field: content
Parsing field: status
Parsing field: pub_date
Parsing field: comment_status
Parsing field: title
Parsing field: content
Parsing field: status
Parsing field: pub_date
Parsing field: comment_status

  • Added field 'posts.basepost.tags'
    Parsing field: content
    Parsing field: status
    Parsing field: pub_date
    Parsing field: comment_status
    Traceback (most recent call last):
    File "./manage.py", line 11, in
    execute_manager(settings)
    File "/home/cleifer/pypath/django/core/management/init.py", line 362, in execute_manager
    utility.execute()
    File "/home/cleifer/pypath/django/core/management/init.py", line 303, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
    File "/home/cleifer/pypath/django/core/management/base.py", line 195, in run_from_argv
    self.execute(_args, *_options.dict)
    File "/home/cleifer/pypath/django/core/management/base.py", line 222, in execute
    output = self.handle(_args, *_options)
    File "/home/cleifer/projects/enchilada/worldonline/thirdparty/south/management/commands/startmigration.py", line 389, in handle
    modelsinspector.get_model_fields(model)[field_name])
    KeyError: 'tags'

exclude filter not supported

It's currently not possible to create a queryset which excludes models with given tags. I've fixed it with a simple patch but I'm not sure if it is the right way to do it.

just add
if hasattr(value, 'prepare'):
return value.prepare()
if hasattr(value, '_prepare'):
return value._prepare()

to the get_prep_lookup method in TaggableManager after the first if block. Tested with Django 1.2.1

TaggableManager should include a Field parameter

With custom tagging, one often needs to build a customized field to display the form elements. One should be able to customize how TaggableManager is displayed in a form without having to subclass TaggableManager.

'TaggableManager' object has no attribute 'bulk_related_objects'

When calling .delete() on an object with a tags = TaggableManager(blank=True, through=TaggedModel) I'm getting the error in the title of this issue.

This is on Django trunk and taggit up to commit b6b290. Afterwards I don't see anything related to this.

Let me know if I can do anything to help.

Ready for a release?

I use this project in another and it would be cool if you make a release (or just tag it) when you think it's rather stable. I dont want to use the always-latest master so I'm using the latest commit:

-e git://github.com/alex/django-taggit.git@c565907#egg=django-taggit

Django r14507 breaks taggit

Django r14507(http://code.djangoproject.com/changeset/14507) introduced changes to generic relations, which cause taggit to break.

"'TaggableManager' object has no attribute 'bulk_related_objects'"

Traceback:
Traceback:
File "/Users/knutin/git/foo/src/django/django/core/handlers/base.py" in get_response

  1.                     response = callback(request, _callback_args, *_callback_kwargs)
    
    File "/Users/knutin/git/foo/src/django/django/contrib/admin/options.py" in wrapper
  2.             return self.admin_site.admin_view(view)(_args, *_kwargs)
    
    File "/Users/knutin/git/foo/src/django/django/utils/decorators.py" in _wrapped_view
  3.                 response = view_func(request, _args, *_kwargs)
    
    File "/Users/knutin/git/foo/src/django/django/views/decorators/cache.py" in _wrapped_view_func
  4.     response = view_func(request, _args, *_kwargs)
    
    File "/Users/knutin/git/foo/src/django/django/contrib/admin/sites.py" in inner
  5.         return view(request, _args, *_kwargs)
    
    File "/Users/knutin/git/foo/src/django/django/utils/decorators.py" in _wrapper
  6.         return bound_func(_args, *_kwargs)
    
    File "/Users/knutin/git/foo/src/django/django/utils/decorators.py" in _wrapped_view
  7.                 response = view_func(request, _args, *_kwargs)
    
    File "/Users/knutin/git/foo/src/django/django/utils/decorators.py" in bound_func
  8.             return func(self, _args2, *_kwargs2)
    
    File "/Users/knutin/git/foo/src/django/django/contrib/admin/options.py" in changelist_view
  9.             response = self.response_action(request, queryset=cl.get_query_set())
    
    File "/Users/knutin/git/foo/src/django/django/contrib/admin/options.py" in response_action
  10.         response = func(self, request, queryset)
    
    File "/Users/knutin/git/foo/src/django/django/contrib/admin/actions.py" in delete_selected
  11.     queryset, opts, request.user, modeladmin.admin_site, using)
    
    File "/Users/knutin/git/foo/src/django/django/contrib/admin/util.py" in get_deleted_objects
  12. collector.collect(objs)
    
    File "/Users/knutin/git/foo/src/django/django/contrib/admin/util.py" in collect
  13.     return super(NestedObjects, self).collect(objs, source_attr=source_attr, **kwargs)
    
    File "/Users/knutin/git/foo/src/django/django/db/models/deletion.py" in collect
  14.                 field.rel.on_delete(self, field, sub_objs, self.using)
    
    File "/Users/knutin/git/foo/src/django/django/db/models/deletion.py" in CASCADE
  15.                   source_attr=field.name, nullable=field.null)
    
    File "/Users/knutin/git/foo/src/django/django/contrib/admin/util.py" in collect
  16.     return super(NestedObjects, self).collect(objs, source_attr=source_attr, **kwargs)
    
    File "/Users/knutin/git/foo/src/django/django/db/models/deletion.py" in collect
  17.                 sub_objs = relation.bulk_related_objects(new_objs, self.using)
    

None isn't a good return value from TaggableManager.related_query_name()

Because it causes "AttributeError: 'NoneType' object has no attribute 'endswith'" in Options.get_all_field_names() on a TaggedItemBase subclass. Which I'm seeing when I try to do queries with filters that span related tables on a TaggedItemBase subclass.

Maybe '' would be an equally-good replacement that wouldn't cause this? Need to look into whether there's something more reasonable.

Index taggit_taggeditems.object_id

We're using taggit (very nice! thanks!) on support.mozilla.com, and we ran into a pretty horrific table-scan query due to taggit_taggeditems.object_id not being indexed. Could we get a db_index=True or something in the TaggedItem model?

TagManager

I'm I missing something or is TagManager non-existent? Still hacking on this?

Caught AttributeError: 'TaggableManager' object has no attribute 'flatchoices'

Hi,
I'm using taggit 0.9.1 with latest django. I installed taggit and reset my application db. When I try to add new data, ("Question" model, which as tags as a member), I get the above error.
Here is the traceback.
Environment:

Request Method: GET
Request URL: http://localhost:8000/admin/questions/question/
Django Version: 1.2.1
Python Version: 2.6.5
Installed Applications:
['django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.markup',
'django.contrib.admin',
'firstsite.questions',
'firstsite.accounts',
'firstsite.demo',
'taggit',
'south']
Installed Middleware:
('django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware')

Template error:
In template /usr/local/lib/python2.6/dist-packages/django/contrib/admin/templates/admin/change_list.html, error at line 95
Caught AttributeError while rendering: 'TaggableManager' object has no attribute 'flatchoices'
85 : {% endif %}

86 : {% endblock %}

87 :

88 : <form id="changelist-form" action="" method="post"{% if cl.formset.is_multipart %} enctype="multipart/form-data"{% endif %}>{% csrf_token %}

89 : {% if cl.formset %}

90 : {{ cl.formset.management_form }}

91 : {% endif %}

92 :

93 : {% block result_list %}

94 : {% if action_form and actions_on_top and cl.full_result_count %}{% admin_actions %}{% endif %}

95 : {% result_list cl %}

96 : {% if action_form and actions_on_bottom and cl.full_result_count %}{% admin_actions %}{% endif %}

97 : {% endblock %}

98 : {% block pagination %}{% pagination cl %}{% endblock %}

99 :

100 :

101 :

102 : {% endblock %}

103 :

Traceback:
File "/usr/local/lib/python2.6/dist-packages/django/core/handlers/base.py" in get_response

  1.                 response = callback(request, _callback_args, *_callback_kwargs)
    
    File "/usr/local/lib/python2.6/dist-packages/django/contrib/admin/options.py" in wrapper
  2.             return self.admin_site.admin_view(view)(_args, *_kwargs)
    
    File "/usr/local/lib/python2.6/dist-packages/django/utils/decorators.py" in _wrapped_view
  3.                 response = view_func(request, _args, *_kwargs)
    
    File "/usr/local/lib/python2.6/dist-packages/django/views/decorators/cache.py" in _wrapped_view_func
  4.     response = view_func(request, _args, *_kwargs)
    
    File "/usr/local/lib/python2.6/dist-packages/django/contrib/admin/sites.py" in inner
  5.         return view(request, _args, *_kwargs)
    
    File "/usr/local/lib/python2.6/dist-packages/django/utils/decorators.py" in _wrapper
  6.         return decorator(bound_func)(_args, *_kwargs)
    
    File "/usr/local/lib/python2.6/dist-packages/django/utils/decorators.py" in _wrapped_view
  7.                 response = view_func(request, _args, *_kwargs)
    
    File "/usr/local/lib/python2.6/dist-packages/django/utils/decorators.py" in bound_func
  8.             return func(self, _args2, *_kwargs2)
    
    File "/usr/local/lib/python2.6/dist-packages/django/contrib/admin/options.py" in changelist_view
  9.     ], context, context_instance=context_instance)
    
    File "/usr/local/lib/python2.6/dist-packages/django/shortcuts/init.py" in render_to_response
  10. return HttpResponse(loader.render_to_string(_args, *_kwargs), **httpresponse_kwargs)
    
    File "/usr/local/lib/python2.6/dist-packages/django/template/loader.py" in render_to_string
  11. return t.render(context_instance)
    
    File "/usr/local/lib/python2.6/dist-packages/django/template/init.py" in render
  12.         return self._render(context)
    
    File "/usr/local/lib/python2.6/dist-packages/django/template/init.py" in _render
  13.     return self.nodelist.render(context)
    
    File "/usr/local/lib/python2.6/dist-packages/django/template/init.py" in render
  14.             bits.append(self.render_node(node, context))
    
    File "/usr/local/lib/python2.6/dist-packages/django/template/debug.py" in render_node
  15.         result = node.render(context)
    
    File "/usr/local/lib/python2.6/dist-packages/django/template/loader_tags.py" in render
  16.     return compiled_parent._render(context)
    
    File "/usr/local/lib/python2.6/dist-packages/django/template/init.py" in _render
  17.     return self.nodelist.render(context)
    
    File "/usr/local/lib/python2.6/dist-packages/django/template/init.py" in render
  18.             bits.append(self.render_node(node, context))
    
    File "/usr/local/lib/python2.6/dist-packages/django/template/debug.py" in render_node
  19.         result = node.render(context)
    
    File "/usr/local/lib/python2.6/dist-packages/django/template/loader_tags.py" in render
  20.     return compiled_parent._render(context)
    
    File "/usr/local/lib/python2.6/dist-packages/django/template/init.py" in _render
  21.     return self.nodelist.render(context)
    
    File "/usr/local/lib/python2.6/dist-packages/django/template/init.py" in render
  22.             bits.append(self.render_node(node, context))
    
    File "/usr/local/lib/python2.6/dist-packages/django/template/debug.py" in render_node
  23.         result = node.render(context)
    
    File "/usr/local/lib/python2.6/dist-packages/django/template/loader_tags.py" in render
  24.         result = block.nodelist.render(context)
    
    File "/usr/local/lib/python2.6/dist-packages/django/template/init.py" in render
  25.             bits.append(self.render_node(node, context))
    
    File "/usr/local/lib/python2.6/dist-packages/django/template/debug.py" in render_node
  26.         result = node.render(context)
    
    File "/usr/local/lib/python2.6/dist-packages/django/template/loader_tags.py" in render
  27.         result = block.nodelist.render(context)
    
    File "/usr/local/lib/python2.6/dist-packages/django/template/init.py" in render
  28.             bits.append(self.render_node(node, context))
    
    File "/usr/local/lib/python2.6/dist-packages/django/template/debug.py" in render_node
  29.         result = node.render(context)
    
    File "/usr/local/lib/python2.6/dist-packages/django/template/init.py" in render
  30.                 dict = func(*args)
    
    File "/usr/local/lib/python2.6/dist-packages/django/contrib/admin/templatetags/admin_list.py" in result_list
  31.         'results': list(results(cl))}
    
    File "/usr/local/lib/python2.6/dist-packages/django/contrib/admin/templatetags/admin_list.py" in results
  32.         yield list(items_for_result(cl, res, None))
    
    File "/usr/local/lib/python2.6/dist-packages/django/contrib/admin/templatetags/admin_list.py" in items_for_result
  33.                 result_repr = display_for_field(value, f)
    
    File "/usr/local/lib/python2.6/dist-packages/django/contrib/admin/util.py" in display_for_field
  34. if field.flatchoices:
    

Exception Type: TemplateSyntaxError at /admin/questions/question/
Exception Value: Caught AttributeError while rendering: 'TaggableManager' object has no attribute 'flatchoices'

TagWidget failing on select_related when value doesn't exist

django 1.1.1

I just upgraded to the newest release of taggit and I'm running into this:

If I try to go to add an object of any model with a TagField I immediately get 'NoneType' object has no attribute 'select_related' before I even get to the change_form.

With some basic trouble shooting I found out that when you hit this line value = ", ".join(o.tag.name for o in value.select_related("tag")), there is no value available at this time (at least on a new object that doesnt exist yet). I change the if statement above it to only run this IF value is not none. After that everything seems to work fine. adding, saving, etc. The tags are created properly and associated.

I've tried stripping down my environment because it seems that if this is an actual bug that this would happen to everyone using it. This obviously isnt the case, but figured I would at least start a discussion on it. here is what my working bit looks like

if not isinstance(value, basestring) and value:
    value = ", ".join(o.tag.name for o in value.select_related("tag"))

Aggregates produce incorrect SQL

Using aggregate queries against tags results in the wrong SQL being generated.

>>> MyModel.objects.annotate(num_tags=Count('tags')).filter(num_tags=0).distinct()
SELECT "billing_discount"."id", "billing_discount"."name", "billing_discount"."internal_description", "billing_discount"."start_ts", "billing_discount"."end_ts", "billing_discount"."active", "billing_discount"."percentage", "billing_discount"."billing_country", "billing_discount"."can_stack", "billing_discount"."realm_id", "billing_discount"."product_id", COUNT(DISTINCT "taggit_taggeditem"."tag_id") AS "num_tags"
FROM "billing_discount"
LEFT OUTER JOIN "taggit_taggeditem" ON ("billing_discount"."id" = "taggit_taggeditem"."object_id")
GROUP BY "billing_discount"."id",
     "billing_discount"."name",
     "billing_discount"."internal_description",
     "billing_discount"."start_ts",
     "billing_discount"."end_ts",
     "billing_discount"."active",
     "billing_discount"."percentage",
     "billing_discount"."billing_country",
     "billing_discount"."can_stack",
     "billing_discount"."realm_id",
     "billing_discount"."product_id" HAVING COUNT(DISTINCT "taggit_taggeditem"."tag_id") = 0 LIMIT 21

The join against taggeditem doesn't have the constraint against content_type_id, so this is actually checking for tags on everything with the same IDs.

Tag field always appears as 'changed' in Django forms (contains patch)

django-taggit's custom TagWidget always reports to Django's form classes that it has changed. This results in the django-admin logs claiming that the tag field has been modified, even when the value is left the same.

(This bug is present in django-taggit 6c6936e, and tested against Django 1.2.5 and 1.3 beta 1 SVN-15323.)

Why this is happening:

To determine whether a field has changed, Django's BaseForm asks the field's widget to compare its initial value (the value from the model/initial dictionary) to the raw value submitted to the form before clean() has been called. In TagWidget's case this means it's comparing a tag manager to a string, which is always unequal.

Solution:

This can be fixed by customising the TagWidget's _has_changed method to normalise both values to strings before comparing them, and I'm attaching a patch that does that.

(This smells like a misfeature in Django, in that it ought to be checking against cleaned_data for changes; but I expect there's a lot of existing behaviour that depends on it checking against the raw values instead, so it probably won't get fixed upstream in Django. Even if it does, the revised method should be safe.)

no way to use tag names with commas in TagField

Which sucks if you happen to have a dataset where tag names are predefined, and some of them must include commas.

django-tagging has a very effective little tag-string parser that handles space-separated tags in the simple case, comma-separated if unquoted commas are found, and allows quoting of tag names that include commas.

Is taggit's "stupid" tagstring parsing a fixed design decision? If not, I'll port tagging's parser, with tests. If so, I'll do it anyway, but keep it in a private branch :-)

name field of default tag model should be unique=True

I don't think there's a reasonable use case for two distinct Tag objects with identical names, having the possibility is just more likely to lead to problems and confusion.

It would be pretty easy to document the column-alteration SQL necessary for existing installs, and/or provide a South migration for the common case of people using South.

Plus, this would allow a nice fix for the race-condition currently present in TaggableManager.add().

tagging an abstract model doesn't work

Assume you have this model:

from django.db import models
from taggit.managers import TaggableManager
class BaseModel(models.Model):
    name = models.CharField(max_length=50, unique=True)
    tags = TaggableManager()

    def __unicode__(self):
        return self.name

class Meta(object):
    abstract = True 

class AlphaModel(BaseModel):
    pass

class BetaModel(BaseModel):
    pass

Then a syncdb will emit the following error messages:

Creating test database 'default'...
Error: One or more models did not validate:
tests.alphamodel: Accessor for m2m field 'tagged_items' clashes with related m2m field
'TaggedItem.alphamodel_set'. Add a related_name argument to the definition for 'tagged_items'.
tests.alphamodel: Accessor for m2m field 'tagged_items' clashes with related m2m field
'TaggedItem.alphamodel_set'. Add a related_name argument to the definition for 'tagged_items'.
tests.betamodel: Accessor for m2m field 'tagged_items' clashes with related m2m field
'TaggedItem.betamodel_set'. Add a related_name argument to the definition for 'tagged_items'.
tests.betamodel: Accessor for m2m field 'tagged_items' clashes with related m2m field
'TaggedItem.betamodel_set'. Add a related_name argument to the definition for 'tagged_items'.

Obviously if you move the tags-attribute to the non-abstract models, everything works. I assume that a related_name on the content_object-attribute of TaggedItemBase would be a solution, but there's no such attribute for the GenericForeignKey :-(

related_name conflicts when added to an abstract base class

Hi,

I tried the following

class Model(models.Model):
    ...
    tags = TaggableManager()

    class Meta:
        abstract = True

however, it seems that it produces 'related_name' conflicts in every class that inherits this base class.

such as:

Error: One or more models did not validate:
projects.project: Accessor for m2m field 'tagged_items' clashes with related m2m field 'TaggedItem.project_set'. Add a related_name argument to the definition for 'tagged_items'.
projects.project: Accessor for m2m field 'tagged_items' clashes with related m2m field 'TaggedItem.project_set'. Add a related_name argument to the definition for 'tagged_items'.
articles.article: Accessor for m2m field 'tagged_items' clashes with related m2m field 'TaggedItem.article_set'. Add a related_name argument to the definition for 'tagged_items'.
articles.article: Accessor for m2m field 'tagged_items' clashes with related m2m field 'TaggedItem.article_set'. Add a related_name argument to the definition for 'tagged_items'.

Kind thanks,

Daryl

TaggableManager extra_filters lookup when using model inheritance

Model.objects.filter(tags__in=...) fails when using model inheritance. It looks like contribute_to_class only gets called once when a TaggableManager is added to a parent model, so self.model is the base model. This gives you the wrong content_type_id when doing the extra_filters lookup.

Example:

from django.db import models
from taggit.managers import TaggableManager

class BasePost(models.Model):
    content = models.TextField()
    tags = TaggableManager()

class ChildPost(BasePost):
    more_stuff = models.CharField(max_length=200, blank=True)

In [1]: from posts.models import *

In [2]: bp = BasePost.objects.create(content='this is a basepost')

In [3]: bp.tags.add('basepost', 'everybody')

In [4]: bp.tags.all()
Out[4]: [<Tag: basepost>, <Tag: everybody>]

In [5]: cp = ChildPost.objects.create(content='this is a childpost')

In [6]: cp.tags.add('childpost', 'everybody')

In [7]: cp.tags.all()
Out[7]: [<Tag: childpost>, <Tag: everybody>]

In [8]: BasePost.objects.filter(tags__in=['everybody'])
Out[8]: [<BasePost: BasePost object>]

In [9]: ChildPost.objects.filter(tags__in=['everybody'])
Out[9]: []

In [11]: BasePost.objects.filter(tags__in=['basepost'])
Out[11]: [<BasePost: BasePost object>]

In [12]: ChildPost.objects.filter(tags__in=['childpost'])
Out[12]: []

In [14]: TaggedItem.objects.filter(tag__name='everybody')
Out[14]: [<TaggedItem: BasePost object tagged with everybody>, <TaggedItem: ChildPost object tagged with everybody>]

get_db_prep_lookup logic

I believe the get_db_prep_lookup is currently broken. You cant update tags based on this logic. When updating you will always hit the Value Error.

IntegrityError when two tags that slugify to the same thing are given

I ran in to an IntegrityError while migrating data from django-tagging to django-taggit in cases where both "some tag" and "some-tag" were in the tag list. I wrote a test and fixed this issue by changing lookups to be by slugified tag which would collapse "some tag" and "some-tag" in to a single tag rather than raise an IntegrityError.

Here's the commit to the slugify branch of our fork:

http://github.com/pragmaticbadger/django-taggit/commit/e624ad595cbe80d86ec4339007fd585c08971a17

I'm not in love with the approach and am open to alternatives or a wontfix.

Cannot delete any object which uses tags on the model

Traceback:
File "/usr/local/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
100. response = callback(request, _callback_args, *_callback_kwargs)File "/usr/local/lib/python2.7/site-packages/django/contrib/admin/options.py" in wrapper
240. return self.admin_site.admin_view(view)(_args, *_kwargs)File "/usr/local/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapped_view
74. response = view_func(request, _args, *_kwargs)File "/usr/local/lib/python2.7/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
69. response = view_func(request, _args, *_kwargs)File "/usr/local/lib/python2.7/site-packages/django/contrib/admin/sites.py" in inner
194. return view(request, _args, *_kwargs)File "/usr/local/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapper
21. return decorator(bound_func)(_args, *_kwargs)File "/usr/local/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapped_view
74. response = view_func(request, _args, *_kwargs)File "/usr/local/lib/python2.7/site-packages/django/utils/decorators.py" in bound_func
17. return func(self, _args2, *_kwargs2)File "/usr/local/lib/python2.7/site-packages/django/contrib/admin/options.py" in delete_view
1081. (deleted_objects, perms_needed) = get_deleted_objects((obj,), opts, request.user, self.admin_site)File "/usr/local/lib/python2.7/site-packages/django/contrib/admin/util.py" in get_deleted_objects
109. obj._collect_sub_objects(collector)File "/usr/local/lib/python2.7/site-packages/django/db/models/base.py" in _collect_sub_objects
604. for sub_obj in f.value_from_object(self).all():
Exception Type: AttributeError at /admin/content/content/13/delete/
Exception Value: 'unicode' object has no attribute 'all'

If I comment out tags = TaggableManager() from the model in question, I can then go about deleting the object normally. It doesn't matter whether there are tags filled in or not. It happens with blank tag fields also. Only difference is that the error says 'str' instead of 'unicode'.

This is the code in question, I assume:

def value_from_object(self, instance):
    if instance.pk:
        return ", ".join(map(unicode, getattr(instance, self.name).all()))
    return ""

I've tried working through the code myself but I don't know enough about it yet to debug. I'm using the latest Django from trunk.

through Model specified as string not respected

Django allows you to specify the through model using a string containing the name of the model class but taggit raises an Exception if you try to do the same:

.../apps/newsroom/models.py", line 99, in Article
tags = TaggableManager(through='ContentTagThrough')
File "/home/brian/.virtualenvs/gr/lib/python2.6/site-packages/taggit/managers.py", line 40, in init
self.use_gfk = through is None or issubclass(through, GenericTaggedItemBase)
TypeError: issubclass() arg 1 must be a class

If it is not trivial to support the string argument it would be helpful to call this out in the docs.

Cannot use graph_models after adding taggit

After I add the django-taggit and try to use graph_models from django-extensions I get the following traceback. Is it just my problem? Is there a workaround?

Traceback (most recent call last):
File "./manage.py", line 11, in
execute_manager(settings)
File "/home/rif/.virtualenvs/bucatar/lib/python2.6/site-packages/django/core/management/init.py", line 438, in execute_manager
utility.execute()
File "/home/rif/.virtualenvs/bucatar/lib/python2.6/site-packages/django/core/management/init.py", line 379, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/rif/.virtualenvs/bucatar/lib/python2.6/site-packages/django/core/management/base.py", line 191, in run_from_argv
self.execute(_args, *_options.dict)
File "/home/rif/.virtualenvs/bucatar/lib/python2.6/site-packages/django/core/management/base.py", line 220, in execute
output = self.handle(_args, *_options)
File "/home/rif/.virtualenvs/bucatar/lib/python2.6/site-packages/django_extensions/management/commands/graph_models.py", line 30, in handle
dotdata = generate_dot(args, **options)
File "/home/rif/.virtualenvs/bucatar/lib/python2.6/site-packages/django_extensions/management/modelviz.py", line 207, in generate_dot
add_attributes(field)
File "/home/rif/.virtualenvs/bucatar/lib/python2.6/site-packages/django_extensions/management/modelviz.py", line 198, in add_attributes
'blank': field.blank,
AttributeError: 'TaggableManager' object has no attribute 'blank'

as_sql errors

Running ./manage.py test in my project that uses taggit, I get 4 errors from the taggit app. They seem to revolve around AttributeError: 'Query' object has no attribute 'as_sql' errors in managers.py line 72.

can't define multiple tag fields on a model

a model like this:

class Item(models.Model):
...
tags1 = TaggableManager()
tags2 = TaggableManager()

will give this error on python manage.py syncdb:

Error: One or more models did not validate:
taggit_test.item: Accessor for m2m field 'tags1' clashes with related m2m field 'TaggedItem.item_set'. Add a related_name argument to the definition for 'tags1'.
taggit_test.item: Accessor for m2m field 'tags2' clashes with related m2m field 'TaggedItem.item_set'. Add a related_name argument to the definition for 'tags2'.

Delete objects deletes wrong TaggedItems

If we do:
Foo.objects.all().delete()
It deletes all the TaggedItems by PK but for any type of content_type, not just Foo type. This is because "get_prep_lookup" gets called with the list of PKs of Foo, and doesn't filter by content_type.

We cannot simple filter out by content_type since "get_prep_lookup" also gets called with list of PKs of Tags when we call Tags.objects.remove('tag').

I tested with 0.4 but it probably also occurs on 0.6.

'TaggableManager' object has no attribute 'serialize'

Try to ./manage.py dumpdata for a model with a TaggableManager and this complaint pops up.

Traceback (most recent call last):
  File "./manage.py", line 11, in <module>
    execute_manager(settings)
  File "/Users/idan/.virtualenvs/djangoadvent/lib/python2.6/site-packages/django/core/management/__init__.py", line 362, in execute_manager
    utility.execute()
  File "/Users/idan/.virtualenvs/djangoadvent/lib/python2.6/site-packages/django/core/management/__init__.py", line 303, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/Users/idan/.virtualenvs/djangoadvent/lib/python2.6/site-packages/django/core/management/base.py", line 195, in run_from_argv
    self.execute(*args, **options.__dict__)
  File "/Users/idan/.virtualenvs/djangoadvent/lib/python2.6/site-packages/django/core/management/base.py", line 222, in execute
    output = self.handle(*args, **options)
  File "/Users/idan/.virtualenvs/djangoadvent/lib/python2.6/site-packages/django/core/management/commands/dumpdata.py", line 80, in handle
    return serializers.serialize(format, objects, indent=indent)
  File "/Users/idan/.virtualenvs/djangoadvent/lib/python2.6/site-packages/django/core/serializers/__init__.py", line 87, in serialize
    s.serialize(queryset, **options)
  File "/Users/idan/.virtualenvs/djangoadvent/lib/python2.6/site-packages/django/core/serializers/base.py", line 49, in serialize
    if field.serialize:
AttributeError: 'TaggableManager' object has no attribute 'serialize'

Tag Cloud

I've started working on an initial implementation of a tag cloud for django-taggit. The code is up at my fork, http://github.com/sykora/django-taggit/tree/cloud .

The logic behind the cloud generation is basically the same as that used in django-tagging et al.

Feedback welcome.

tags__in returning duplicate results? (Needs documentation)

Consider the following:

>>> apple = Food.objects.create(name="apple")
>>> apple.tags.add("red", "green", "delicious")
>>> cherry = Food.objects.create(name="cherry")
>>> cherry.tags.add("red")
>>> Food.objects.filter(tags__in=["red", "green])
[<Food: apple>, <Food: apple>, <Food: cherry>]

The apple object is returned twice, obviously the solution is to chain .distinct() on to the end of the queryset but this wasn't obvious to me at first. I think this should be documented more heavily as the most common real-world use cases require distinct and you might not realise until later when you have a larger dataset and at that stage it's much harder to troubleshoot.

Personally I would default to distinct() on all queries but obviously changing the API can be nasty when so many people are using taggit.

README.txt suggestion.

It's a bit silly but ...
In README.txt I think there is strong suggestion to type 'django-taggit' as one of the application in INSTALLED_APPS. What is obviously not true.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.