Django Rest Access Model Values in Another Model - python

I am new on Django and I have some issues about Rest API. I want to access User Model Values from Project Model. I have User JSON like this:
[
{
"id": 15,
"first_name": "Ebrar",
"last_name": "Bilgili",
"university": "Bahçeşehir University",
"faculty": "Software Engineering",
"user": 17
},
]
And also I have Project JSON like this:
{
"id": 4,
"title": "teammate",
"city": "istanbul",
"user": 17,
"user_profile": 15
}
But I want to access User First name, Last name, University and Faculty values in Project JSON like this:
{
"id": 4,
"title": "teammate",
"city": "istanbul",
"user": 17,
"user_profile": {
"first_name": "Ebrar",
"last_name": "Bilgili",
"university": "Bahçeşehir University",
"faculty": "Software Engineering",
}
}
I have many researched but I could not find any solution. I searched all the methods that came to my mind.. I hope you help me. Thanks.
My models.py:
class User(AbstractUser):
username = models.CharField(max_length=250, unique=True)
email = models.EmailField(max_length=50, unique=True)
password = models.CharField(max_length=250)
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email']
class UserProfile(models.Model):
user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
first_name = models.CharField(max_length=250)
last_name = models.CharField(max_length=250)
university = models.CharField(max_length=250)
faculty = models.CharField(max_length=250)
class Meta:
ordering = ["first_name"]
def __str__(self):
return "%s %s" % (self.first_name, self.last_name)
class Project(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
user_profile = models.ForeignKey(
'UserProfile', related_name='name', on_delete=models.CASCADE)
title = models.CharField(max_length=200)
city = models.CharField(max_length=50)
def __str__(self):
return self.title
and my serializers.py:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'
extra_kwargs = {
'password': {'write_only': True}
}
def create(self, validated_data):
password = validated_data.pop('password', None)
instance = self.Meta.model(**validated_data)
if password is not None:
instance.set_password(password)
instance.save()
return instance
class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
fields = '__all__'
class ProjectSerializer(serializers.ModelSerializer):
class Meta:
model = Project
fields = '__all__'
and views.py:
class RegisterView(APIView):
def post(self, request):
serializer = UserSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data)
class LoginView(APIView):
def post(self, request):
email = request.data['email']
password = request.data['password']
user = User.objects.filter(email=email).first()
if user is None:
raise AuthenticationFailed('User not found!')
if not user.check_password(password):
raise AuthenticationFailed("Incorrect password!")
payload = {
'id': user.id,
'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=60),
'iat': datetime.datetime.utcnow()
}
token = jwt.encode(payload, 'secret', algorithm='HS256')
response = Response()
response.set_cookie(key='token', value=token, httponly=True)
response.data = {
'id': user.id,
'username': user.username,
'token': token
}
return response
class UserView(APIView):
def get(self, request):
token = request.COOKIES.get('token')
if not token:
raise AuthenticationFailed('Unauthenticated!')
try:
payload = jwt.decode(token, 'secret', algorithms=['HS256'])
except jwt.ExpiredSignatureError:
raise AuthenticationFailed('Unautheticated!')
user = User.objects.filter(id=payload['id']).first()
serializer = UserSerializer(user)
return Response(serializer.data)
class UserProfileView(APIView):
def post(self, request):
serializer = UserProfileSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def put(self, request):
serializer = UserProfileSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def get(self, request):
try:
id = request.query_params['id']
if id != None:
user = UserProfile.objects.get(id=id)
serializer = UserProfileSerializer(user)
except:
users = UserProfile.objects.all()
serializer = UserProfileSerializer(users, many=True)
return Response(serializer.data)
class ProjectView(APIView):
def post(self, request):
serializer = ProjectSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def get(self, request):
try:
id = request.query_params['id']
if id != None:
project = Project.objects.get(id=id)
serializer = ProjectSerializer(project)
except:
projects = Project.objects.all()
serializer = ProjectSerializer(projects, many=True)
return Response(serializer.data)

Try this:
class ProjectSerializer(serializers.ModelSerializer):
user_profile = UserProfileSerializer()
class Meta:
model = Project
fields = '__all__'

Related

Django Rest Framework: How to request data validate before serializers?

