How to edit api and add changes in django - python

I'm sending api like:
[
{
"id": 1,
"name": "Burger",
"name_ru": "Burger",
"name_en": "Burger",
"img": null,
"parent_category": 1
},
{
"id": 3,
"name": "Pizza",
"name_ru": "Pizza",
"name_en": "Pizza",
"img": null,
"parent_category": 1
}
]
how can edit this api? I want to send parent_category with id and name, not just id.
My views.py:
class TestList(APIView):
def get(self, request, pk, format=None):
cc = Child_Category.objects.filter(parent_category_id = pk)
serializer = ChildCategorySerializer(cc, many=True)
return Response(serializer.data)
My models.py:
class Parent_Category(models.Model):
name = models.CharField(max_length=255)
name_ru = models.CharField(max_length=255)
name_en = models.CharField(max_length=255)
img = models.ImageField(blank=True, null=True)
def __str__(self):
return self.name_en
class Meta:
verbose_name_plural = 'Parent Categories'
class Child_Category(models.Model):
name = models.CharField(max_length=255)
name_ru = models.CharField(max_length=255)
name_en = models.CharField(max_length=255)
parent_category = models.ForeignKey(Parent_Category, on_delete=models.CASCADE)
img = models.ImageField(blank=True, null=True)
def __str__(self):
return self.name_en
class Meta:
verbose_name_plural = 'Child Categories'

Related

How to filter one-to-many relationship with django rest api?

I have a one-to-many relationship like:
class Category(models.Model):
name = models.CharField(max_length=100)
slug = models.SlugField(max_length=100)
images = models.ImageField(upload_to="photos/categories")
category = models.ForeignKey("Category", on_delete=models.CASCADE, related_name='part_of', blank=True, null=True)
date_create = models.DateTimeField(auto_now_add=True)
date_update = models.DateTimeField(auto_now=True)
description = models.TextField(max_length=1000, blank=True)
legislation = models.TextField(max_length=1000, blank=True)
review = models.TextField(max_length= 000, blank=True)
eaza = models.TextField(max_length=1000, blank=True)
class Meta:
verbose_name = "category"
verbose_name_plural = "categories"
def __str__(self):
return self.name
class Animal(models.Model):
name = models.CharField(max_length=100)
slug = models.SlugField(max_length=100)
images = models.ImageField(upload_to="photos/categories")
category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='animals')
date_create = models.DateTimeField(auto_now_add=True)
date_update = models.DateTimeField(auto_now=True)
description = models.TextField(max_length=1000, blank=True)
legislation = models.TextField(max_length=1000, blank=True)
review = models.TextField(max_length=1000, blank=True)
eaza = models.TextField(max_length=1000, blank=True)
class Meta:
verbose_name = "animal"
verbose_name_plural = "animals"
def __str__(self):
return self.name
and serializer:
class AnimalSerializer(serializers.ModelSerializer):
class Meta:
model = Animal
fields = ['id','category_id','name', 'description']
class CategorySerializer(serializers.ModelSerializer):
animals = AnimalSerializer(many=True)
class Meta:
model = Category
fields = ['id','category_id','name', 'description', 'animals']
and urls:
from . import views
urlpatterns = [
path('', CategoryViewSet.ApiOverview, name='home'),
path('all/', views.view_items, name='view_items'),
path('all/<int:id>/', views.detail_item ),
]
views.py:
#api_view(['GET'])
def view_items(request):
queryset = Category.objects.all()
serializer = CategorySerializer(queryset, many=True)
# checking for the parameters from the URL
if request.query_params:
items = Category.objects.filter(**request.query_params.dict())
serializer = CategorySerializer(items , many=True)
else:
items= Category.objects.all()
serializer = CategorySerializer(items , many=True)
# if there is something in items else raise error
if items:
return Response(serializer.data)
else:
return Response(status=status.HTTP_404_NOT_FOUND)
So for example if I do this: http://127.0.0.1:8000/djangoadmin/all/?name=cobra
[
{
"id": 28,
"category_id": 22,
"name": "cobra",
"description": "cobra",
"animals": [
{
"id": 4,
"category_id": 28,
"name": "indian",
"description": "cobra"
},
{
"id": 5,
"category_id": 28,
"name": "cape cobra",
"description": "cape cobra"
},
{
"id": 6,
"category_id": 28,
"name": "Chinese cobra",
"description": "Chinese cobra"
}
]
}
]
But of course I only want to return the children of the parent :
{
"id": 4,
"category_id": 28,
"name": "indian",
"description": "cobra"
},
{
"id": 5,
"category_id": 28,
"name": "cape cobra",
"description": "cape cobra"
},
{
"id": 6,
"category_id": 28,
"name": "Chinese cobra",
"description": "Chinese cobra"
}
But for example if I do this: http://127.0.0.1:8000/djangoadmin/all/?category_id=28
I get an:
HTTP 404 Not Found
Question: how to return only the child items?

