Django Reverse Accessor Clashes

匿名 (未验证) 提交于 2019-12-03 01:18:02

问题:

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'. 

回答1:

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') 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!