Reputation: 107
Thank you so much for your help, i really appreciate it.
I get this error "'tuple' object has no attribute 'user'" Anybody can tell me if my codes is right. im trying to make artist followers system.
View.py
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def artist_follow(request, pk):
artist = Artist.objects.get(pk=pk)
current_user = User.objects.get(pk=request.user.id)
# check the current user already followed the artsit, if exist remove it else add
if artist.followers().user.filter(user=current_user).exists(): # This line throw error
artist.followers().user.remove(current_user)
else:
artist.followers().user.add(current_user)
return Response(status=status.HTTP_200_OK)
Model.py
class Artist(models.Model):
name = models.CharField(unique=True, max_length=100)
.....
def __str__(self):
return self.name
def followers(self):
return ArtistFollower.objects.get_or_create(artist=self)
class ArtistFollower(models.Model):
artist = models.OneToOneField(Artist, on_delete=models.CASCADE)
user = models.ManyToManyField(User, related_name='user_artist_followed')
def __str__(self):
return self.artist.name
Traceback
Traceback (most recent call last):
File "/opt/anaconda3/envs/app-ENV/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/opt/anaconda3/envs/app-ENV/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/opt/anaconda3/envs/app-ENV/lib/python3.8/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/opt/anaconda3/envs/app-ENV/lib/python3.8/site-packages/django/views/generic/base.py", line 70, in view
return self.dispatch(request, *args, **kwargs)
File "/opt/anaconda3/envs/app-ENV/lib/python3.8/site-packages/rest_framework/views.py", line 509, in dispatch
response = self.handle_exception(exc)
File "/opt/anaconda3/envs/app-ENV/lib/python3.8/site-packages/rest_framework/views.py", line 469, in handle_exception
self.raise_uncaught_exception(exc)
File "/opt/anaconda3/envs/app-ENV/lib/python3.8/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
raise exc
File "/opt/anaconda3/envs/app-ENV/lib/python3.8/site-packages/rest_framework/views.py", line 506, in dispatch
response = handler(request, *args, **kwargs)
File "/opt/anaconda3/envs/app-ENV/lib/python3.8/site-packages/rest_framework/decorators.py", line 50, in handler
return func(*args, **kwargs)
File "/Users/username/Desktop/Clients/app/source/app/artists/web/views.py", line 44, in artist_follow
if artist.followers().user.filter(user=current_user).exists():
Exception Type: AttributeError at /api/v1/web/artists/1/follow
Exception Value: 'tuple' object has no attribute 'user'
Upvotes: 1
Views: 685
Reputation: 476557
Your .followers()
method uses .get_or_create(…)
[Django-doc], and thus:
Returns a tuple of
(object, created)
, where object is the retrieved or created object and created is a boolean specifying whether a new object was created.
You can return the item that is obtained or constructed by subscripting:
class Artist(models.Model):
# …
def followers(self):
return ArtistFollower.objects.get_or_create(artist=self)[0]
or work with a throw away variable:
class Artist(models.Model):
# …
def followers(self):
obj, __ = ArtistFollower.objects.get_or_create(artist=self)
return obj
It however does not seem to make much sense to create a ArtistFollower
model. Why not create a ManyToManyField
to the User
class in Artist
model. This will simplify the modeling, and reduce the size of the database.
Such model thus looks like:
from django.conf import settings
class Artist(models.Model):
name = models.CharField(unique=True, max_length=100)
followers = models.ManyToManyField(
settings.AUTH_USER_MODEL,
related_name='following_artists'
)
You thus can then access the followers of an artist with:
my_artist.followers.all() # queryset of User objects
or for a user the artists they are following with:
my_user.following_artists.all()
You can also edit the ManyToManyField
at both directions. For more information, see te section on many-to-many relations of the documentation.
Note: It is normally better to make use of the
settings.AUTH_USER_MODEL
[Django-doc] to refer to the user model, than to use theUser
model [Django-doc] directly. For more information you can see the referencing theUser
model section of the documentation.
Upvotes: 1