I want to validate email variable before UserSerializer, and then return filtered data. The following code works; but I declared "serializer" twice. If I want to use serializer once, how can I do it?
views.py
#api_view(['GET'])
def get_user(request):
email = request.data.get('email')
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
Users = User.objects.filter(email=email)
serializer = UserSerializer(Users, many= True)
return Response({"status": "success", "data": serializer.data})
else:
return Response({"status": "errors", "data": serializer.errors})
serializers.py
class UserSerializer(serializers.ModelSerializer):
email = serializers.EmailField(required=True)
phone = serializers.CharField(required=False)
sex = ChoiceField(required=False, choices=User.TYPE_CHOICES)
class Meta:
model = User
fields = ('id', 'email', 'phone', 'name','sex', 'updated', 'created')
models.py
class User(models.Model):
TYPE_CHOICES = (
('0', 'men'),
('1', 'girl'),
('2', 'nobody'),
)
email = models.EmailField(unique=True, max_length=50)
phone = models.TextField(unique=True, max_length=11)
name = models.TextField(default="AKA")
sex = models.CharField(
max_length=2,
choices=TYPE_CHOICES,
default="0"
)
updated = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = "users"
User anether serializer for Validating Email
class EmailSerializer(serializers.Serializer):
email = serializers.EmailField(required=True)
#api_view(['GET'])
def get_user(request):
serializer = EmailSerializer(data=request.data)
if serializer.is_valid():
email = serializer.validated_data['email']
Users = User.objects.filter(email=email)
serializer = UserSerializer(Users, many= True)
return Response({"status": "success", "data": serializer.data})
else:
return Response({"status": "errors", "data": serializer.errors})

Custom Model relation with Django User Model Pls help i am new to Django rest Api

