почему пользовательский интерфейс администратора не добавляет раздел тегов для некоторых моделей, использующих django-taggit?

Я новичок в django и использую django-taggit 0.10a1 для функциональности тегов в моем django 1.4. .2 приложение. Я также попробовал приложение с тегами django, но, поскольку этот проект не поддерживался, а django-taggit имел много положительных отзывов от разработчиков, я выбрал его.

Мне было интересно, может ли кто-нибудь из вас помочь мне с проблемой, которую я вижу. Следуя документации, я добавил:

tags = TaggableManager()

ко всем моим моделям, которые нуждаются в маркировке. Большинство моделей автоматически добавили раздел «Теги» в администраторе django, как указано в документации, но для некоторых моделей раздел «Теги» не отображается в пользовательском интерфейсе администратора. Я не мог понять, почему. Вот пара моделей, которые у меня есть с строкой тегов, объявленной после всех полей. Если вы видите что-то неправильное в размещении этого утверждения в моей модели, и если вы можете сообщить мне, если вы обнаружите какие-либо проблемы, я был бы очень признателен. Ниже приведены примеры нерабочих моделей с TaggableManager:


Модель DigitalObject

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

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)

Я был бы искренне признателен, если бы кто-нибудь из вас мог взглянуть на него и сообщить мне, если вы видите что-то, что я мог пропустить, или если вам нужна дополнительная информация, чтобы понять мою проблему.

Заранее спасибо.


person StreetCat    schedule 07.08.2013    source источник


Ответы (1)


Оказывается, модели, для которых столбец тегов не отображался, имели наборы полей в admin.py. Для моделей, которые не упорядочены по наборам полей, taggit автоматически добавляет столбец «теги» в интерфейс администратора. Для тех, которые упорядочены по наборам полей, столбец «теги» из модели должен быть специально включен в один из наборов полей.

admin.py для модели WorkRecord

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 включен в набор полей Стандартные поля выше.

person StreetCat    schedule 05.09.2013