Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

django intermediate model with no foreign key error

Building some complex models for my django app and got some help here:

Using ManyToMany through correctly for complex model in django

To which the result was getting this far here:

ipaswdb.ProviderLocations: (fields.E336) The model is used as an intermediate model by 'ipaswdb.Group.providers', but it does not have a foreign key to 'Group' or 'Provider'.

I mean yes the error is i n english but I do not know what it is really trying to tell me.

Full models below, but the idea was to have A group having many locations.

A provider belonging to a group via whichever location(s) they work at, secondly a provider can belong to many groups at many locations

Provider A -> location 1
         -> location 2
         -> location 3

Group 1 -> has a location 1
        -> has a location 2

Group 2 -> has a location 3
        -> has a location 4

Provider A belongs to group 1 and 2 via locations 1,2,3

My full models are:

class Group(models.Model):
    group_name = models.CharField(max_length=50)

    created_at=models.DateField(auto_now_add=True)
    updated_at=models.DateField(auto_now=True)
    providers = models.ManyToManyField('Provider', through='ProviderLocations')




class Provider(models.Model):
    first_name = models.CharField(max_length = 50)

    created_at=models.DateField(auto_now_add=True)
    updated_at=models.DateField(auto_now=True)



class ProviderLocations(models.Model):
    provider = models.ForeignKey('Provider', on_delete=models.CASCADE)
    group_location = models.ForeignKey('GroupLocations', on_delete=models.CASCADE)
    created_at=models.DateField(auto_now_add=True)
    updated_at=models.DateField(auto_now=True)

class GroupLocations(models.Model):
    address = models.ForeignKey('Address', on_delete= models.SET_NULL, null=True)
    group = models.ForeignKey('Group', on_delete=models.SET_NULL, null=True)
    doing_business_as = models.CharField(max_length = 255)
    created_at=models.DateField(auto_now_add=True)
    updated_at=models.DateField(auto_now=True)

I tried an edit on the ProviderLocations too with no results:

class ProviderLocations(models.Model):
    provider = models.ForeignKey('Provider', on_delete=models.CASCADE)
    group = models.ManyToManyField('Group', through='GroupLocations')
    created_at=models.DateField(auto_now_add=True)
    updated_at=models.DateField(auto_now=True)
like image 422
Codejoy Avatar asked Oct 31 '22 01:10

Codejoy


1 Answers

When you set up the intermediary model, you explicitly specify foreign keys to the models that are involved in the many-to-many relationship. This explicit declaration defines how the two models are related

Group (not GroupLocations) and Provider are the ones in the M2M relationship so the throughmodel ProviderLocations must be linked to their ForeignKeys:

class ProviderLocations(models.Model):
    provider = models.ForeignKey('Provider', on_delete=models.CASCADE)
    group = models.ForeignKey('Group', on_delete=models.CASCADE)

As is, each provider has a set of groups and each group has a set of group locations and you can walk through that hierarchy to fetch your objects.

You can make provider part of a group via group locations by eliminating the ProviderLocations model and using GroupLocations as the throughmodel:

class Group(models.Model):
    group_name = models.CharField(max_length=50)

    created_at=models.DateField(auto_now_add=True)
    updated_at=models.DateField(auto_now=True)
    providers = models.ManyToManyField('Provider', through='GroupLocations')


class Provider(models.Model):
    first_name = models.CharField(max_length = 50)

    created_at=models.DateField(auto_now_add=True)
    updated_at=models.DateField(auto_now=True)


class GroupLocations(models.Model):
    provider = models.ForeignKey('Provider', on_delete=models.CASCADE)
    group = models.ForeignKey('Group', on_delete=models.SET_NULL, null=True)
    address = models.ForeignKey('Address', on_delete= models.SET_NULL, null=True)
    doing_business_as = models.CharField(max_length = 255)
    created_at=models.DateField(auto_now_add=True)
    updated_at=models.DateField(auto_now=True)
like image 150
Moses Koledoye Avatar answered Nov 08 '22 06:11

Moses Koledoye