I am new to django and I am using django-taggit 0.10a1 for tagging functionality in my django 1.4.2 application. I also tried django-tagging app but as that project was not maintained and as django-taggit had a lot of positive reviews from developers, I opted for that.
I was wondering if the any of you can help me with the problem I am seeing. After following the documentation, I added :
tags = TaggableManager()
to all my models that need tagging. Most of the models automatically added Tags section in the django admin as the documentation specified, but for some of the models, Tags section doesn't show up on admin UI. I was not able to figure out why. Here are a couple of models that I have with the tags line declared after all the fields. If you see anything wrong in the placement of that statement in my model, and if you can let me know if you see any issue, I would greatly appreciate it. Sample non-working models with TaggableManager are as follows:
DigitalObject model
class DigitalObject(models.Model):
title = models.CharField(max_length=255, verbose_name=_("title"))
ascii_title = models.CharField(max_length=255, verbose_name=_("ASCII title"))
title_variants = models.CharField(max_length=300, null=True, blank=True, verbose_name=_("title variants"))
collection = models.ForeignKey(Collection, related_name="collection_objects", verbose_name=_("collection"))
object_creator = models.ForeignKey(Creator, null=True, blank=True, related_name="objects_created", verbose_name=_("object creator"))
language = models.ManyToManyField("Language", null=True, blank=True, verbose_name=_("language"), related_name="language_objects")
subject = models.ManyToManyField(SubjectHeading, null=True, blank=True, related_name="collection_objects", verbose_name=_("subject"))
object_id = models.CharField(max_length=6, null=True, blank=True, verbose_name=_("object ID"))
digital_id = models.CharField(max_length=100, null=True, blank=True, verbose_name=_("digital ID"))
rights_holders = models.CharField(max_length=255, null=True, blank=True, verbose_name=_("rights holder(s)"))
license_type = models.ForeignKey("License", default=1, verbose_name=_("license type"))
permission_form = models.FileField(upload_to='permissionforms', verbose_name=_("permission form"), null=True, blank=True)
# Physical object info
identifier = models.CharField(max_length=60, help_text=_("e.g. ISBN, ISSN, DOI"), null=True, blank=True, verbose_name=_("identifier"))
marks = models.CharField(max_length=255, null=True, blank=True, verbose_name=_("marks/inscriptions"))
measurements = models.CharField(max_length=255, null=True, blank=True, verbose_name=_("physical description"))
phys_object_type = models.ForeignKey("PhysicalObjectType", verbose_name=_("Physical object type"), related_name="digital_objects", null=True, blank=True)
donor = models.CharField(max_length=255, null=True, blank=True, verbose_name=_("donor"))
sponsor_note = models.CharField(max_length=255, null=True, blank=True, verbose_name=_("sponsor note"))
phys_obj_date = models.DateField(null=True, blank=True, verbose_name=_("physical object date"))
phys_obj_precision = models.CharField(max_length=1, choices=constants.DATE_PRECISION_CHOICES, default=u'f', null=True, blank=True, verbose_name=_("Precision"))
phys_obj_BC = models.BooleanField(default=False, verbose_name=_("Is B.C. date"))
phys_obj_location = models.ForeignKey("Location", null=True, blank=True, verbose_name=_("physical object location"))
# Digital object info
digi_object_format = models.ForeignKey("DigitalObjectType", verbose_name=_("Digital object format"), null=True, blank=True)
# Container info
series_num = models.CharField(max_length=12, null=True, blank=True, verbose_name=_("series #"))
series_name = models.CharField(max_length=255, null=True, blank=True, verbose_name=_("series name"))
subseries_num = models.CharField(max_length=12, null=True, blank=True, verbose_name=_("subseries #"))
subseries_name = models.CharField(max_length=255, null=True, blank=True, verbose_name=_("subseries name"))
box_num = models.CharField(max_length=12, null=True, blank=True, verbose_name=_("box #"))
folder_num = models.CharField(max_length=12, null=True, blank=True, verbose_name=_("folder #"))
drawer_num = models.CharField(max_length=12, null=True, blank=True, verbose_name=_("drawer #"))
folder_name = models.CharField(max_length=255, null=True, blank=True, verbose_name=_("folder name"))
folder_date = models.CharField(max_length=255, null=True, blank=True, verbose_name=_("folder date"))
# Relationships
related_production = models.ManyToManyField(Production, related_name="related_objects", null=True, blank=True, verbose_name=_("related production"))
related_festival = models.ManyToManyField(FestivalOccurrence, related_name="related_objects", null=True, blank=True, verbose_name=_("related festival"))
related_venue = models.ManyToManyField(Location, related_name="related_objects", null=True, blank=True, verbose_name=_("related venue"))
related_creator = models.ManyToManyField(Creator, related_name="related_objects", null=True, blank=True, verbose_name=_("related creator"))
related_work = models.ManyToManyField(WorkRecord, related_name="related_objects", null=True, blank=True, verbose_name=_("related work"))
# extra details
summary = models.TextField(null=True, blank=True, verbose_name=_("summary"))
notes = models.TextField(null=True, blank=True, verbose_name=_("notes"))
creation_date = models.DateField(null=True, blank=True, help_text="Click 'Today' to see today's date in the proper date format.", verbose_name=_("creation date"))
creation_date_precision = models.CharField(max_length=1, null=True, blank=True, choices=constants.DATE_PRECISION_CHOICES, default=u'y', verbose_name=_("Precision"))
creation_date_BC = models.BooleanField(default=False, verbose_name=_("Is B.C. date"))
restricted = models.BooleanField(default=False, verbose_name=_("Restricted?"))
restricted_description = models.CharField(max_length=255, null=True, blank=True, verbose_name=_("Details of restrictions"))
ready_to_stream = models.BooleanField(default=False, verbose_name=_("Uploaded to streaming server"))
hi_def_video = models.BooleanField(default=False, verbose_name=_("Hi-def video"))
poster_image = models.FileField(upload_to='digitalobjects/poster_images', storage=OverwriteStorage(), verbose_name=_("Poster image (for videos)"), null=True, blank=True)
attention = models.TextField(null=True, blank=True, verbose_name=_("attention"))
has_attention = models.BooleanField(default=False)
needs_editing = models.BooleanField(default=True, verbose_name=_("needs editing"))
published = models.BooleanField(default=True, verbose_name=_("published"))
tags = TaggableManager()
def phys_obj_date_display(self):
return display_date(self.phys_obj_date, self.phys_obj_precision, self.phys_obj_BC)
def creation_date_display(self):
return display_date(self.creation_date, self.creation_date_precision, self.creation_date_BC)
def has_related_things(self):
if self.related_production.exists():
return True
if self.related_festival.exists():
return True
if self.related_venue.exists():
return True
if self.related_creator.exists():
return True
if self.related_work.exists():
return True
return False
def object_number(self):
num = ''
num += self.collection.repository.repository_id
num += self.collection.collection_id
num += self.object_id
return num
def first_file(self):
if self.files:
df = self.files.order_by('seq_id')[0]
return df
else:
return False
def __unicode__(self):
return "%s (%s)" % (self.title, str(self.object_number()))
def update_digital_object_title(sender, **kwargs):
obj = kwargs['instance']
obj.ascii_title = unidecode(obj.title)
pre_save.connect(update_digital_object_title, sender=DigitalObject)
WorkRecord model
class WorkRecord(models.Model):
title = models.CharField(max_length=255, verbose_name=_("title"))
title_variants = models.CharField(max_length=300, null=True, blank=True, verbose_name=_("title variants"))
ascii_title = models.CharField(max_length=255, verbose_name=_("ASCII title"))
creators = models.ManyToManyField(Creator, through="WorkRecordCreator", verbose_name=_("creators"))
creators_display = models.CharField(max_length=255, verbose_name=_("creators"))
work_type = models.ForeignKey("WorkRecordType", verbose_name=_("work type"))
subject = models.ManyToManyField(SubjectHeading, null=True, blank=True, related_name="works", verbose_name=_("subject"))
genre = models.ForeignKey("WorkGenre", null=True, blank=True, help_text=_("The work's genre - e.g. drama, comedy"), verbose_name=_("genre"))
culture = models.ForeignKey("WorkCulture", null=True, blank=True, help_text=_("The culture the work is a part of"), verbose_name=_("culture"))
style = models.ForeignKey("WorkStyle", null=True, blank=True, help_text=_("A movement or period the work belongs to"), verbose_name=_("style"))
lang = models.ManyToManyField("Language", null=True, blank=True, verbose_name=_("language"))
creation_date = models.DateField(null=True, blank=True, help_text="Click 'Today' to see today's date in the proper date format.", verbose_name=_("creation date"))
creation_date_precision = models.CharField(max_length=1, choices=constants.DATE_PRECISION_CHOICES, default=u'y', null=True, blank=True, verbose_name=_("Precision"))
creation_date_BC = models.BooleanField(default=False, verbose_name=_("Is B.C. date"))
publication_date = models.DateField(null=True, blank=True, help_text="Click 'Today' to see today's date in the proper date format.", verbose_name=_("publication date"))
publication_date_precision = models.CharField(max_length=1, choices=constants.DATE_PRECISION_CHOICES, default=u'y', null=True, blank=True, verbose_name=_("Precision"))
publication_date_BC = models.BooleanField(default=False, verbose_name=_("Is B.C. date"))
publication_rights = models.CharField(max_length=30, null=True, blank=True, verbose_name=_("publication rights"))
performance_rights = models.CharField(max_length=30, null=True, blank=True, verbose_name=_("performance rights"))
website = models.URLField(null=True, blank=True, help_text=_("A site where users can find the text of this work"), verbose_name=_("website"))
digital_copy = models.ForeignKey("DigitalObject", null=True, blank=True, verbose_name=_("digital copy"))
summary = models.TextField(null=True, blank=True, verbose_name=_("summary"))
notes = models.TextField(null=True, blank=True, verbose_name=_("notes"))
related_works = models.ManyToManyField("self", through="RelatedWork", symmetrical=False, null=True, blank=True, related_name="related_to", verbose_name=_("related works"))
attention = models.TextField(null=True, blank=True, verbose_name=_("attention"))
has_attention = models.BooleanField(default=False)
needs_editing = models.BooleanField(default=True, verbose_name=_("needs editing"))
published = models.BooleanField(default=True, verbose_name=_("published"))
awards_text = models.TextField(null=True, blank=True, verbose_name=_("awards (plain text)"))
biblio_text = models.TextField(null=True, blank=True, verbose_name=_("bibliography (plain text)"))
biblio_text_es = models.TextField(null=True, blank=True, verbose_name=_("bibliography (plain text, Spanish)"))
secondary_biblio_text = models.TextField(null=True, blank=True, verbose_name=_("secondary bibliography (plain text)"))
secondary_biblio_text_es = models.TextField(null=True, blank=True, verbose_name=_("secondary bibliography (plain text, Spanish)"))
tags = TaggableManager()
def creation_date_display(self):
return display_date(self.creation_date, self.creation_date_precision, self.creation_date_BC)
creation_date_display.short_description = _("Creation date")
def publication_date_display(self):
return display_date(self.publication_date, self.publication_date_precision, self.publication_date_BC)
publication_date_display.short_description = _("Publication date")
def creators_display_links(self):
cs = ""
for wrc in WorkRecordCreator.objects.filter(work_record=self):
cs += "<a href='/creator/" + str(wrc.creator.id) + "'>"
cs += wrc.creator.display_name()
cs += "</a>, "
cs = cs.rstrip(', ')
return cs
def has_system_links(self):
if AwardCandidate.objects.filter(work_record=self).exists():
return True
elif RelatedWork.objects.filter(first_work=self).exists():
return True
elif RelatedWork.objects.filter(second_work=self).exists():
return True
elif WorkRecordCreator.objects.filter(work_record=self).exists():
return True
elif Role.objects.filter(source_text=self).exists():
return True
elif Production.objects.filter(source_work=self).exists():
return True
elif DigitalObject.objects.filter(related_work=self).exists():
return True
elif BibliographicRecord.objects.filter(work_record=self).exists():
return True
else:
return False
def __unicode__(self):
return "%s (%s)" % (self.title, self.work_type.name)
def update_wr_title(sender, **kwargs):
obj = kwargs['instance']
obj.ascii_title = unidecode(obj.title)
pre_save.connect(update_wr_title, sender=WorkRecord)
I would sincerely appreciate if any of you could please take a look at it and let me know if you see anything that I might have missed or if you need more information to understand my issue.
Thanks in advance.
Turns out that the models for which the tags column wasn't appearing had field sets in admin.py. For models which are not arranged by field sets, taggit automatically adds "tags" column to Admin UI. For the ones which are arranged by fieldsets, "tags" column from model should be specifically included in one of the the field sets.
admin.py for WorkRecord model
class WorkRecordAdmin(TranslationAdmin):
form = arcforms.WorkRecordAdminForm
inlines = (WorkRecordCreatorInline, RoleInline, RelatedWorkInline,)
list_display = ('title', 'creators_display', 'work_type', 'genre', 'culture', 'style', 'has_system_links')
list_filter = ('work_type', 'lang', 'genre', 'culture', 'style', 'has_attention',)
search_fields = ['title', 'ascii_title', 'title_variants']
filter_horizontal = ['subject', 'lang']
fieldsets = (
('Titles', {
'fields': ('title', 'title_variants')
}),
('Description', {
'fields': ('work_type', 'subject', 'genre', 'culture', 'style', 'lang')
}),
('Creation / Publication', {
'fields': (('creation_date', 'creation_date_precision', 'creation_date_BC'), ('publication_date', 'publication_date_precision', 'publication_date_BC'), 'publication_rights', 'performance_rights')
}),
('Access', {
'fields': ('website', 'digital_copy')
}),
('Standard fields', {
'fields': ('summary', 'notes', 'attention', 'needs_editing', 'published', 'tags')
})
)
tags column is included in the Standard fields fieldset above.