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
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?
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')
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"
}
]
}
]
}
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))
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