I am using django and rest api. And I have two models:
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 my serializer looks:
class AnimalSerializer(serializers.ModelSerializer):
class Meta:
model = Animal
fields = ['id','name', 'description']
class CategorySerializer(serializers.ModelSerializer):
animals = AnimalSerializer(many=True)
class Meta:
model = Category
fields = ['id','category_id','name', 'description', 'animals']
and views.py:
class CategoryViewSet(viewsets.ModelViewSet):
serializer_class = CategorySerializer
queryset = Category.objects.all()
#action(methods=['get'], detail=False)
def mainGroups(self,request):
mainGroups = Category.objects.filter(category_id__isnull=True)
serializer = self.get_serializer(mainGroups, many=True)
return Response(serializer.data)
and urls.py:
router = routers.DefaultRouter()
router.register('groups', CategoryViewSet)
urlpatterns = [
path('', include(router.urls))
]
So if I go to: http://127.0.0.1:8000/djangoadmin/groups/
I get as output:
[
{
"id": 11,
"category_id": null,
"name": "zoogdieren",
"description": "hoi",
"animals": []
},
{
"id": 12,
"category_id": null,
"name": "amfibieen",
"description": "kujhkjh",
"animals": []
},
{
"id": 13,
"category_id": null,
"name": "vogels",
"description": "kljhkjh",
"animals": []
},
{
"id": 16,
"category_id": 13,
"name": "roofvogels",
"description": "kljhkljjl",
"animals": []
},
{
"id": 17,
"category_id": 12,
"name": "kikkers",
"description": "kjhkjh",
"animals": []
},
{
"id": 21,
"category_id": null,
"name": "reptielen",
"description": "reptielen",
"animals": []
},
{
"id": 22,
"category_id": 21,
"name": "slangen",
"description": "slangen",
"animals": []
},
{
"id": 24,
"category_id": 11,
"name": "honden",
"description": "hhhh",
"animals": []
},
{
"id": 25,
"category_id": 11,
"name": "katten",
"description": "kjhkjh",
"animals": []
},
{
"id": 26,
"category_id": 11,
"name": "olifanten",
"description": "kjhkjhkjh",
"animals": []
},
{
"id": 27,
"category_id": 21,
"name": "krokodillen",
"description": "l;l;'ll;;'l",
"animals": []
},
{
"id": 28,
"category_id": 22,
"name": "cobra",
"description": "cobra",
"animals": [
{
"id": 4,
"name": "indian cobra",
"description": "cobra"
},
{
"id": 5,
"name": "cape cobra",
"description": "cape cobra"
},
{
"id": 6,
"name": "Chinese cobra",
"description": "Chinese cobra"
}
]
},
{
"id": 29,
"category_id": 16,
"name": "valken",
"description": "valken",
"animals": []
},
{
"id": 30,
"category_id": 16,
"name": "gieren",
"description": "Gieren",
"animals": []
},
{
"id": 31,
"category_id": 21,
"name": "aligatoren",
"description": "aligatoren",
"animals": []
},
{
"id": 32,
"category_id": 13,
"name": "meeuwen",
"description": "meeuwen",
"animals": []
},
{
"id": 33,
"category_id": 22,
"name": "droppel slangen",
"description": "droppel slangen",
"animals": []
}
]
So for example zoogdieren with id 11 has many linked categories:
honden category_id = 11
katten category_id = 11
Question:
How to make a query that will filter for example on name zoogdieren and then the api call will filter the referenced id's?
So for example you fill in: http://127.0.0.1:8000/djangoadmin/groups?name=zoogdieren and as output:
{
"id": 24,
"category_id": 11,
"name": "honden",
"description": "hhhh",
"animals": []
},
{
"id": 25,
"category_id": 11,
"name": "katten",
"description": "kjhkjh",
"animals": []
},
if I do this: http://127.0.0.1:8000/djangoadmin/groups/11/
I get the main category:
{
"id": 11,
"category_id": null,
"name": "zoogdieren",
"description": "hoi",
"animals": []
}
But I want to have the related entities with category_id 11
Now in http://127.0.0.1:8000/djangoadmin/groups/11/ you just getitem with id = 11. If you eant to get all items with category_id = 11, you just have to make smth like that: http://127.0.0.1:8000/djangoadmin/groups?category_id=11.
Related
this is django rest_framework api I created this api for restourant. This is menu api . I want to save menu.json's data to my database, but I could not. Can you give any advice to save json data to my models. I got this error:
File "C:\Users\OSMAN MERT\AppData\Local\Programs\Python\Python310\lib\site-packages\django\utils\functional.py", line 49, in __get__
res = instance.__dict__[self.name] = self.func(instance)
File "C:\Users\OSMAN MERT\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\models\fields\related.py", line 113, in related_model
apps.check_models_ready()
File "C:\Users\OSMAN MERT\AppData\Local\Programs\Python\Python310\lib\site-packages\django\apps\registry.py", line 143, in check_models_ready
raise AppRegistryNotReady("Models aren't loaded yet.")
django.core.exceptions.AppRegistryNotReady: Models aren't loaded yet.
models.py
class Meal(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=100)
is_vegetarian = models.BooleanField(default=False)
is_vegan = models.BooleanField(default=False)
def __str__(self):
return self.name
class Ingredient(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=100)
#groups = models.CharField(max_length=100)
#meal = models.ForeignKey(Meal, on_delete=models.CASCADE, related_name='ingredients')
def __str__(self):
return self.name
class Option(models.Model):
id = models.AutoField(primary_key=True)
ingredient = models.ForeignKey(Ingredient, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
quality = models.CharField(max_length=100)
price = models.FloatField()
per_amount = models.CharField(max_length=100)
def __str__(self):
return self.name
class MealIngredient(models.Model):
id = models.AutoField(primary_key=True)
meal = models.ForeignKey(Meal, on_delete=models.CASCADE)
ingredient = models.ForeignKey(Ingredient, on_delete=models.CASCADE)
path = r"C:\Users\OSMAN MERT\Desktop\menu\menu_core\menu.json"
with open(path) as f:
data = json.loads(f.read())
for meal in data["meals"]:
id = meal["id"]
name = meal["name"]
meal_obj, created = Meal.objects.get_or_create(name=name)
for ingredient in meal["ingredients"]:
name_in = ingredient["name"]
ingredient_obj, created = Ingredient.objects.get_or_create(name=name_in)
MealIngredient.objects.get_or_create(meal=meal_obj, ingredient=ingredient_obj)
for ingre in data["ingredients"]:
ingre_name = ingre["name"]
ingre_obj, created = Ingredient.objects.get_or_create(name=ingre_name)
for opti in ingre["options"]:
opt_name = opti["name"]
opt_quality = opti["quality"]
opt_price = opti["price"]
opt_amount = opti["per_amount"]
Option.objects.get_or_create(ingredient=ingre_obj, name=opt_name, quality=opt_quality,
price=opt_price, per_amount=opt_amount)
This is some data from menu.json not all code include there. menu.json
{
"meals": [
{
"id": 1,
"name": "Rice and chicken bowl",
"ingredients": [
{ "name": "Rice", "quantity": 120, "quantity_type": "gram" },
{ "name": "Chicken", "quantity": 85, "quantity_type": "gram" }
]
},
{
"id": 2,
"name": "Pasta with marinara sauce and vegetables",
"ingredients": [
{ "name": "Pasta", "quantity": 115, "quantity_type": "gram" },
{
"name": "Marinara sauce",
"quantity": 120,
"quantity_type": "millilitre"
},
{ "name": "Vegetables", "quantity": 240, "quantity_type": "gram" }
]
},
{
"id": 3,
"name": "Grilled chicken with roasted vegetables",
"ingredients": [
{ "name": "Chicken", "quantity": 85, "quantity_type": "gram" },
{ "name": "Vegetables", "quantity": 240, "quantity_type": "gram" }
]
}
],
"ingredients": [
{
"name": "Rice",
"groups": ["vegan", "vegetarian"],
"options": [
{
"name": "Long grain white rice",
"quality": "high",
"price": 3,
"per_amount": "kilogram"
},
{
"name": "Medium grain brown rice",
"quality": "medium",
"price": 2,
"per_amount": "kilogram"
},
{
"name": "Quick cooking white rice",
"quality": "low",
"price": 1.5,
"per_amount": "kilogram"
}
]
}]
Models.py
class Cat_Breed_Detail(models.Model):
id = models.AutoField(primary_key=True,verbose_name="id")
key_name = models.CharField(max_length=35,default='',null=True,verbose_name="key_name")
display_name= models.CharField(max_length=35,default='',null=True,verbose_name="display_name")
def __str__(self):
return self.key_name
class Cat_Image(models.Model):
image=models.ImageField(upload_to="ImagesCat/")
cat=models.ForeignKey(Cat_Breed_Detail,on_delete=models.CASCADE,null=True,related_name='images')
def image_preview(self):
if self.image:
return mark_safe('<img src="{0}" width="150" height="150" />'.format(self.image.url))
else:
return '(No image)'
Selializer.py
class CatImageSerializer(serializers.ModelSerializer):
class Meta:
model = Cat_Image
fields = '__all__'
class CatDataSerializer(serializers.ModelSerializer):
class Meta:
model = Cat_Breed_Detail
fields = ['id','key_name','display_name','images']
View.py
class CatListCreate(ListAPIView):
queryset = CatBreedDetails.objects.all().order_by('key_name')
serializer_class = CatDataSerializer
pagination_class = CustomPagination
response i am getting here i am getting nested response i dont want it i just want image url in images as a list not like the response i am currently getting :
{
"id": 9,
"key_name": "abyssinian",
"display_name": "Abyssinian",
"image": [
{
"id": 3,
"image": "/media/Abyssinian_0006.jpg",
"cat": 9
},
{
"id": 4,
"image": "/media/Abyssinian_0092.jpg",
"cat": 9
}
]
},
{
"id": 18,
"key_name": "american_bobtail",
"display_name": "American Bobtail",
"image": [
{
"id": 5,
"image": "/media/American_Bobtail_0004.jpg",
"cat": 18
},
{
"id": 6,
"image": "/media/American_Bobtail_0057.png",
"cat": 18
}
]
},
{
"id": 19,
"key_name": "american_curl",
"display_name": "American Curl",
"image": [
{
"id": 7,
"image": "/media/American_Curl_0078.jpg",
"cat": 19
},
{
"id": 8,
"image": "/media/American_Curl_0083.png",
"cat": 19
}
]
}
i want to get all the images in one list not like image:{image:"...."
,image:"......"} i am new to djnago and still learning is there any way to make it done .
is there any way i can get response like that :
{
"id": 9,
"key_name": "abyssinian",
"display_name": "Abyssinian",
"image": ["/media/Abyssinian_0006.jpg","/media/Abyssinian_0092.jpg",]
}
[
{
"id": 1,
"key_name": "first cat",
"display_name": "first cat",
"images": [
{
"image": "http://localhost:8000/ImagesCat/Screenshot_from_2022-12-21_18-16-28.png"
},
{
"image": "http://localhost:8000/ImagesCat/Screenshot_from_2022-12-29_13-41-31.png"
}
]
}
]
this is how I get response if you want to make like yours then you have to override list method
from rest_framework import serializers
from app.models import Cat_Image, Cat_Breed_Detail
class CatImageSerializer(serializers.ModelSerializer):
class Meta:
model = Cat_Image
fields = '__all__'
class CatImageSerializer2(serializers.ModelSerializer):
class Meta:
model = Cat_Image
fields = ['image']
class CatDataSerializer(serializers.ModelSerializer):
images = CatImageSerializer2(read_only=True, many=True)
class Meta:
model = Cat_Breed_Detail
fields = ['id', 'key_name', 'display_name', 'images']
My serializers class
class ConditionSerializers(serializers.ModelSerializer):
class Meta:
model = TblCondition
fields = ['id','operator','condition','relation']
class ConditionSerializers(serializers.ModelSerializer):
relation_with=ConditionSerializers(many=False)
class Meta:
model = TblCondition
fields = ['id','operator','relation_with','condition','relation']
class RuleSerializers(serializers.ModelSerializer):
conditiontbl=ConditionSerializers(many=True)
class Meta:
model = TblRule
fields = ['rule_table_no','rule_no','rule_name','columns','data_file','true','conditiontbl' ]
My model class
class TblRule(models.Model):
rule_table_no=models.AutoField(primary_key=True)
rule_no=models.IntegerField(blank=False)
rule_name=models.CharField(max_length=100,blank=False)
columns=models.CharField(max_length=100)
data_file=models.CharField(max_length=100)
true=models.CharField(max_length=100)
class TblCondition(models.Model):
rule=models.ForeignKey(TblRule, on_delete=models.CASCADE,related_name='conditiontbl')
operator=models.CharField(max_length=100)
condition=models.CharField(max_length=100)
relation=models.CharField(max_length=50,blank=True)
relation_with=models.OneToOneField(to='self',null=True,blank=True,on_delete=models.CASCADE)
Getting these results in postman API by calling ruletbl models
[
{
"rule_table_no": 2,
"rule_no": 1,
"rule_name": "Age Discritization",
"columns": "Age",
"data_file": "Data1",
"true": "Teen",
"conditiontbl": [
{
"id": 4,
"operator": ">",
"relation_with": null,
"condition": "15",
"relation": ""
},
{
"id": 5,
"operator": "<=",
"relation_with": {
"id": 4,
"operator": ">",
"condition": "15",
"relation": ""
},
"condition": "25",
"relation": "and"
}
]
},
{
"rule_table_no": 3,
"rule_no": 1,
"rule_name": "Age Discritization",
"columns": "Age",
"data_file": "Data1",
"true": "Young",
"conditiontbl": []
}
]
Results I want :
[
{
"rule_table_no": 2,
"rule_no": 1,
"rule_name": "Age Discritization",
"columns": "Age",
"data_file": "Data1",
"true": "Teen",
"conditiontbl": [
{
"id": 7,
"operator": ">",
"relation_with": null,
"condition": "15",
"relation": ""
},
{
"id": 6,
"operator": "<=",
"relation_with": {
"id": 7,
"operator": ">",
"relation_with":
{
"id": 7,
"operator": ">",
"relation_with": null,
"condition": "15",
"relation": ""
},
"condition": "15",
"relation": "or"
},
"condition": "25",
"relation": "and"
}
]
},
{
"rule_table_no": 3,
"rule_no": 1,
"rule_name": "Age Discritization",
"columns": "Age",
"data_file": "Data1",
"true": "Young",
"conditiontbl": []
}
]
You can see conditiontbl list fileds in ruletbl model (e.g. in JASON results), inside conditiontbl filed we have objects of tblcondition models with fileds ("relation_with"), and this relation_with filed is again refering to its own tblcondition model you can see its second object. I want this refering in relation_with fileds to its own conditiontbl model to be recursive. Any solution ?
In Django, recursive serialization can be implemented by creating a custom serializer class that extends the BaseSerializer class and overrides the to_representation() method
from django.core.serializers import serialize
from django.core.serializers.json import DjangoJSONEncoder
from django.db import models
from rest_framework import serializers
class Node(models.Model):
parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True)
value = models.CharField(max_length=255)
class NodeSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Node
fields = ('url', 'parent', 'value')
root = Node.objects.get(pk=1)
serialized_data = serialize('json', [root], cls=DjangoJSONEncoder)
I have UserModel each user has multiple package and each package have price and program.
model.py:
class User(models.Model):
name= models.CharField(max_length=100)
class Package(models.Model):
package_name = models.CharField(max_length=100)
user= models.ForeignKey(User, on_delete=models.CASCADE,related_name='user_package')
class Program(models.Model):
title = models.CharField(max_length=100)
user_package = models.ForeignKey(Package, on_delete=models.CASCADE)
class Price(models.Model):
price = models.FloatField()
user_package = models.ForeignKey(Package, on_delete=models.CASCADE)
serializer look like:
class UserSerializer(NestedCreateMixin, NestedUpdateMixin,serializers.ModelSerializer):
program = ProgramSerializer(source='user_program', many=True, read_only=True)
package = PackageSerializer(source='user_package', many=True, read_only=True)
price = PriceSerializer(source='price', many=True, read_only=True)
class Meta:
model = User
fields= ("__all__")
views.py:
class user_apiView(APIView):
def get(self, request):
user= user.objects.all()
serializer = UserSerializer(user, many = True)
return Response(serializer.data)
and that what I get:
{
"id": 1,
"package": [
{
"id": 1,
"package_name": "wfe",
"user": 1
},
{
"id": 2,
"package_name": "wfe",
"user": 1
}
]
}
how can GET this RESULT?
{
"id": 1,
"package": [
{
"id": 1,
"package_name": "wfe",
"user": 1
},
{
"id": 2,
"package_name": "wfe",
"user": 1
}
],
"price": [
{
"id": 1,
"price": "wfe",
"package": 1
},
{
"id": 2,
"price": "wfe",
"package": 2
}
]
"program": [
{
"id": 1,
"title": "wfe",
"package": 1
},
{
"id": 2,
"title": "wfe",
"package": 2
}
]
}
The problem is that your price and program models are not directly related to your user model. If you consider the relations it is like price -> package -> user, so you will have to get those relations in the package serializer instead like this
serializers.py
class ProgramSerializer(serializers.ModelSerializer):
class Meta:
model = Program
fields= ("__all__")
class PriceSerializer(serializers.ModelSerializer):
class Meta:
model = Price
fields= ("__all__")
class PackageSerializer(serializers.ModelSerializer):
program = ProgramSerializer(source='program_set', many=True, read_only=True)
price = PriceSerializer(source='price_set', many=True, read_only=True)
class Meta:
model = Package
fields= ("__all__")
class UserSerializer(serializers.ModelSerializer):
package = PackageSerializer(source='user_package', many=True, read_only=True)
class Meta:
model = User
fields= ("__all__")
Note that this will however not give you the output in the format you mentioned though, the price and program fields will instead be nested under package.
[
{
"id": 1,
"package": [
{
"id": 1,
"program": [
{
"id": 1,
"title": "program1",
"user_package": 1
}
],
"price": [
{
"id": 1,
"price": 1000.0,
"user_package": 1
}
],
"package_name": "package1",
"user": 1
},
{
"id": 2,
"program": [
{
"id": 2,
"title": "program2",
"user_package": 2
}
],
"price": [
{
"id": 2,
"price": 1500.0,
"user_package": 2
}
],
"package_name": "package2",
"user": 1
}
],
"name": "user1"
}
]
If you really want the format in the way you posted you might instead want to take a look at https://www.django-rest-framework.org/api-guide/fields/#serializermethodfield
Below is code of my serializers.py and model.py class
serializers.py
class SliderImageSerializers(serializers.ModelSerializer):
class Meta:
model=SliderImage
fields='url','rank'
class ItemVariationsSerializer(serializers.ModelSerializer):
# items = ItemsSerializer(many=True, read_only=True)
class Meta:
model = ItemVariation
fields ='price','item_code','image'
class RestaurantSerializers(serializers.ModelSerializer):
items = ItemVariationsSerializer(many=True, read_only=True)
sliders = SliderImageSerializers(many=True, read_only=True)
class Meta:
model=Restaurant
fields=('__all__')
models.py
class ItemVariation(models.Model):
restaurant=models.ForeignKey(Restaurant,on_delete=models.CASCADE)
item=models.ForeignKey(Item,on_delete=models.CASCADE)
price=models.IntegerField(blank=True,null=True,default=0)
item_code=models.CharField(max_length=500)
keyword= models.ManyToManyField(Keyword)
image=models.ImageField(upload_to='dishes/', blank=True, null=True)
def __str__(self):
return str(self.id)
Below is response that i received
response:
{
"id": 1,
"sliders": [
{
"url": "/media/restaurant/download_2.jpeg",
"rank": 1
}
],
"name": "Haveli",
"email": "test#tet.com",
"web": "wdew",
"short_description": "dsfsdf",
"description": "fsdfsd",
"phone": 21315,
"lat": 30.704649,
"lng": 76.717873,
"address1": "dsff",
"address2": "vfdg",
"city": "sdfds",
"state": "fs",
"postalcode": "sdfsd",
"avg_rating": 1,
"price": 0,
"restaurant_type": 1,
"keywords": [
1,
2,
3
]
}
I need to add ItemVariationsSerializer to RestaurantSerializers response
but i need response like below
{
"id": 1,
"sliders": [
{
"url": "/media/restaurant/download_2.jpeg",
"rank": 1
}
],
"name": "Haveli",
"email": "test#tet.com",
"items":[
{
"price":"213"
"item_code":"testr"
}
]
"keywords": [
1,
2,
3
] }
I need your help to get needed response. Thanks