Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Reverse Accessor Clashes

Tags:

django

So here I'm having lots of problems with reverse accessor clashes. I though I was being pretty clever and DRY with my model structure to be able to use user.profile for any kind of profile, or to use provider.profile for either provider... but I'm getting clash errors all over the place.

Mind taking a look at my code and seeing if there is any way for me to finagle this so I can still user just the user.profile without needing to know which kind of profile (and likewise provider.profile without needing to know which kind of provider)? Or just telling me that what I'm trying to do is impossible and any better solutions?

class BaseProfileModel(models.Model):
    '''
    An abstract model class containing fields and/or methods relevant to all users.
    '''
    user = models.OneToOneField(User, related_name="profile", primary_key=True)
    phone = PhoneNumberField(verbose_name=_("Phone Number"))
    pic = models.ImageField(upload_to=get_upload_file_name,
                            width_field="width_field",
                            height_field="height_field",
                            null=True,
                            blank=True,
                            verbose_name=_("Profile Picture")
                           )
    height_field = models.PositiveIntegerField(null=True, default=0)
    width_field = models.PositiveIntegerField(null=True, default=0)
    thumbnail = ImageSpecField(source='pic',
                                   processors=[ResizeToFill(180,180)],
                                   format='JPEG',
                                   options={'quality': 100})
    bio = models.TextField(
        verbose_name=_("About"),
        default="",
        blank=True,
        max_length=800
    )

    class Meta:
        abstract = True

    def __str__(self):
        if self.user.email:
            return self.user.email
        else:
            return self.user.username

    @property
    def is_provider(self):
        return hasattr(self, 'provider')

    def get_absolute_url(self):
        return reverse_lazy(self.profile_url_name, kwargs={'pk': self.pk})

    # Methods

class BaseHumanProfileModel(BaseProfileModel):
    '''
    Abstract base class containing fields relevant to human users
    '''
    birth_date = models.DateField(verbose_name=_("Date of Birth"))
    GENDER_CHOICES = (
        ('M', _('Male')),
        ('F', _('Female')),
        ('N', _('Not Specified')),
    )
    gender = models.CharField(
        max_length=1, choices=GENDER_CHOICES, default='N', verbose_name=_('Gender'))

    class Meta:
        abstract = True

class CustomerProfile(BaseHumanProfileModel):
    '''
    Concrete Human subclass for the consumers
    '''
    home_location = models.OneToOneField(
        Location,
        related_name='customer',
        null=True,
        blank=True,
        on_delete=models.SET_NULL
        )
    profile_url_name = 'profiles:customer_profile'

    # Methods

class Provider(models.Model):
    '''
    Class containing information needed for providers
    Other models (provider profiles, reviews, events, etc.) will use this class
    as ForeignKey to interface with functionalities related to creating and managing
    sessions/listings.
    '''
    stripe_access_token = models.TextField(blank=True, default='')

    # Methods....


class IndividualProviderProfile(BaseHumanProfileModel):
    '''
    Concrete subclass for representing the profile of an individual provider.
    '''
    provider = models.OneToOneField(Provider, related_name='profile')
    locations = models.ManyToManyField(Location, null=True, blank=True, related_name='individual_providers')
    specialties = models.CharField(
        verbose_name=_("Specialties"),
        max_length=200,
        blank=True,
    )
    certifications = models.CharField(
        verbose_name=_("Certifications"),
        max_length=200,
        blank=True,
    )
    profile_url_name = 'profiles:individual_provider_profile'

    # methods


class OrganizationProviderProfile(BaseProfileModel):
    '''
    Profile representing a provider that is an organization.
    Contains key to provider class for interfacing with session scheduling
    Also contains set of individual providers that work for the organization.
    '''
    provider = models.OneToOneField(Provider, related_name='profile')
    website = models.URLField(blank=True)
    location = models.ForeignKey(Location, related_name='organization')
    employees = models.ManyToManyField(IndividualProviderProfile, null=True, blank=True, related_name='organization')

    @property
    def locations(self):
        return Locations.objects.filter(pk=self.location.pk)

    profile_url_name = 'profiles:organization_provider_profile'

    #methods

Now when I try to sync the db I get this rather long and intense set of warnings:

CommandError: System check identified some issues:

ERRORS:
profiles.CustomerProfile.user: (fields.E304) Reverse accessor for 'CustomerProfile.user' clashes with reverse accessor for 'OrganizationProviderProfile.user'.
    HINT: Add or change a related_name argument to the definition for 'CustomerProfile.user' or 'OrganizationProfile.user'.
profiles.CustomerProfile.user: (fields.E304) Reverse accessor for 'CustomerProfile.user' clashes with reverse accessor for 'IndividualProviderProfile.user'.
    HINT: Add or change a related_name argument to the definition for 'CustomerProfile.user' or 'IndividualProviderProfile.user'.