Calculate sum of model objects in django serializers

In my app, each user has his wallets in which he can save his daily expenses.
How can I get sum of money for each instance of wallet with many expenses saved to it?
I've tried serializers.SerializerMethodField()
from django.db.models import Sum
from django.db.models import Q
class WalletInstanceSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.id')
entry = BudgetEntrySerializer(many=True, read_only=True)
expense_sum = serializers.SerializerMethodField()
class Meta:
model = WalletInstance
fields = '__all__'
def get_expense_sum(self, obj):
return WalletInstance.objects.filter(Q(id=obj.id)|Q(entry__entry_type='income')).aggregate(Sum('entry__amount'))['entry__amount__sum']
And this gives me data in the correct format but the sum is wrong, for example
[
{
"id": "d458196e-49f1-42db-8bc2-ee1dba438953",
"owner": 1,
"entry": [
{
"id": 3,
"owner": 1,
"title": "dsfdsf",
"amount": 7,
"description": "sdfdsf",
"entry_type": "income",
"date_added": "2022-08-13",
"entry_category": {
"id": 2,
"name": "Transport"
}
},
{
"id": 4,
"owner": 1,
"title": "fesfvsdfgvbtdg",
"amount": 12,
"description": "efesf",
"entry_type": "income",
"date_added": "2022-08-13",
"entry_category": {
"id": 2,
"name": "Transport"
}
}
],
"viewable": [
"admin#gmail.com"
],
"expense_sum": 83,
"name": "dsdsds",
"date_added": "2022-08-13"
}
]
Expense_sum is 83 but amount fields are 7 and 12 so that's equal to 19
How can i get the correct number?
Models
class BudgetEntry(models.Model):
STATE= [
('income','income'),
('expenses','expenses'),
]
owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='owner_of_entry', on_delete=models.CASCADE)
title = models.CharField(max_length=20)
amount = models.IntegerField()
description = models.CharField(max_length=60, null=True)
entry_type = models.CharField(max_length=15, choices=STATE, null=True)
entry_category = models.ForeignKey(Category, null=True, blank=True, related_name='category_of_entry', on_delete=models.SET_NULL)
date_added = models.DateField(auto_now_add=True)
class WalletInstance(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True)
name = models.CharField(max_length=30, null=True)
owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='owner', on_delete=models.CASCADE)
viewable = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='can_view', blank=True)
entry = models.ManyToManyField(BudgetEntry, related_name='BudgetEntry', blank=True)
date_added = models.DateField(auto_now_add=True)
I think ORM query for the BudgetEntry is wrong. It should be like the following:
def get_expense_sum(self, obj):
return obj.entry.filter(entry_type='income').aggregate(Sum('entry__amount'))['entry__amount__sum']
I've figured it out. Firstly I've created #property in my database to get sum of expenses, but this wasn't very useful If I ever wanted to count income so I passed the value arg to the function where the value can be expense/income
class WalletInstance(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True)
name = models.CharField(max_length=30, null=True)
owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='owner', on_delete=models.CASCADE)
viewable = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='can_view', blank=True)
entry = models.ManyToManyField(BudgetEntry, related_name='BudgetEntry', blank=True)
date_added = models.DateField(auto_now_add=True)
def total_amount(self, value):
queryset = self.entry.filter(entry_type=value).aggregate(
total_amount=models.Sum('amount'))
return queryset["total_amount"]
And now I'm calling this function in my serializer instead of counting there
class WalletInstanceSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.id')
entry = BudgetEntrySerializer(many=True, read_only=True)
viewable = serializers.SlugRelatedField(many=True, queryset=get_user_model().objects.all(), slug_field='email')
expense_sum = serializers.SerializerMethodField()
class Meta:
model = WalletInstance
fields = '__all__'
def get_expense_sum(self, obj):
wallet_obj = WalletInstance.objects.get(id=obj.id)
return wallet_obj.total_amount('expenses')

In djangorestframewokr how to apply group by in django serializer using queryset?

