Rendering user specific data - django

I'm trying to create a webapp which renders data for the user specifically.
I have to models, one for the user (djangos built in User) and one for the data to be rendered.
My model ffor the user:
class UserProfileInfo(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
def __str__(self):
return self.user.username
My model for the data:
class MyModel(models.Model):
user_k = models.ForeignKey(User,related_name='RelatedName',on_delete=models.CASCADE)
Date_Time = models.DateTimeField(default=timezone.now)
DataOne = models.PositiveIntegerField(null=True)
DataTwo = models.PositiveIntegerField(null=True)
DataThree = models.PositiveIntegerField(null=True)
In my views.py file i have this view for it:
class MyView(DetailView):
model = models.User
context_object_name = 'mylist'
template_name = 'my_app/example.html'
def get_queryset(self):
return User.objects.filter(user_k=self.request.user)
And my problem that i can't solve is that I'm getting this error:
Cannot query "user": Must be "MyModel" instance.
I've googled it multiple times also tried the django documentation.
My guess is that the problem might be in the my models, where my intention was to connect my second model to the username, but I'm not sure.
Thanks for your help!

There is no reason User would have a user_k attribute so User.objects.filter(user_k=xxx) makes no sense.
Either use your MyModel model:
class MyView(DetailView):
model = models.MyModel
def get_queryset(self):
return MyModel.objects.filter(user_k=self.request.user)
Or use your UserProfileInfo model:
class MyView(DetailView):
model = models.UserProfileInfo
def get_queryset(self):
return UserProfileInfo.objects.filter(user=self.request.user)

Related

How to retrive data from OneToOne Relational Model in DRF using API view

I have imported User model and customized it a/c to my need and make OneToOne Relation with UserProfileModel Model. While retrieving data I got this error.
"The serializer field might be named incorrectly and not match any attribute or key on the AnonymousUser instance.
Original exception text was: 'AnonymousUser' object has no attribute 'gender'."
My Model is :
class UserProfileModel(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True, related_name='userprofilemodel')
gender = models.CharField(max_length=20)
locality = models.CharField(max_length=70)
city = models.CharField(max_length=70)
address = models.TextField(max_length=300)
pin = models.IntegerField()
state = models.CharField(max_length=70)
profile_image = models.FileField(upload_to='user_profile_image', blank=True)
My Serializer looks like:
class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
model= User
fields = ['id', 'name' , 'email','mobile',]
class UserProfileModelSerializer(serializers.ModelSerializer):
user = serializers.StringRelatedField(many=True, read_only=True)
class Meta:
model= UserProfileModel
fields = ['user','gender' , 'locality','city','address','pin','state','profile_image', ]
My view looks like:
class UserProfileDataView(APIView):
def get(self, request, format=None):
# user = UserProfileModel.objects.all()
serializer = UserProfileModelSerializer(request.user)
return Response(serializer.data, status=status.HTTP_200_OK)
I want to retrieve profile data of the logged user using UserProfileModel Model
Your first issue in that you are passing a User instance to the UserProfileModelSerializer, which is expecting a UserProfileModel instance. To fix this you need to change:
serializer = UserProfileModelSerializer(request.user)
to
serializer = UserProfileModelSerializer(request.user.userprofilemodel)
where userprofilemodel is the related_name you have set on the user field in your UserProfileModel.
Second issue is, as Mohamed Beltagy said, you're allowing anyone to access the view, including unauthenticated users. Django rest framework has a built in mixin that you can use to restrict access to authenticated users only (https://www.django-rest-framework.org/api-guide/permissions/#isauthenticated).
from rest_framework.permissions import IsAuthenticated
class UserProfileDataView(APIView):
permission_classes = [IsAuthenticated]
the problem here is you are passing an anonymous user which has no profile ( you permit non-authenticated users access this view)
def get(self, request, format=None):
# user = UserProfileModel.objects.all()
if request.user.is_authenticated:
serializer = UserProfileModelSerializer(request.user)
return Response(serializer.data, status=status.HTTP_200_OK)
else:
return Response(status=status.HTTP_401_UNAUTHORIZED)

Why Django doesn't update an object?

I have a model Profile, which connects with User.
For example I have Testuser. When I try to update his field 'money', nothing happens. I suppose it may be because I use User, instead of Profile in get_object. But if I change it to Profile, there is an error, that Profile doesn't have username field. How can I solve this problem?
model:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
money = models.IntegerField(default=0)
form:
class AddMoneyForm(forms.ModelForm):
class Meta:
model = Profile
fields = ('money',)
view:
class AddMoneyView(UpdateView):
model = Profile
template_name = 'users/money.html'
fields = ['money']
def get_object(self, queryset=None):
return get_object_or_404(User, username=self.kwargs.get('username'), pk=self.request.user.pk)
def get_success_url(self):
return reverse('account', kwargs={'username': self.request.user.username})
url:
path('account/<str:username>/money/', AddMoneyView.as_view(), name='money'),

How to set read_only dynamically in django rest framework?

I am trying to check if the user id not equal to 1 then he should not be able to update few fields. I tried something similar to the following code but it did not work because of the following issues
self.user.id don't actually return the user I need to get the authenticated user in different why?
the def function maybe should have a different name like update?
also the general way maybe wrong?
class ForAdmins(serializers.ModelSerializer)):
class Meta:
model = User
fields = '__all__'
class ForUsers(serializers.ModelSerializer)):
class Meta:
read_only_fields = ['email','is_role_veryfied','is_email_veryfied']
model = User
fields = '__all__'
class UsersSerializer(QueryFieldsMixin, serializers.ModelSerializer):
def customize_read_only(self, instance, validated_data):
if (self.user.id==1):
return ForAdmins
else:
return ForUsers
class Meta:
# read_only_fields = ['username']
model = User
fields = '__all__'
You can make the decision which serializer you want to pass from your views
or
you can do it inside modelSerializer update method.
for getting user from Serializer class Try:
request = self.context.get('request', None)
if request:
user = request.user
for getting user from View class Try:
user = self.request.user

