I have a one-to-many relationship model with payments and paymentlines. How can I group all the paymentlines with the same item and display in serializer. The key is the payments belong to the same order which order id is one the attributes in payments model.
views.py
class OrderItemViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Payment.objects.all()
def get_queryset(self):
return self.queryset.filter(order_id=self.request.GET.get("order_id"))
serializer_class = PaymentSerializer
serializers.py:
class PaymentLineSerializer(ModelSerializer):
class Meta:
model = PaymentLine
fields = (
"item_number",
"currency",
"available_quantity",
"order_total_amount",
)
class PaymentSerializer(ModelSerializer):
payment_lines = PaymentLineSerializer(PaymentLine.objects.select_related("payment"), many=True)
class Meta:
model = Payment
fields = ("order_id", "total_amount", "currency", "payment_lines")
To display this json:
[
{
"order_id": 4,
"total_amount": "250.964024",
"currency": "USD",
"payment_lines": [
{
"item_number": 1100,
"currency": "USD",
"available_quantity": 0,
"order_total_amount": 0,
},
{
"item_number": 1200,
"currency": "USD",
"available_quantity": 1,
"order_total_amount": 224.982012,
}
]
}
]
instead of this:
[
{
"order_id": 4,
"total_amount": "444.700000",
"currency": "USD",
"payment_lines": [
{
"item_number": 1100,
"currency": "USD",
"available_quantity": 1,
"order_total_amount": 25.982012,
},
{
"item_number": 1200,
"currency": "USD",
"available_quantity": 1,
"order_total_amount": 224.982012,
}
]
},
{
"order_id": 4,
"total_amount": "-25.982012",
"external_reference_type": "MAG",
"currency": "USD",
"payment_lines": [
{
"item_number": 1100,
"currency": "USD",
"available_quantity": -1,
"order_total_amount": -25.982012,
}
]
}
]
How about this. I assums that paymentline_set is your related name in models.py
from django.db.models import Prefetch
class OrderItemViewSet(viewsets.ReadOnlyModelViewSet):
def get_queryset(self):
return Payment.objects.filter(
order_id=self.request.GET.get("order_id")
).prefetch_related(
Prefetch(
'paymentline_set',
queryset=PaymentLine.objects.all(),
to_attr='payment_lines'
)
)
class PaymentSerializer(ModelSerializer):
payment_lines = PaymentLineSerializer(many=True)
class Meta:
model = Payment
fields = ("order_id", "total_amount", "currency", "payment_lines")
You can use without Prefetch(), but .prefetch_related('paymentline_set') then in PaymentSerializer change payment_lines to paymentline_set.
Related
I want to customise the output of serializer to group some fields of the models into a nested dictionary, so I override to_representation:
My models.py
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('auth.User', related_name='snippets', on_delete=models.CASCADE)
class Meta:
ordering = ['created']
My serializers.py
class SnippetSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
class Meta:
model = Snippet
fields = ['id', 'title', 'code', 'linenos', 'language', 'style', 'owner']
def to_representation(self, instance):
return {
'id': instance.id,
'owner': instance.owner.username,
'therest': {
'title': instance.title,
'code': instance.code,
'linenos': instance.linenos,
'language': instance.language,
'style': instance.style
}
}
class UserSerializer(serializers.ModelSerializer):
snippets = SnippetSerializer
class Meta:
model = User
fields = ['id', 'username', 'snippets']
depth = 1
My expected outcome of users serializer is:
[
{
"id": 1,
"username": "admin",
"snippets": [
{
"id": 1,
"owner": "admin",
"therest": {
"title": "",
"code": "foo=\"bar\"\\n",
"linenos": false,
"language": "python",
"style": "abap"
}
}
]
}
]
but I got this instead:
[
{
"id": 1,
"username": "admin",
"snippets": [
{
"id": 1,
"created": "2022-09-01T17:11:59.743112Z",
"title": "",
"code": "foo=\"bar\"\\n",
"linenos": false,
"language": "python",
"style": "abap",
"owner": 1
},
]
}
]
Nested snippets in UserSerializer does not inherit to_representation from SnippetSerializer. Did I miss something?
I want to filter users based on their subscription_status which s stored in a pivot table.
I have Three tables users , subscription_packages , subscription_package_user
$user=User::with(['studentDetails','subscriptionsSatus.courses'])
->withPagination($offset,$perPage)
->get()
->sortBy('first_name')->values();
this code return the response is
[
{
"id": 44,
"first_name": "Abcd Test",
"last_name": "Test lastname",
"student_details": null,
"subscriptions_satus": [
{
"id": 1,
"name": "Gold",
"price": 3000,
"user_id": "2"
"pivot": {
"user_id": 44,
"subscription_package_id": 1,
"subscription_status": "on_free_trial",
"expires_on": null,
"id": 9
},
"courses": [
{
"id": 18,
"title": "English Grammar for Class 3",
"price": 400,
"strikethrough_price": null,
"status": "draft",
"user_id": 2,
"image": "http://127.0.0.1:8000/courses/1615702915.png",
"description": null,
"pivot": {
"subscription_package_id": 1,
"course_id": 18,
}
}
]
}
]
}]
i want to return only users who having subscription_status =$filter.
$filter='acive'or 'on_free_trail'
my model is
public function subscriptionsSatus()
{
return $this->belongsToMany(SubscriptionPackage::class)->withTimestamps()->withPivot('subscription_status','expires_on','id');
}
I havetried
$filter=$request->input('filter')??"active";
$user=User::with(['studentDetails','subscriptionsStatus.courses'])
->whereHas('subscriptionsStatus', function($query) use($filter){
$query->wherePivot('subscription_status','=',$filter);
})
->withPagination($offset,$perPage)
->get()
->sortBy('first_name')->values();
But Got error Column not found 'pivot'
You need to use wherePivot along with the orWhere like below:
public function subscriptionsStatus()
{
return $this->belongsToMany(SubscriptionPackage::class)
->withTimestamps()
->withPivot('subscription_status','expires_on','id')
->wherePivot(function($q){
return $q->where('subscription_status','=','active')
->orWhere('subscription_status','=','on_free_trail');
});
}
Update
Or in your controller:
$user=User::with(['studentDetails','subscriptionsStatus.courses'])
->whereHas('subscriptionsStatus', function($query) use($filter){
$query->withPivot('subscription_status')
->wherePivot('subscription_status','=',$filter);
})
->withPagination($offset,$perPage)
->get()
->sortBy('first_name')->values();
I'm quite new to Laravel,
Let's say I have 2 tables: main_sport and sub_sport. These two tables have a one-to-many relationship. 1 sport can have many sub sports.
I want the following json format
{
"success": "1",
"sports": [
"id": 1,
"name_of_categories": "Popular Sports",
"sub_sports:[
{
"id": 1,
"name_sub_sport_category": "Badminton"
},
{
"id": 2,
"name_sub_sport_category": "Football"
},
{
"id": 3,
"name_sub_sport_category": "Cricket"
},
]
]
"sports":[
"id": 2,
"name_of_categories": "Team Sports",
"sub_sports:[
{
"id": 4,
"name_sub_sport_category": "Badminton"
},
{
"id": 5,
"name_sub_sport_category": "Football"
},
]
]
}
I try for this function and i am getting following result
public function fetch()
{
$query= DB::table('details')
->join('table_sub_sport_category','table_sub_sport_category.id','=','details.sub_id')
->join('table_main_sport_category','table_main_sport_category.id','=','details.main_id')
->select(DB::raw('table_main_sport_category.id as id'),'table_main_sport_category.name_of_categories','table_sub_sport_category.name_sub_sport_category')
->get()
return response()->json(['success' =>'1','data'=>$query]);
}
{
"success": "1",
"data": [
{
"id": 1,
"name_of_categories": "Popular Sports",
"name_sub_sport_category": "Badminton"
},
{
"id": 1,
"name_of_categories": "Popular Sports",
"name_sub_sport_category": "Football"
},
{
"id": 1,
"name_of_categories": "Popular Sports",
"name_sub_sport_category": "Cricket"
},
]
}
Could you help me to get the desired result?
You should define sub_sport in the main sport Model like this:
class Sport extends Model{
public function sub_sport(){
return $this->hasMany(SubSport::class);
}
}
And in your controller you should write this:
$data = Sport::with('sub_sport')->get();
Use below code
$query= DB::table('details')
->join('table_sub_sport_category','table_sub_sport_category.id','=','details.sub_id')
->join('table_main_sport_category','table_main_sport_category.id','=','details.main_id')
->select(DB::raw('table_main_sport_category.id as id'),'table_main_sport_category.name_of_categories','table_sub_sport_category.name_sub_sport_category')
->get()
return Response::json([
'status' => 'error',
'sports' => $query
], 200);
I have a Django REST framework application with a course and department model. I have the following models, serializers and viewset to represent the course catalog.
## MODELS ##
class Department(models.Model):
"""Academic Department"""
name = models.CharField(max_length=30, unique=True)
class Course(models.Model):
"""Courses in the course catalog"""
course_name = models.CharField(max_length=30, unique=True)
department = models.ForeignKey(Department, on_delete=models.PROTECT)
course_number = models.DecimalField(decimal_places=0, max_digits=3, unique=True)
credits = models.IntegerField()
class Meta:
unique_together = (("department", "course_number"),)
## SERIALIZERS ##
class DepartmentSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = models.Department
#fields = ('id', 'last_name', 'first_name')
class CourseSerializer(serializers.ModelSerializer):
department = serializers.SlugRelatedField(
many = False,
read_only = False,
slug_field = 'name',
queryset = models.Department.objects.all()
)
class Meta:
model = models.Course
fields = (
'id',
'course_name',
'department',
'course_number',
'credits')
## VIEWSETS ##
class CourseViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows courses to be viewed or edited.
"""
queryset = models.Course.objects.all().order_by('department__name','course_number')
serializer_class = serializers.CourseSerializer
Course has a foreign key pointing to department and using the SlugRelatedField a courses department is listed in the result JSON as the department name:
{
"count": 5,
"next": null,
"previous": null,
"results": [
{
"id": 5,
"course_name": "History of Justin",
"department": "English",
"course_number": "344",
"credits": 3
},
{
"id": 6,
"course_name": "34",
"department": "Math",
"course_number": "4",
"credits": 4
},
{
"id": 1,
"course_name": "Pre Calc",
"department": "Math",
"course_number": "101",
"credits": 3
},
{
"id": 2,
"course_name": "Calc I",
"department": "Math",
"course_number": "200",
"credits": 3
},
{
"id": 3,
"course_name": "Calc II",
"department": "Math",
"course_number": "201",
"credits": 3
}
]
}
I can also populate new courses with the following body in a POST request:
{
"course_name": "Chemistry I",
"department": "Science",
"course_number": "200",
"credits": 3
}
However, the auto generated form does not render the slug field text.
.
How can I change what this form renders?
You'll need to add a __str__ method to Department in order to tell Django about how to represent a Department instance:
class Department(models.Model):
"""Academic Department"""
name = models.CharField(max_length=30, unique=True)
def __str__(self):
return self.name
When i m using has many without select it returns all fields from userTrancastion table
Invoicemodule.php
$invoice = UserInvoiceDetail::with('transaction')
->select('Id','UserId','TotalPrice')
->where('UserId','=',$playerId)
->get();
return $invoice;
UserInvoiceDetail.php
class UserInvoiceDetail extends Model
{
protected $table = 'user_invoice_details';
protected $primaryKey ='Id';
public function transaction()
{
return $this->hasMany(UserTransaction::class, 'InvoiceId');
}
}
Output
"Invoices":
[
{
"Id": 1,
"UserId": 5,
"TotalPrice": 110,
"transaction": [
{
"Id": 1,
"InvoiceId": 1,
"UserId": 5,
"ReferenceTransactionId": null,
"CategoryId": 1,
"ProductId": 140,
"Price": 5,
"Quantity": 5,
"CustomerId": 1,
},
{
"Id": 2,
"InvoiceId": 1,
"UserId": 5,
"ReferenceTransactionId": null,
"CategoryId": 2,
"ProductId": 3,
"Price": 15,
"Quantity": 3,
"CustomerId": 1,
}
]
}
]
But When i m using has many with select it returns nothing userTrancastion table
UserInvoiceDetail.php
class UserInvoiceDetail extends Model
{
protected $table = 'user_invoice_details';
protected $primaryKey ='Id';
public function transaction()
{
return $this->hasMany(UserTransaction::class, 'InvoiceId')->select('user_transactions.Id','user_transactions.ProductId');
}
}
Output
"Invoices": [
{
"Id": 1,
"UserId": 5,
"TotalPrice": 110,
"transaction": []
},
{
"Id": 2,
"UserId": 5,
"TotalPrice": 110,
"transaction": []
}
]
why this is happening, I want to use join in transaction() function, so i need only selective fields.
How can use select with hasmany()?
Thank you in advance.
The relation need to the column that by which it related so add InvoiceId
also, it doesn't need to add user_transactions
public function transaction()
{
return $this->hasMany(UserTransaction::class, 'InvoiceId')->select('Id','ProductId','InvoiceId');
}