models.py
Sharing two mapping table where in CategoryLessonMapping, category is mapped with lesson and in UserLessonMapping, user is mapped with lesson
------- category mapped with lesson --------------------
class CategoryLessonMapping(models.Model):
category = models.ForeignKey(MasterCategory, on_delete=models.CASCADE, blank=True, null=True)
lesson = models.ForeignKey(Lesson, on_delete=models.CASCADE, blank=True, null=True)
class Meta:
db_table = 'category_lesson_mapping'
------- user mapped with lesson --------------------
class UserLessonMapping(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True)
lesson = models.ForeignKey(Lesson, on_delete=models.CASCADE, blank=True, null=True)
class Meta:
db_table = 'user_lesson_mapping'
views.py
------- getting lesson and category related to lesson in json format --------------------
class PatientLessonListView(ListAPIView):
serializer_class = PatientLessonSerializer
queryset = UserLessonMapping.objects.all()
permission_class = (permissions.IsAuthenticated,)
def get_queryset(self):
user_lesson = self.queryset.filter(user=self.request.user)
user_lesson_id = user_lesson.values_list("lesson_id", flat=True)
return CategoryLessonMapping.objects.filter(lesson_id__in=user_lesson_id)
serializers.py
--------- get lesson serialized data -------------
class LessonSerializer(serializers.ModelSerializer):
class Meta:
model = Lesson
fields = ('id', 'lesson_type', 'content', 'description')
depth = 1
--------- get category serialized data -------------
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = MasterCategory
fields = ('id', 'name', 'code')
--------------- getting lesson and category related to user ----------used in views.py------------
class PatientLessonSerializer(serializers.ModelSerializer):
lesson = LessonSerializer()
category = CategorySerializer()
class Meta:
model = CategoryLessonMapping
fields = ['lesson','category']
then json format in which i'm getting it is
[
{
"lesson": {
"id": 1,
"lesson_type": {
"id": 1,
"lesson_type": "Video",
"lesson_code": "VIDEO",
"is_active": 1,
"created_at": "2022-07-14T13:36:16Z",
"updated_at": "2022-07-14T13:36:16Z"
},
"content": "https://www.youtube.com/watch?v=inpok4MKVLM",
"description": "Please follow the below steps for next few days"
},
"category": {
"id": 1,
"name": "insomnia",
"code": "INS"
}
}
]
where in an object i'm getting 2 key-value one is 'category' and other is 'lesson' but what actually i want is grouping all the lessons related to one category, inside category key. like this
{
"categories": [
{
"name": "insomnia",
"code": "INS",
"image": "https://images.everydayhealth.com/images/emotional-health/meditation/a-complete-guide-to-meditation-722x406.jpg?w=1110",
"icon": "moon",
"lessions": [
{
"type": "video",
"link": "https://www.youtube.com/watch?v=inpok4MKVLM",
"description": "Please follow the below steps for next few days"
}
]
}
]
}

How to make nested serializers represent data in given way?

models:
class Category(models.Model):
name = models.CharField(max_length=80)
created_at = models.DateTimeField(auto_now_add = True, null = True)
created_by = models.ForeignKey(User, default = None, blank=True, null=True, on_delete=models.DO_NOTHING, related_name="created_by")
updated_at = models.DateTimeField(auto_now = True, null = True)
updated_by = models.ForeignKey(User, default = None, blank=True, null=True, on_delete=models.DO_NOTHING, related_name="updated_by")
deleted_at = models.DateTimeField(null = True)
deleted_by = models.ForeignKey(User, default = None, blank=True, null=True, on_delete=models.DO_NOTHING, related_name='deleted_by')
class Meta:
verbose_name_plural = "Categories"
def __str__(self):
return self.name
class Product(models.Model):
category = models.ManyToManyField(Category, blank=False)
name = models.CharField(max_length=100)
description = models.TextField(max_length=250)
price = models.DecimalField(max_digits=6, decimal_places=2)
quantity = models.IntegerField(default=0)
created_at = models.DateTimeField(auto_now_add = True, null = True)
created_by = models.ForeignKey(User, default = None, blank=True, null=True, on_delete=models.DO_NOTHING, related_name="products_created_by")
updated_at = models.DateTimeField(auto_now = True, null = True)
updated_by = models.ForeignKey(User, default = None, blank=True, null=True, on_delete=models.DO_NOTHING, related_name="products_updated_by")
deleted_at = models.DateTimeField(null = True)
deleted_by = models.ForeignKey(User, default = None, blank=True, null=True, on_delete=models.DO_NOTHING, related_name='products_deleted_by')
class Meta:
ordering = ("name", )
def __str__(self):
return self.name
serializer:
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = ("id", "name", "created_at", "created_by", "updated_at", "updated_by", "deleted_at", "deleted_by",)
class ProductSerializer(serializers.ModelSerializer):
# category = serializers.PrimaryKeyRelatedField(many=True, read_only=True, source="category")
category = CategorySerializer(many=True)
created_by = serializers.StringRelatedField()
updated_by = serializers.StringRelatedField()
deleted_by = serializers.StringRelatedField()
class Meta:
model = Product
fields = (
"id", "name", "category", "description", "price",
"quantity", "created_at", "created_by", "updated_at",
"updated_by", "deleted_at", "deleted_by",
)
response in postman:
"id": 6,
"name": "Watch",
"category": [
{
"id": 3,
"name": "Electronics",
"created_at": "2020-12-07T12:45:32.521172Z",
"created_by": 2,
"updated_at": "2020-12-07T12:45:32.521217Z",
"updated_by": null,
"deleted_at": null,
"deleted_by": null
},
{
"id": 4,
"name": "Accessories",
"created_at": "2020-12-07T12:46:00.992857Z",
"created_by": 2,
"updated_at": "2020-12-07T12:46:00.992910Z",
"updated_by": null,
"deleted_at": null,
"deleted_by": null
}
],
"description": "Accessory for Smart Phones",
"price": "99.99",
"quantity": 0,
"created_at": "2020-12-07T14:00:12.312151Z",
"created_by": "user1",
"updated_at": "2020-12-07T14:00:12.312222Z",
"updated_by": null,
"deleted_at": null,
"deleted_by": null
}
I want to achieve something like this:
{
"category_ids": [
1,
2
],
"category": [
{
"name": "Category1"
},
{
"name": "Category2"
}
],
"creator": {
"name": "Admin"
},
"updater": {
"name": "Admin2"
}
}
my head hurts. can't find any solution to this problem. probably I am missing something or I am unaware of something.
it's many to many field. I tried to use PrimaryKeyRelatedField and source, but nothing. my biggest problem is, I don't know how to list category_ids seperately
You Can Use SerializerMethodField to achieve this
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = ("name",)
class UserSerializer(serializers.Serializer):
name = serializers.CharField()
class ProductSerializer(serializers.ModelSerializer):
category_ids = serializers.SerializerMethodField()
category = CategorySerializer(many=True)
creator = UserSerializer()
updator = UserSerializer()
class Meta:
model = Product
fields = ("category_ids","category", "creator", "updator")
def get_category_ids(self, instance):
return list(instance.category.all().values_list('id', flat=True))