Querying and Filtering related models in DRF

I have Contact model to list the followers of an User object, I try to filter the contacts of a User but I still could not manage get a correct queryset. My Contact model is simple with two ForeignKey:
class Contact(models.Model):
user_from = models.ForeignKey(User,related_name='rel_from_set', on_delete=models.CASCADE,)
user_to = models.ForeignKey(User,related_name='rel_to_set', on_delete=models.CASCADE,)
def __str__(self):
return '{} follow {}'.format(self.user_from, self.user_to)
I have created serializers for User and Contact:
##Contact Serializer
class ContactsSerializer(serializers.ModelSerializer):
user_from = serializers.StringRelatedField(read_only=True)
user_to = serializers.StringRelatedField(read_only=True)
class Meta:
model = Contact
fields = ["user_from", "user_to"]
##UserSerializer
class UserInformationSerializer(serializers.ModelSerializer):
followers = ContactsSerializer(many=True, read_only=True)
class Meta:
model = User
fields = ['first_name', 'last_name', 'followers']
​
And try to make a query through views:
class FollowerListView(APIView):
queryset = Contact.objects.all()
serializer_class = ContactsSerializer
lookup_field = "username"
def get(self, request, format=None, slug=None):
kwarg_username = self.kwargs.get("slug")
user = User.objects.filter(is_active=1).filter(username=kwarg_username)
print(user.username)
contacts = Contact.objects.filter(user_to=user.id)
serializer = ContactsSerializer(contacts)
return Response(serializer.data)
Now I get error message:
AttributeError at /api/member/ytsejam/followers/
'QuerySet' object has no attribute 'username'
print(user.username)
If i try print(user) I can see the user an Object.
Can you guide me how to correct?
Thanks
filter will always return a queryset. If you expect to retrieve one single item, use get.
So that it looks like that:
def get(self, request, format=None, slug=None):
kwarg_username = self.kwargs.get("slug")
user = User.objects.filter(is_active=1).get(username=kwarg_username)
print(user.username)
contacts = Contact.objects.filter(user_to=user.id)
serializer = ContactsSerializer(contacts)
return Response(serializer.data)
You could, of course, do this on one take:
User.objects.get(is_active=1, username=kwarg_username)
But beware, if there are two rows in your model that would satisfy this call, Django will throw an error. Best make sure that the username has a unique constraint.

Django RF update_or_create

I am trying to update or create the following model:
class Profile(models.Model):
user = models.OneToOneField(AUTH_USER_MODEL, on_delete=models.CASCADE)
canMakeEvent = models.BooleanField(default=False)
with the serializer:
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
fields = '__all__'
and view:
def post(self, request):
answer, created = Profile.objects.update_or_create(
user=request.user, canMakeEvent = request.data['canMakeEvent'])
return Response()
I understand the response isn't correct but the code to update_or_create is what I'm worried about primarily. The console outputs the following:
UNIQUE constraint failed: event_profile.user_id
You need to add defaults argument to perform search only by user_id not by combination of (user_id, canMakeEdit):
answer, created = Profile.objects.update_or_create(
user=request.user, defaults={'canMakeEvent': request.data['canMakeEvent']})
This will allow to update existing profile of selected user if it exists or create new otherwise.