Jay Jung
Jay Jung

Reputation: 1885

How do I retrieve and return an instance from my Class-Based Detail view?

I have two linked models:

class MyUser(AbstractBaseUser, PermissionsMixin):
    username = models.CharField(max_length=24, unique=True)
    profile_page = models.OneToOneField(Profile, null=True)  

class Profile(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True, blank=True)  

I am attempting to retrieve and return an instance of a single user's profile in this CBV:

class ProfileView(DetailView):
    queryset = Profile.objects.all()
    template_name = 'profile_detail.html'

    def get_object(self, *args, **kwargs):
        user_profile = self.kwargs.get('username')
        obj = get_object_or_404(Profile, user=user_profile)
        return obj  

The get_object_or_404 call causes the following exception: invalid literal for int() with base 10: 'adam'
"adam" because I am requesting the page url: http://127.0.0.1:8000/profile/adam

Here are my url patterns:

urlpatterns = [
    url(r'^edit/', profile_edit, name='profile_edit'),
    url(r'^(?P<username>[\w.@+-]+)$', ProfileView.as_view(), name='profile'),
]  

(Just in case: these also belong in the namespaced /profile/)

I'm trying to access the model fields within the Profile model. Why is it that I receive the error when trying to return obj to my profile_detail.html template?

What I've tried:
If I change the URL regex to accept ID or PK instead of <username> and access the url of /profile/1, I receive: TypeError at /profile/1 __str__ returned non-string (type MyUser). If I then update my code to be:

def get_object(self, *args, **kwargs):
    user_profile = self.kwargs.get('id')
    obj = get_object_or_404(Profile, user=user_profile)
    objj = obj.user
    return objj  

then the errors clear and I can somewhat get things to appear on the profile_detail.html page. However, the {{object}} refers to the MyUser model, and not the Profile model as I desired.
What might be going on? Does it have something to do with

def __str__(self):
    return self.username  

in the models?

edit: string method for my Profile model:

def __str__(self):
    return self.user  

Upvotes: 0

Views: 67

Answers (1)

Alasdair
Alasdair

Reputation: 309089

You are including the username in the url, not the user id. Therefore you need to change the get_object_or_404 line as follows:

self.kwargs.get('username')
obj = get_object_or_404(Profile, user__username=user_profile)

As the error message __str__ returned non-string (type MyUser) suggests, your Profile.__str__ method should be returning a string, for example:

def __str__(self):
    return self.user.username

Finally, you appear to have two OneToOneFields, MyUser.profile_page and Profile.user. This is unnecessary. If you remove the MyUser.profile_page field, then you can follow the Profile.user relationship backwards from MyUser to Profile with user.profile.

Upvotes: 2

Related Questions