django rest framework get all related fields and filter in a manytomany field nested

I'm new in Django I want to get all informations of my contacts for a store given in parameter and all extra from another model.
Here is my code :
Models.py
class Store(models.Model):
name = models.CharField(max_length=100)
​
​
class Contact(models.Model):
id = models.CharField(primary_key=True, max_length=200)
first_name = models.CharField(max_length=100, null=True, blank=True)
last_name = models.CharField(max_length=100, null=True, blank=True)
email = models.CharField(max_length=100, null=True, blank=True)
stores = models.ManyToManyField(Store, related_name='contacts')
​
​
class DataType(models.Model):
datatype = models.CharField(max_length=10)
class DataField(models.Model):
name = models.CharField(max_length=100)
label = models.CharField(max_length=100)
datatype = models.ForeignKey(
'DataType',
on_delete=models.SET_NULL,
null=True
)
class DataFieldValue(models.Model):
contact = models.ForeignKey(
Contact,
on_delete=models.SET_NULL,
related_name='datafieldvalues',
null=True
)
datafield = models.ForeignKey(
'DataField',
on_delete=models.SET_NULL,
null=True
)
value = models.CharField(
max_length=250,
null=True,
blank=True
)
Views.py
# Contact API views.
class ContactListAPIView(generics.ListAPIView):
queryset = Contact.objects.all()
serializer_class = ContactSerializer
filter_class = ContactFilter
Filters.py
class ContactFilter(django_filters.rest_framework.FilterSet):
store = django_filters.CharFilter()
class Meta:
model = Contact
fields = ['store']
Serializers.py
class ContactSerializer(serializers.ModelSerializer):
class Meta:
model = Contact
fields = '__all__'
(Additionnal) Here is the schema :
schema
this is what i want:
GET /contacts/?store=54
{
"count": 25,
"next": "<url>/contacts/?page=3",
"previous": "<url>/contacts/?page=2",
"data": [
{
"id": "a519d2cd-13c6-48f3-b391-9a7e0cee58cc",
"src_id": 356,
"first_name": "Benjamin",
"last_name": "Pavard",
"email": "benjamin.pavard#email.fr",
"datafields" : {
"age" : "eighteen"
},
"store": 54
},
....
]
}
but this is what i got :
{
"next": null,
"previous": null,
"count": 10,
"data": [
{
"id": "1234567",
"first_name": null,
"last_name": null,
"email": "cartouche#email.fr",
},
.....
}
Questions :
how can i get the "datafields" ?
"age" is a "datafield" object and "eighteen" is a datafieldvalue object.
How can i get only the store that i've previously gave in parameter?
Thanks a lot for your help whatever it was.
You need to add more fields in the ContactSerializer
class ContactSerializer(serializers.ModelSerializer):
store = serializers.SerializerMethodField()
datafields = serializers.SerializerMethodField()
class Meta:
model = Contact
fields = '__all__'
def get_datafields(self, obj):
result = {}
for data_field_value in obj.datafieldvalues.all().select_related('datafield'):
result[data_field_value.datafield.label] = data_field_value.value
return result
def get_store(self, obj):
request = self.context['request']
store = request.query_params.get('store', '')
return store

Categories

Resources