profiles.CustomerProfile.user: (fields.E305) Reverse query name for 'CustomerProfile.user' clashes with reverse query name for 'OrganizationProviderProfile.user'.
    HINT: Add or change a related_name argument to the definition for 'CustomerProfile.user' or 'OrganizationProviderProfile.user'.
profiles.CustomerProfile.user: (fields.E305) Reverse query name for 'CustomerProfile.user' clashes with reverse query name for 'IndividualProviderProfile.user'.
    HINT: Add or change a related_name argument to the definition for 'CustomerProfile.user' or 'IndividualProviderProfile.user'.
profiles.OrganizationProfile.provider: (fields.E304) Reverse accessor for 'OrganizationProviderProfile.provider' clashes with reverse accessor for 'IndividualProviderProfile.provider'.
    HINT: Add or change a related_name argument to the definition for 'OrganizationProviderProfile.provider' or 'IndividualProviderProfile.provider'.
profiles.OrganizationProviderProfile.provider: (fields.E305) Reverse query name for 'OrganizationProviderProfile.provider' clashes with reverse query name for 'IndividualProviderProfile.provider'.
    HINT: Add or change a related_name argument to the definition for 'OrganizationProviderProfile.provider' or 'IndividualProviderProfile.provider'.
profiles.OrganizationProviderProfile.user: (fields.E304) Reverse accessor for 'OrganizationProviderProfile.user' clashes with reverse accessor for 'CustomerProfile.user'.
    HINT: Add or change a related_name argument to the definition for 'OrganizationProviderProfile.user' or 'CustomerProfile.user'.
profiles.OrganizationProviderProfile.user: (fields.E304) Reverse accessor for 'OrganizationProviderProfile.user' clashes with reverse accessor for 'IndividualProviderProfile.user'.
    HINT: Add or change a related_name argument to the definition for 'OrganizationProviderProfile.user' or 'IndividualProvider.user'.
profiles.OrganizationProviderProfile.user: (fields.E305) Reverse query name for 'OrganizationProviderProfile.user' clashes with reverse query name for 'CustomerProfile.user'.
    HINT: Add or change a related_name argument to the definition for 'OrganizationProviderProfile.user' or 'CustomerProfile.user'.
profiles.OrganizationProviderProfile.user: (fields.E305) Reverse query name for 'OrganizationProviderProfile.user' clashes with reverse query name for 'IndividualProviderProfile.user'.
    HINT: Add or change a related_name argument to the definition for 'OrganizationProviderProfile.user' or 'IndividualProvider.user'.
profiles.IndividualProviderProfile.provider: (fields.E304) Reverse accessor for 'IndividualProviderProfile.provider' clashes with reverse accessor for 'OrganizationProviderProfile.provider'.
    HINT: Add or change a related_name argument to the definition for 'IndividualProviderProfile.provider' or 'OrganizationProviderProfile.provider'.
profiles.IndividualProviderProfile.provider: (fields.E305) Reverse query name for 'IndividualProviderProfile.provider' clashes with reverse query name for 'OrganizationProviderProfile.provider'.
    HINT: Add or change a related_name argument to the definition for 'IndividualProviderProfile.provider' or 'OrganizationProviderProfile.provider'.
profiles.IndividualProviderProfile.user: (fields.E304) Reverse accessor for 'IndividualProviderProfile.user' clashes with reverse accessor for 'CustomerProfile.user'.
    HINT: Add or change a related_name argument to the definition for 'IndividualProviderProfile.user' or 'CustomerProfile.user'.
profiles.IndividualProviderProfile.user: (fields.E304) Reverse accessor for 'IndividualProviderProfile.user' clashes with reverse accessor for 'OrganizationProviderProfile.user'.
    HINT: Add or change a related_name argument to the definition for 'IndividualProviderProfile.user' or 'OrganizationProviderProfile.user'.
profiles.IndividualProviderProfile.user: (fields.E305) Reverse query name for 'IndividualProviderProfile.user' clashes with reverse query name for 'CustomerProfile.user'.
    HINT: Add or change a related_name argument to the definition for 'IndividualProviderProfile.user' or 'CustomerProfile.user'.
profiles.IndividualProviderProfile.user: (fields.E305) Reverse query name for 'IndividualProviderProfile.user' clashes with reverse query name for 'OrganizationProviderProfile.user'.
    HINT: Add or change a related_name argument to the definition for 'IndividualProviderProfile.user' or 'OrganizationProviderProfile.user'.
like image 694
rfj001 Avatar asked Nov 16 '14 08:11

rfj001


1 Answers

related_name's must be unique. You're giving the same name to all the related_name's.

Try to rename them like this:

user = models.OneToOneField(User, related_name="custom_user_profile", primary_key=True)
#..
provider = models.OneToOneField(Provider, related_name='user_ind_provider_profile')
#..
provider = models.OneToOneField(Provider, related_name='user_org_provider_profile')
like image 152
doniyor Avatar answered Nov 09 '22 22:11

doniyor