0

I have 2 models in the same app cross referencing each other. One as a foreign key and another as many to many key.

class VideoEmbed(models.Model):
    person = models.ForeignKey('Person')
    title = models.CharField(max_length=250) 
    video = EmbedVideoField()

class Person(models.Model):
    name = models.CharField(max_length=200)
    born = models.DateField(blank=True, null=True)
    video = models.ManyToManyField(VideoEmbed, related_name='video_embed', null=True, blank=True)

The reason why I wanted to do this is to link Person with its related videos as one person could have many videos. Now in the django admin site the videoembed model will record video against each person and accordingly these will be shown in the each instance of Person respectively.However in the django site I have to select each of these videos from a select box in the many to many relationship field.

Video field in Person instance

I wanted this field to only show the videos that are linked to this instance via the videoembed model and not all of the videos added. Is there a way to do this? If not then may be I should be able to see 2 fields in this section instead one so that I can select the videos which are linked to a Person instance.

Uma
  • 689
  • 2
  • 12
  • 35
  • I'm confused. Why do you need the reference from Video back to person? That reverse link already provided by the ManyToMany link? –  Feb 06 '15 at 05:26
  • @LegoStormtroopr Hi, there are specific videos for each person and there can be many videos linked with each person. Now consider 50-100 total videos and figuring out which video belongs to a particular person will be difficult. – Uma Feb 06 '15 at 05:38

1 Answers1

3

I think this is a misunderstanding of how ManyToMany relationships work. When you define a ManyToMany, a reverse relation is included on the "far side" of the relationship.

For example, consider the trimmed down version of your code:

class Video(models.Model):
    title = models.CharField(max_length=250) 

class Person(models.Model):
    name = models.CharField(max_length=200)
    videos = models.ManyToManyField(VideoEmbed, related_name='people', null=True, blank=True)

In this, person_object.videos gives a set of the videos for a person, what isn't obvious is that Django also sets up a reverse relation on Video that is accessible video_object.people that is a set of all Person objects that refer to that specific Video via the ManyToMany Relationship.

This relationship is by default model_name and _set, so for yours the default would be person_set, but by setting the related_name argument in the ManytoManyField it overrides this.

Adding a ForeignKey to the Video model creates and entirely separate and independent relationship.

Consider this simple model where a Video now has an author, and people are tagged in videos (in reality they would probably both go on the video, but we are demonstrating both how the ForeignKey and ManyToMany are independant, and also the value of good semantics for attribute names):

class Video(models.Model):
    title = models.CharField(max_length=250) 
    author = models.ForeignKey('Person')

class Person(models.Model):
    name = models.CharField(max_length=200)
    videos_person_tagged_in = models.ManyToManyField(VideoEmbed, related_name='tagged_people', null=True, blank=True)

Here, setting video_object.author won't change the tagged_people of a video, nor will setting a videos_person_tagged_in for a Person change the author.

As for why the reverse relation for a ManyToMany isn't showing up in Django admin, this is a known issue that requires custom forms to work around. Mostly because you have defined the ManyToMany on one item, it will only show up in that models admin page.

Community
  • 1
  • 1
  • Thanks Lego for a detailed explanation. My understanding from your answer is that I can't get many to many work as per my requirement. Does this also mean I will not be able to at least display 2 fields in person instance on the admin site. so instead of it just showing the title to me it also shows author? – Uma Feb 06 '15 at 06:30
  • It depends. I'd suggest changing your model names and attributes to better match what you are trying to achieve. Videos dinner have people, they have authors, actors, taggers, likers, etc... –  Feb 06 '15 at 06:32
  • You might be able to make it but your code is too vague to understand right now. –  Feb 06 '15 at 06:33
  • If this has been helpful, don't forget to upvote or accept to indicate to future usera that your problem was answered. –  Feb 06 '15 at 06:33
  • is there a particular information you are looking for to be able to provide the solution to the problem. – Uma Feb 06 '15 at 06:37
  • I've explained pretty explicitly what the problem is. **Your models are too vague**. What is a person in relation to a video. –  Feb 06 '15 at 06:39