I am new to Django Rest API for user model i am using Django default user model. my end end goal is when user login he will able to see data only related to him
I want my value like this
{ "user": 1
{
"id": 1,
"rent_date": "23-08-2022",
"rentmonth": "June",
"rent_amount": 5000.0,
"bijli_bill": 250.0,
"other_amount": 150.0,
"other_commnet": "test",
"total_amount": 5400.0,
"total_rent_amount": 17000.0,
}
}
But Getting like this, user showing under rent model
{
"status": "success",
"data": [
{
"id": 1,
"rent_date": "23-08-2022",
"rentmonth": "June",
"rent_amount": 5000.0,
"bijli_bill": 250.0,
"other_amount": 150.0,
"other_commnet": "test",
"total_amount": 5400.0,
"total_rent_amount": 17000.0,
"user": 1
},
{
"id": 2,
"rent_date": "23-08-2022",
"rentmonth": "July",
"rent_amount": 6000.0,
"bijli_bill": 250.0,
"other_amount": 150.0,
"other_commnet": "test",
"total_amount": 6400.0,
"total_rent_amount": 17000.0,
"user": 2
},
This is my Model.py
from django.contrib.auth.models import User
class rent(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
rent_date = models.DateField(auto_now_add=True)
rentmonth = models.CharField(max_length=30)
rent_amount = models.FloatField()
bijli_bill = models.FloatField()
other_amount = models.FloatField(blank=True)
other_commnet = models.CharField(blank=True, max_length=200)
#property
def total_amount(self):
return self.rent_amount + self.bijli_bill + self.other_amount
this my serializers.py
from rest_framework import serializers
from .models import rent
from django.contrib.auth.models import User
from django.db.models import Sum
class rentSerializer(serializers.ModelSerializer):
rent_date = serializers.DateField(format="%d-%m-%Y", read_only=True)
rentmonth = serializers.CharField()
rent_amount = serializers.FloatField()
bijli_bill = serializers.FloatField()
other_amount = serializers.FloatField()
other_commnet = serializers.CharField(max_length=200)
total_amount = serializers.FloatField()
total_rent_amount = serializers.SerializerMethodField()
class Meta:
model = rent
fields = ('__all__')
def get_total_rent_amount(self, obj):
totalprice = rent.objects.all().aggregate(total_price=Sum('rent_amount'))
return totalprice["total_price"]
# User Serializer
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', 'username', 'email')
# Register Serializer
class RegisterSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', 'username', 'email', 'password')
extra_kwargs = {'password': {'write_only': True}}
def create(self, validated_data):
user = User.objects.create_user(validated_data['username'], validated_data['email'], validated_data['password'])
return user
Here is my view.py
class rentViews(APIView):
def post(self, request):
serializer = rentSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response({"status": "success", "data": serializer.data}, status=status.HTTP_200_OK)
else:
return Response({"status": "error", "data": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
def get(self, request, id=None):
if id:
item = rent.objects.get(id=id)
serializer = rentSerializer(item)
return Response({"status": "success", "data": serializer.data}, status=status.HTTP_200_OK)
items = rent.objects.all()
serializer = rentSerializer(items, many=True)
return Response({"status": "success", "data": serializer.data}, status=status.HTTP_200_OK)
def patch(self, request, id=None):
item = rent.objects.get(id=id)
serializer = rentSerializer(item, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
return Response({"status": "success", "data": serializer.data})
else:
return Response({"status": "error", "data": serializer.errors})
def delete(self, request, id=None):
item = get_object_or_404(rent, id=id)
item.delete()
return Response({"status": "success", "data": "Item Deleted"})
###############################UserAPI#######################################
# Register API
class RegisterAPI(generics.GenericAPIView):
serializer_class = RegisterSerializer
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.save()
return Response({
"user": UserSerializer(user, context=self.get_serializer_context()).data,
"token": AuthToken.objects.create(user)[1]
})
# Login API
class LoginAPI(KnoxLoginView):
permission_classes = (permissions.AllowAny,)
def post(self, request, format=None):
serializer = AuthTokenSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.validated_data['user']
login(request, user)
return super(LoginAPI, self).post(request, format=None)

Method GET not allowed when PATCH Null Value in Django Rest Framework

I have a problem with PATCH Null Value in Django Rest Framework with Extend User Model. Please take a look my issues!
Serializers:, Profile is extend User Model
class UserEditSerializer(ModelSerializer):
job_title = serializers.CharField(source='profile.job_title')
class Meta:
model = User
fields = [
'username',
'job_title',
]
def update(self, instance, validated_data):
instance.username = validated_data.get('username', instance.username)
instance.save()
if (validated_data.get('profile') is not None):
profile_data = validated_data.pop('profile')
profile = instance.profile
profile.job_title = profile_data.get('job_title', profile.job_title)
My viewsets:
class UserUpdateAPIView(ReadOnlyModelViewSet):
queryset = User.objects.all()
serializer_class = UserEditSerializer
permission_classes = (IsAuthenticated,)
#detail_route(methods=['PATCH'])
def edit(self, request):
user_obj = User.objects.get(id=request.user.id)
serializer = UserEditSerializer(user_obj, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return JsonResponse({'message': 'Error'}, status=500)
My api patch request to server:
{
"job_title": ""
}
Error:
{
"detail": "Method \"GET\" not allowed."
}
Error Photo

Django Rest framework nested serializer not returning relation values in validated_data

I have defined everything correctly. (GET is working correctly) I can get the user detail through nested serializer. But when I do PUT I am not getting validated_data in update method which is in UserSerializer.
models.py
class UserProfile(models.Model):
user = models.ForeignKey(User, related_name='users',
on_delete=models.CASCADE)
phone_number = models.CharField(max_length=15)
known_languages = models.CharField(max_length=100)
date_updated = models.DateTimeField(auto_now=True)
user_domain = models.CharField(max_length=100, default=None)
serializers.py
class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
fields = ['phone_number', 'known_languages', 'user_domain']
class UserSerializer(serializers.ModelSerializer):
users = UserProfileSerializer()
class Meta:
model = User
fields = ['first_name', 'last_name', 'username', 'email', 'users']
def update(self, instance, validated_data):
import pdb;pdb.set_trace()
#here I am not getting users value. it is returning empty list
return instance
views.py
def put(self, request, pk):
user_obj = self.get_object(pk)
request.POST._mutable = True
request.data['users'] = { 'phone_number': request.data.pop('phone_number'), 'user_domain': request.data.pop('user_domain'), 'known_languages': request.data.pop('known_languages') }
request.POST._mutable = False
serializer = UserSerializer(user_obj, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Can any one help on it......
data = request.data.dict()
data['users'] = { 'phone_number': request.data.pop('phone_number'), 'user_domain': request.data.pop('user_domain'), 'known_languages': request.data.pop('known_languages') }
serializer = UserSerializer(user_obj, data=data, partial=True )
works perfect for me
remove this three lines:
request.POST._mutable = True
request.data['users'] = { 'phone_number': request.data.pop('phone_number'), 'user_domain': request.data.pop('user_domain'), 'known_languages': request.data.pop('known_languages') }
request.POST._mutable = False
and just use inside update:
def update(self, instance, validated_data):
request = self.context.get('request')
data = request.data.copy()
users = {
'phone_number': data.get('phone_number'),
'user_domain': data.get('user_domain'),
'known_languages': data.get('known_languages')
}
# your code ...

I get some troubles with post and save serializer

serializers.py:
class SnippetSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
class Meta:
model = Snippet
fields = ('id', 'title','owner', 'code', 'linenos', 'language', 'style')
def create(self, validated_data):
owner=validated_data.pop('owner')
try:
owner=User.objects.get(username=owner)
snippet=Snippet.objects.create(owner=owner,**validated_data)
return snippet
except:
return Http404
view.py:
class SnippetList(APIView):
"""
List all snippets, or create a new snippet.
"""
permission_classes = (permissions.IsAuthenticatedOrReadOnly,IsOwnerOrReadOnly,)
def get(self, request, format=None):
snippets = Snippet.objects.all()
serializer = SnippetSerializer(snippets, many=True)
return Response(serializer.data)
def post(self, request, format=None):
data=request.data
data['owner']=request.user
serializer = SnippetSerializer(data=data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Models:
class Snippet(models.Model):
created = models.DateTimeField(auto_now_add=True)
title = models.CharField(max_length=100, blank=True, default='')
code = models.TextField()
linenos = models.BooleanField(default=False)
language = models.CharField(choices=LANGUAGE_CHOICES, default='python', max_length=100)
style = models.CharField(choices=STYLE_CHOICES, default='friendly', max_length=100)
owner = models.ForeignKey(User)
highlighted = models.TextField()
Post data:
{
"title": "dfhhtryres",
"owner": "admin",
"code": "hfdsadfghdfh",
"linenos": false,
"language": "python",
"style": "friendly"
}
Error: KeyError at /snippets/ 'owner'

Categories

Resources