1
votes

I'm trying to apply HyperlinkedModelSerializer to my User_Info model. When I try to do so I get an error saying:

Could not resolve URL for hyperlinked relationship using view name "user_info-detail". You may have failed to include the related model in your API, or incorrectly configured the lookup_field attribute on this field.

I am supplying my models, views, serializers, and urls below. Could it be that I am inheriting from AbstractBaseUser in my model rather than models.Model?

models.py

class My_User_Info_Manager(BaseUserManager):
    def create_user(self, email, name=None, password=None, phone_number=None, reseller=None):
        user = self.model(
            email = self.normalize_email(email),
            name = name,
            phone_number = phone_number,
            reseller = reseller,

            )
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, name=None, password=None):
        user = self.create_user(
            email, name=name, password=password
        )
        user.is_superuser = True
        user.is_staff = True
        user.save(using=self._db)
        return user



class User_Info(AbstractBaseUser):

    email = models.EmailField(max_length=225,
                              unique=True, db_index=True, primary_key=True)

    name = models.CharField(max_length=255, null=False)


    phone_number = models.CharField(max_length=30, null=True)
    reseller = models.CharField(max_length=255, null=True)
    username = "Required for FTP Services"

    ### attributes and methods for superuser to access django admin
    is_superuser = models.BooleanField(default=False)
    is_staff = models.BooleanField(default=False)

    def has_perm(self, perm, obj=None):
        return self.is_superuser

    def has_module_perms(self, app_label):
        return self.is_superuser


    objects = My_User_Info_Manager()

    USERNAME_FIELD = 'email'

serializers.py

class UserInfoSerializer(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = User_Info # get model

        # add the fields
        fields = '__all__'

views.py

class UserInfoViewSet(viewsets.ModelViewSet):
    """
    Provides `list`, `create`, `retrieve`, `update`, `partial_update` and `destroy` actions for the Users 
    model.

    Overrides 'create' action hash the password from the POST payload.

    The User_Info model is a profile of a seller that can be used to log into the seller side of the web
    app. It contains relevant information about the reseller themselves.
    """

    queryset = User_Info.objects.all()
    serializer_class = UserInfoSerializer
    permission_classes = [IsAuthenticated]

    # override create method to has the password
    def create(self, request):
        request.data['password'] = make_password(request.data['password']) #hash password
        return super().create(request)

urls.py

# urls for ViewSets
router = DefaultRouter()
router.register(r'accounts', accounts_views.AccountsViewSet)
router.register(r'activity', activity_views.ActivityViewSet)
router.register(r'customers', customers_views.CustomersViewSet)
router.register(r'users', users_views.UserInfoViewSet)
router.register(r'products', products_views.ProductsViewSet)
router.register(r'payments', payments_views.PaymentsViewSet)

urlpatterns = [
    path('', include(router.urls)),
    path('admin/', admin.site.urls),
    path(r'api-token-auth/', obtain_jwt_token),
    path(r'api-token-refresh/', refresh_jwt_token),
    path('tax/', include('tax.urls')),
    # path('cdr/', include('cdr.urls')),

]
1

1 Answers

1
votes

You should serializer url in UserInfoSerializer, like

url = serializers.HyperlinkedRelatedField(
        view_name='user_info-detail', source='user_info', read_only=True)

serializers.py

class UserInfoSerializer(serializers.HyperlinkedModelSerializer):
    url = serializers.HyperlinkedRelatedField(
    view_name='user_info-detail', source='user_info', read_only=True)

    class Meta:
        model = User_Info # get model

        # add the fields
        fields = '__all__'

In urls.py, update:

router.register(r'users', users_views.UserInfoViewSet)

to

router.register(r'users', users_views.UserInfoViewSet, base_name='user_info')

Suggestion: let change from user_info to user or User_Info to User only in your naming convention.