Retrieve field values from ManyToMany field in model

33 views
Skip to first unread message

Mark Phillips

unread,
Jun 25, 2017, 6:09:17 PM6/25/17
to django users
I have this class

class DocumentMetaData(models.Model):
    document = models.ManyToManyField(Document)
    metadata = models.ManyToManyField(MetaData)
    metadatavalue = models.ManyToManyField(MetaDataValue)
    
    def __str__(self):
        return "%s - %s" % (self.document, self.metadata)

The Document class has a field called 'title' and the Metadata class has a field called 'name'. How do I accesses these two fields from the class DocumentMetaData so the string output is something like <document.title> - <metadata.name>?

Thanks!

Mark

Vijay Khemlani

unread,
Jun 25, 2017, 7:20:52 PM6/25/17
to django...@googlegroups.com
A DocumentMetaData instance may be associated with multiple documents
and multiple metadata according to your model, so your question is
ambiguous.

If you want a particular DocumentMetaData to only refer to a single
document and a single metadata then change the ManyToManyField for a
ForeignKey

If you do that then you can do self.document.title and
self.metadata.name to access those fields.
> --
> You received this message because you are subscribed to the Google Groups
> "Django users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to django-users...@googlegroups.com.
> To post to this group, send email to django...@googlegroups.com.
> Visit this group at https://groups.google.com/group/django-users.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/django-users/CAEqej2NCVAp07CvESrUnR7k61UG4b0_q5OcaemfOrh%2B77mnTdQ%40mail.gmail.com.
> For more options, visit https://groups.google.com/d/optout.
>

Mark Phillips

unread,
Jun 26, 2017, 1:52:14 AM6/26/17
to django users
On Sun, Jun 25, 2017 at 4:20 PM, Vijay Khemlani <vkhe...@gmail.com> wrote:
A DocumentMetaData instance may be associated with multiple documents
and multiple metadata according to your model, so your question is
ambiguous.

Sorry about the confusion. When I create a DocumentMetaData, then there is a single row in the table that has a Document_id and MetaData_id. That is the document title and MetaData name I am trying to get so it can be displayed in the admin screen for that particular row in the DocumentMetaData table. I hope that makes more sense.

If you want a particular DocumentMetaData to only refer to a single
document and a single metadata then change the ManyToManyField for a
ForeignKey

That is not what I want.  

If you do that then you can do self.document.title and
self.metadata.name to access those fields.

On 6/25/17, Mark Phillips <ma...@phillipsmarketing.biz> wrote:
> I have this class
>
> class DocumentMetaData(models.Model):
>     document = models.ManyToManyField(Document)
>     metadata = models.ManyToManyField(MetaData)
>     metadatavalue = models.ManyToManyField(MetaDataValue)
>
>     def __str__(self):
>         return "%s - %s" % (self.document, self.metadata)
>
> The Document class has a field called 'title' and the Metadata class has a
> field called 'name'. How do I accesses these two fields from the class
> DocumentMetaData so the string output is something like <document.title> -
> <
> metadata.name>?
>
> Thanks!
>
> Mark
>
> --
> You received this message because you are subscribed to the Google Groups
> "Django users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.

To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.

Melvyn Sopacua

unread,
Jun 26, 2017, 3:21:55 AM6/26/17
to django...@googlegroups.com

On Sunday 25 June 2017 15:08:25 Mark Phillips wrote:

> I have this class

>

> class DocumentMetaData(models.Model):

> document = models.ManyToManyField(Document)

> metadata = models.ManyToManyField(MetaData)

> metadatavalue = models.ManyToManyField(MetaDataValue)

 

That design is wrong. This is the design you want:

 

class DocumentMetaData(models.Model):

name = models.CharField()

value = models.TextField()

 

class Document(models.Model):

title = models.CharField()

metadata = models.ManyToManyField(DocumentMetaData)

 

This design allows many metadata with name and value to be linked to a each document. I'm not entirely sure how to describe what your data design accomplishes and I'm guessing you can't either or it doesn't accomplish what you think it should.

--

Melvyn Sopacua

Mark Phillips

unread,
Jun 28, 2017, 2:57:40 PM6/28/17
to django users
Melvyn,

Thanks for your response. My original question was how to get the string names for the metadata and document out of the many to many table in the __str__ model method. I was able to accomplish this by the following

class DocumentMetaData(models.Model):
    document = models.ManyToManyField(Document)
    metadata = models.ManyToManyField(MetaData)
    metadatavalue = models.ManyToManyField(MetaDataValue)
    
    def __str__(self):
        title = self.document.all()[0].title
        metadata = self.metadata.all()[0].name
        return "%s - %s" % (title, metadata)

However, you raise a good question about my model design. This is the complete model design (with some of the model methods removed for clarity)

class MetaData(models.Model):
    metadata_id = models.AutoField(primary_key = True)
    name = models.CharField('metadata name', max_length=200)
    description = models.TextField('description')
    required = models.BooleanField(default=False)
          
class MetaDataValue(models.Model):
    metadata = models.ForeignKey(MetaData, on_delete=models.CASCADE,)
    value = models.CharField('value', max_length=200)
                
class Document(models.Model):
    document_id = models.AutoField(primary_key=True)
    document_type = models.ForeignKey(DocumentType, on_delete=models.CASCADE,)
    title = models.CharField('title', max_length=200)
    description = models.TextField('description')
    created_date = models.DateTimeField('date created', editable=False)
    storage_file_name = models.FileField('File name', upload_to=unique_file_path)
    original_file_name = models.CharField(editable=False, max_length=200)
    
class DocumentMetaData(models.Model):
    document = models.ManyToManyField(Document)
    metadata = models.ManyToManyField(MetaData)
    metadatavalue = models.ManyToManyField(MetaDataValue)

The problem I am having is that when I add data to the DocumentMetaData screen in the admin portal, the model does not maintain the relationship between the MetaData and the MetaDataName. For example, I can create the metadata entry People with values Mark, Sally, Sam, and another metadata entry of Events with values birthday, wedding, funeral. When I enter data into the DocumentMetaData, I am able to make an entry for events with the value Sally, which is wrong. So, my model is not really working as expected. 

What I want is to add metadata to documents, where metadata has one to many values. Many documents can have the metadata People with various values from the set of metadata People. Same with Events. But the Metadata Events can only have one or more of these values - birthday, wedding, funeral. 

Thanks for any help you can provide!

Mark

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
Reply all
Reply to author
Forward
0 new messages