How to include related models using Django Rest Framework ListAPIView - django-models

Having 2 models and i need a list, a single queryset of lists that will combine all related fields from the 2 models.
class Product(models.Model):
name = models.CharField(...)
price= models.Decimal(...)
image = models.ImageField(...)
description2 = models.TextField(....)
class Order(models.Model):
buyer = models.CharField(...)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
have it return something that includes the full related model. A queryset Lists of ORDER with this result
{
"id": 1,
"buyer": 1,
"product": 3,
"name": "Product 1",
"image": "url",
"price": 10.50
},
{
"id": 2,
"buyer": 2,
"product": 2,
"name": "Product 2",
"image": "url",
"price": 6.50
},
OR
{
"id": 1,
"buyer": 1,
"product": [
{
'id': 1,
'name': 'Product 1',
'image': "url",
'price': 10.50
}],
},
{
"id": 2,
"buyer": 2,
"product": [
{
'id': 2,
'name': 'Product 2',
'image': "url",
'price': 6.50
}],
}
Is this possible?

First, you need to define the serializer in serializers.py file.
from rest_framework import serializers
from .models import Product, Order
class ProductSerializer(serializers.ModelSerializer):
class Meta:
fields = "__all__"
model = Product
class OrderSerializer(serializers.ModelSerializer):
product = ProductSerializer(read_only = True)
class Meta:
fields = ("buyer", "product", )
model = Order
And then, you need to create the ListAPIView for Order in views.py file.
from rest_framework import generics, mixins
from .models import Order
from .serializers import OrderSerializer
class OrderView(mixins.ListModelMixin, generics.GenericAPIView):
queryset = Order.objects.all()
serializer_class = OrderSerializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
Last you need to add the api url in urls.py,
from .views import *
urlpatterns = [
path('orders', OrderView.as_view(), name="order")
]

Related

Submitting SUMMARY Data from Django to React using DRF

I'm starting to test some API data between django and React using Rest API. I'm able to submit this data between Djnago model and React front end.
[
{
"id": 1,
"gender": "Male",
"age": 40,
"updated": "2022-04-25T18:55:23.304456Z",
"created": "2022-04-25T14:07:48.282139Z"
},
{
"id": 2,
"gender": "Male",
"age": 33,
"updated": "2022-04-25T18:55:23.304456Z",
"created": "2022-04-25T14:07:48.282139Z"
},
{
"id": 3,
"gender": "Female",
"age": 22,
"updated": "2022-04-25T18:55:23.304456Z",
"created": "2022-04-25T14:07:48.282139Z"
},
{
"id": 4,
"gender": "Female",
"age": 33,
"updated": "2022-04-25T18:55:23.304456Z",
"created": "2022-04-25T14:07:48.282139Z"
},
]
My goal is not to submit this raw data, but instead to submit summary data (data analysis) that calculates the average age for males and females, so I should be getting something like this:
[
{
"gender": "Male",
"average_age": 36.5,
},
{
"gender": "Male",
"average_age": 27.5,
}
]
in TestDrf.js
import React from "react"
import axios from 'axios'
export default function App() {
const [incomingData, setIncomingData] = React.useState([])
React.useEffect(function() {
console.log('effect ran')
axios.get('http://127.0.0.1:8000/test/')
.then(data => setIncomingData(data))
}, [])
return (
<div>
<pre>{JSON.stringify(incomingData.data, null, 2)}</pre>
</div>
)
}
in views.py
from rest_framework.response import Response
from rest_framework.decorators import api_view
from .models import Test
from .serializers import TestSerializer
#api_view(['GET'])
def getData(request):
test_data= Test.objects.all()
result = Test.objects.values('gender')
.annotate(average_age=Avg('age'))
serializer = TestSerializer(test_data, many=True)
return Response(serializer.data)
Where should I be making these cross tabulations? on the backend or front end?
if on the backend should I be creating new models for the summary data?
I tried looking online for advice on this but I was unlucky!
A Django query can be used in the backend to perform aggregation; new model is not needed for summary data.
An SQL query for getting average age by gender from a 'person' table would be something like this.
SELECT gender, AVG(age) AS average_age
FROM person
GROUP BY gender;
The equivalent Django query would be similar to this.
from django.db.models import Avg
result = Person.objects.values('gender')
.annotate(average_age=Avg('age'))
UPDATE: Adding a class based API view
class GetData(APIView):
def get(self):
result = Test.objects.values('gender').annotate(average_age=Avg('age'))
response_data = {}
response_data['data'] = list(result)
return Response(response_data, status=status.HTTP_200_OK)
urls.py should be updated to use this API view.
path('getdata/', GetData.as_view()),

