0

I have 3 models: Document, MetaData, MetaDataValue, and a "connector table" DocumentMetaDataValue. I want to add a document and all the associated metadata values on one admin page.

models.py:
# MetaData        
class MetaData(models.Model):
    metadata_id = models.AutoField(primary_key = True)
    name = models.CharField('metadata name', max_length=200, unique=True)
    description = models.TextField('description')

    def __str__(self):
        return self.name

# MetaData Value                   
class MetaDataValue(models.Model):
    metadata_id = models.ForeignKey(MetaData, on_delete=models.CASCADE,)
    value = models.CharField('value', max_length=200, unique=True)

    def __str__(self):
        return self.value

# Document               
class Document(models.Model):
    document_id = models.AutoField(primary_key=True)
    metadata = models.ManyToManyField('MetaData', through='DocumentMetaDataValue', through_fields=('document', 'metadata'))
    metadatavalue = models.ManyToManyField('MetaDataValue', through='DocumentMetaDataValue', through_fields=('document', 'metadataValue'))

class DocumentMetaDataValue(models.Model):
    document = models.ForeignKey(Document, on_delete=models.CASCADE)
    metadata = models.ForeignKey(MetaData, on_delete=models.CASCADE)
    metadataValue = models.ForeignKey(MetaDataValue, on_delete=models.CASCADE)

admin.py:
class Fred(forms.ModelForm):
    """ something newer
    """
    class Meta:
        model = DocumentMetaDataValue
        fields = '__all__'

class DocumentMetaDataValueInline(admin.TabularInline):
    model = DocumentMetaDataValue
    form = Fred

class DocumentAdmin(admin.ModelAdmin):
    form = DocumentForm
    list_display = ('get_document_type', 'document_state', 'title', 'description', 'original_file_name', 'created', 'storage_file_name', 'get_thumb', )
    ordering = ('created',)
    readonly_field = ('document_state',)
    filter_horizontal = ('metadata', 'metadatavalue', )
    inlines = (DocumentMetaDataValueInline, )
    # other code not related to this problem

admin.site.register(Document, DocumentAdmin)

There are 16+ metadata names, and each one has one or more metadata values. For example, the metadata name Person has 23 values ('Bob', 'Sam', 'Sally', etc), and the metadata name Decade has 12+ values (1890, 1900, 1910, 1920, etc). A Document can have one or more metadata names associated with it, and one or more metadata values for that metadata name can be associated with that Document. For example, a Document can be a photograph with two people in it. The metadata value for Decade could be 1910, and the metadata values for Person could be Sam and Sally.

On each line of the inline, I want to show the metadata name opposite a drop down with the associated metadata values. One should be able to pick more than one metadata value for a particular metadata name.desired result

What happens in the code above is each line of the inline has two drop down lists - the first is all the metadata names and the second is all the metadata values. current code output

I want to change the first drop down to be a single string for a metadata name, and the second drop down to still be a drop down, but only the values for that metadata name. I don't see how to make these changes.

Thanks!

Mark

user1045680
  • 815
  • 2
  • 9
  • 19
  • You can take a look of my previous example, if that helps out? https://stackoverflow.com/a/49672772/7707749 In this case you just need to set `DocumentMetaDataValue` as `model` in the first class and register the tags with the models: `Document`, `MetaDataValue` and `MetaData`. – King Reload Apr 09 '18 at 08:31
  • Thanks - I tried that approach and the inline has two drop down boxes, one for MetaData name and one for MetaData values. The problem is, there are 16+ metadata names and 50+ metadata values, so choosing from these two pick lists is fraught with error. What I would like is the metadata names as text, one per line, and have the associated metadata values as a drop down list just for that metadata name. If I were to do it in a form, I would see a query for a dictionary of metadata names and values and a loop over that dict to populate the fields, However, there must be a better way. – user1045680 Apr 10 '18 at 00:02
  • I don't understand what you are trying to do? Basically your list became too long? Or what do you mean to say? My apologies if I am slow to understand. – King Reload Apr 10 '18 at 08:16
  • Thanks for hanging with me! I will answer your question above by editing the original question. – user1045680 Apr 10 '18 at 16:07
  • Add `def __str__(self): return self.value` in the `MetaDataValue` model. – King Reload Apr 10 '18 at 19:08
  • That code is already in the model. I missed it when I copied and pasted the code above. I have added it back in. – user1045680 Apr 10 '18 at 19:36
  • Change the `metadataValue` to a ManyToManyField, as its not associated with the `through_fields` it should be fine, this way a metadata can have multiple metadatavalues. If thats what you meant? Plus I don't think there's a way to change the `metadata` field in a charfield, as it's part of the `through_fields` it should stay a Foreignkey, which forces it to be a dropdown. – King Reload Apr 10 '18 at 19:51
  • This just changes the metadata value to a multi select dropdown, which is progress! However, the full universe of metadata values are loaded in the drop down for each line, and I really need a metadata name/associated metadata values per line in the inline. – user1045680 Apr 10 '18 at 20:09
  • But what do you mean with `metadata name/associated metadata values per line in the inline`? Can you give an example please? Its quite hard without some visual example if you can do a little bit of editing to the image that would help me a bunch :) "I'm not very good with explenations through text, my bad" – King Reload Apr 10 '18 at 20:23
  • Is there a way to limit the values in each drop down (metadata names, and metadata values)? Say, have one value in the metadata name drop down, and only the associated metadata values for the name in the metadata values drop down? – user1045680 Apr 10 '18 at 20:54
  • In the first image I uploaded above, do you see that I covered the first metadata name drop down with one value - Person. The metadata values drop down to the right should only have those metadata values that are associated with Person - ie (Bob, Sam, Sally, etc) from the example above. Right now, the metadata value drop down has all the Person values as well as Decade values. – user1045680 Apr 10 '18 at 21:03
  • Try the running app. Go to http://pmi.pythonanywhere.com/admin/memorabilia/. user name mark password Apple123. Click on MetaDataValues and you can see how the metadata names have associated values. Then go back and look at Documents. Scroll down and check out the inline drop downs. All the MetaData names are in the first one, and all the MetaData values are in the second one. The first drop down should only have one metadata name, and the second drop down in the line should have just the metadata values associated with that name. – user1045680 Apr 10 '18 at 21:10
  • There is a second login after the one above. User name admin password samsung1. – user1045680 Apr 11 '18 at 00:32
  • I see what you mean now, it'll be hard, but I'll try to think of a way in the meantime (I was asleep so I couldn't react), I hope that I can find a way to show the values associated with the name :) – King Reload Apr 11 '18 at 05:39

0 Answers0