How to access forgin key value in react from django api

I have django api in which i have post model which is linked to comments and categories table by forgin key now i am feching data for post detail and when i try to access category of that post it return s id and i want to access name of category this is my post list view
{
"id": 4,
"title": "BLOG PAGE",
"body": "testing",
"owner": "ankit",
"comments": [],
"categories": [
2
],
"created_at": "2021-05-07T17:22:32.989706Z"
},
{
"id": 5,
"title": "Test Post",
"body": "This is a test Post",
"owner": "ankit",
"comments": [],
"categories": [
2
],
and this is my categories
[
{
"id": 2,
"name": "Python",
"owner": "ankit",
"posts": [
4,
5,
6,
8
]
}
]
and this is my post detail component
export class PostDetail extends React.Component {
constructor(props) {
super(props);
const ID = this.props.match.params.id
this.state = {
data: [],
loaded: false,
placeholder: "Loading"
};
}
formatDate(dateString){
const options = { year: "numeric", month: "long", day: "numeric" }
return new Date(dateString).toLocaleDateString(undefined, options)
}
componentDidMount() {
fetch(`${Url}posts/${this.props.match.params.id}`)
.then(response => {
if (response.status > 400) {
return this.setState(() => {
return { placeholder: "Something went wrong!" };
});
}
return response.json();
})
.then(data => {
this.setState(() => {
return {
data,
loaded: true
};
});
});
}
render(){
return(
<>
<h1 className="main-title">{this.state.data.title}</h1>
<div className="container">
<div className="box1">
<h2>Categories</h2>
<div className="categories">{this.state.data.categories}</div>
</div>
</>
);
}
}
and i am getting output as 2 when i try to get data like mention above
i thought i can access it by putting . in front of categories eg. categories.name but it returns TypeError error
TypeError: Cannot read property 'name' of undefined
this are my serializers
class CategorySerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
posts = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
class Meta:
model = Category
fields = ['id', 'name', 'owner', 'posts']
class PostSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
comments = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
class Meta:
model = Post
fields = ['id', 'title', 'body', 'owner', 'comments', 'categories','created_at']
i try to access category of that post it return s id and i want to access name of category this is my post list view
1. For getting only the name of the category.
You can use the SlugRelatedField.
Modify your PostSerializer like so:
class PostSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
comments = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
categories = serializers.SlugRelatedField(many=True, read_only=True, slug_field='name')
class Meta:
model = Post
fields = ['id', 'title', 'body', 'owner', 'comments', 'categories','created_at']
Example JSON response:
{
"id": 4,
"title": "BLOG PAGE",
"body": "testing",
"owner": "ankit",
"comments": [],
"categories": [
"Python"
],
"created_at": "2021-05-07T17:22:32.989706Z"
},
2. To nest full Category objects
class PostSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
comments = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
categories = CategorySerializer(many=True)
class Meta:
model = Post
fields = ['id', 'title', 'body', 'owner', 'comments', 'categories','created_at']
Example JSON response:
{
"id":4,
"title":"BLOG PAGE",
"body":"testing",
"owner":"ankit",
"comments":[],
"categories":[
{
"id":2,
"name":"Python",
"owner":"ankit",
"posts":[
4,
5,
6,
8
]
}
],
"created_at":"2021-05-07T17:22:32.989706Z"
}

JDL: Multiple Menu

I trying to create multiple menu category using JDL. In one CategoryItem have parentID.
I already created JDL like:
microservice * with Category
entity CategoryItem{
name String required
}
relationship ManyToOne{
CategoryItem{parrent} to CategoryItem
}
service * with serviceClass
paginate CategoryItem with pagination
If the client calls a method findAll. Can I return JSON format like that:
[
{
"id": 1,
"name": "car",
"CategoryItem": [
{
"id": 2,
"name": "red car"
},
{
"id": 3,
"name": "blue car"
}
]
},
{
"id": 4,
"name": "bike",
"CategoryItem": []
}
]

How to join 3 tables in query with Django, combined select related and prefetch_related

I have tree models
class Category(models.Model):
name = models.CharField(max_length=60)
class Product(models.Model):
description = = models.CharField(max_length=255)
category = models.ForeignKey(Category, related_name='products')
class Inventory(models.Model):
userReservation = models.ForeignKey(User)
Product=models.ForeignKey(Product related_name='products_reservation')
Quantity = models.IntegerField()
I want to get all product by category, with quantity registered in inventory, for the user and the product
{
"id": 1,
"name": "Corbata",
"products": [{
"id": 10,
"description": "shoes",
"quantitybyInventory": 3
},
{
"id": 9,
"description": "shirt",
"quantitybyInventory": 1
}]}
I have a view with this class
views.py
class inventoryList(generics.ListCreateAPIView):
queryset = Category.objects.prefetch_related('products')
serializer_class = CategorybyProductSerializer
def get_object(self):
queryset = self.queryset()
obj = get_object_or_404(queryset)
return obj
And my serializer
class CategorybyProductSerializer(serializers.ModelSerializer):
products = ProductSerializer(many=True)
class Meta:
model = Category
fields = ('id', 'name', 'products')
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = ('id', 'description')
but I can not show the amount of the inventory table
this query just show me it
{
"id": 1,
"name": "Corbata",
"products": [{
"id": 10,
"description": "shoes"
},
{
"id": 9,
"description": "shirt"
}
]
}
I use SerializerMethodField, and this post
class ProductbyUserSerializer(serializers.ModelSerializer):
quantitybyInventory = serializers.SerializerMethodField(read_only=True)
def get_quantitybyInventory(self, product):
return product.products_reservation.filter(userReservation = self.context['request'].user).count()
class Meta:
model = Product
fields = ('id', 'description', 'quantitybyInventory')

Json Array with Flask-Restless for Datatables.net

I want to use Datatables.net and it requires and json array like the below
{
"data": [
[
"9",
"1",
"sala",
"zeus",
"lights",
"3",
"7",
"tcp",
]
}
But On Flask-Restfull, the nearest I could get from this is
{
"objects": [
{
"channel": 9,
"id": 1,
"location": "sala",
"name": "zeus",
"purpose": "lights",
"role_id": 3,
"role_permissions": 7,
"type": "tcp"
}
}
with this set-up:
manager.create_api(Device,
results_per_page=1000,
primary_key='id',
exclude_columns=['user_devices','role','num_results'],
app=app,
# exclude_columns=['role_id'],
preprocessors=dict(GET_SINGLE=[auth_func],
GET_MANY=[auth_func]),
postprocessors={
'GET_MANY': [api_post_get_many]
}
)
def api_post_get_many(result=None, **kw):
for key in result.keys():
if key != 'objects':
del result[key]
and this model:
class Device(db.Model):
__tablename__ = 'devices'
__table_args__ = (db.UniqueConstraint('id', 'name', 'purpose', 'channel', 'type','location'),
db.ForeignKeyConstraint(
['role_id', 'role_permissions'],
['roles.id', 'roles.permissions']
)
)
id = db.Column(db.Integer, primary_key=True)
purpose = db.Column( db.String(64))
type = db.Column( db.String(64))
name = db.Column(db.String(64))
location = db.Column(db.String(64))
channel = db.Column( db.Integer)
role_id = db.Column(db.Integer)
role_permissions = db.Column(db.Integer)
role = db.relationship('Role', backref=db.backref('devices'))
Is there a way to make FlaskRESTLESS return a json array instead of a json object? Or should I try to serialize the data with python??

Resources