I am creating an api for post to add a record into my table but the problem is that i have two tables named as orders and order_items and the attributes of both tables are For orders:-
order_id,customer_id,waiter_it,status,Date
For order_items:-
Order_id, Item_id, Quantity
All i need to ask is that can i add the data in both of these tables in a signle function? if it is possible than kindly guide me how if not then suggest me do i have to make POST api for both of these tables seperately:
my POST function looks like something this:
@api_view(['POST', ])
def add_order(request):
order=Orders()
if request.method == 'POST':
serializer = OrdersSerializer(order, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
yes you can use 2 tables in function also. PFB the some of the approaches
Approach 1:
Create new serializer in serializer.py file and use the same in views.py like below
class OrderSerializer(serializers.ModelSerializer):
class Meta:
model = Order
class OrderItemSerializer(serializers.ModelSerializer):
class Meta:
model = OrderItem
class CombineSerializer(serializers.Serializer):
order = OrderSerializer(many=True)
order_item = OrderItemSerializer(many=True)
Approach 2
You can use this library to achieve this,
DjangoRestMultipleModels
Check this if it helps
in approach 1 kindly guide me how to store the request.data in CombineSerializer: '''@api_view(['POST', ]) def add_order(request): order=Orders() oitems=OrderItems() if request.method == 'POST': serializer = #what should be written here ? '''
- moazamrana22 4 years, 10 months agoI can help you with the entire code. But I would suggest, please try some logic from your end and let us know if you still stuck, I can give you the hint :)
- sunil 4 years, 10 months agookay! i have done pretty much work on it i have crated nested seializers but when i try to add the data into the tables. It adds the data fine accept one attribute that is menu_id From postman i had inserted the data that is :- { "order_id": 5, "waiter": 1, "customer": 1, "cheff": 2, "order_status": "Pending", "order_time": "2020-06-15T13:45:12Z", "orderitems": [ { "order_id": 3, "menu_id": 1, "quantity": 1, "order_items_id": 8 }, { "order_id": 3, "menu_id": 2, "quantity": 2, "order_items_id": 9 } ] } it returned me the data after adding it that is:- { "order_id": 6, "waiter": 1, "customer": 1, "cheff": 2, "order_status": "Pending", "order_time": "2020-06-15T13:45:12Z", "orderitems": [ { "order_id": 6, "menu_id": null, "quantity": 1, "order_items_id": 9 }, { "order_id": 6, "menu_id": null, "quantity": 2, "order_items_id": 10 } ] } i dont know what is the problem in the database too it is inserting menu_id=null
- moazamrana22 4 years, 10 months agoserializers.py class OrderItemsSerializer(serializers.ModelSerializer): #order_id = serializers.IntegerField(required=True) class Meta: model=OrderItems fields=['order_id','menu_id','quantity','order_items_id']
class OrdersSerializer(serializers.ModelSerializer): orderitems=OrderItemsSerializer(many=True) class Meta: model=Orders fields=['order_id','waiter','customer','cheff','order_status','order_time','orderitems']
def create(self, validated_data):
orderitems_data = validated_data.pop('orderitems')
order = Orders.objects.create(**validated_data)
for x in orderitems_data:
OrderItems.objects.create(order=order, **x)
return order
-
moazamrana22
4 years, 10 months ago
models.py ''' class Orders(models.Model): order_id = models.AutoField(primary_key=True) waiter = models.ForeignKey('Waiters', models.DO_NOTHING, blank=True, null=True) customer = models.ForeignKey(Customers, models.DO_NOTHING, blank=True, null=True) cheff = models.ForeignKey('Cheffs', models.DO_NOTHING, blank=True, null=True) order_status = models.CharField(max_length=20, blank=True, null=True) order_time = models.DateTimeField(blank=True, null=True)
def __str__(self):
return self.order_id
class Meta:
managed = False
db_table = 'orders'
class OrderItems(models.Model): order = models.ForeignKey('Orders', models.DO_NOTHING, related_name='orderitems',blank=True, null=True) menu = models.ForeignKey(Menus, models.DO_NOTHING, blank=True, null=True) quantity = models.IntegerField(blank=True, null=True) order_items_id = models.AutoField(primary_key=True)
class Meta:
managed = False
db_table = 'order_items'
'''
- moazamrana22 4 years, 10 months agoseems like you are talking about different issue right. Initially this ticket raised for different issue, i hope that has been resolved. Now you are talking about different issue.
- sunil 4 years, 10 months agoNeed to add (POST) data into two tables(models) using 1 api_call
- moazamrana22 4 years, 10 months agoMay i know the API you are calling from POSTMAN?. Also can you add print statement
in your views.py & serializer.py and see what is there is menu_id when you calling.
okay! http://127.0.0.1:8000/api/order this is the url that i called through postman url(r'^order',OrderListView.as_view()) this is the url in api/urls.py and i'll print the value in serializer then get back to you
- moazamrana22 4 years, 10 months agoclass OrderListView(generics.ListCreateAPIView): queryset = Orders.objects.all() serializer_class = OrdersSerializer this is views.py
- moazamrana22 4 years, 10 months agoCan you help me with accessing menu_id in views.py and serializer.py ??
- moazamrana22 4 years, 10 months agoThe attribute menu_id in the orderItems is actually a foreign key is that can be a problem ??
- moazamrana22 4 years, 10 months agoIts ok no worries !!!
for x in orderitems_data:
print(x.menu_id)
OrderItems.objects.create(order=order, **x)
return order
Try like this
but still you can insert foreign key data into the Table.
Because you are just sending the hardcoded data from POSTMAN right
So it ideally it should insert the foreign key data as well.
AttributeError: 'collections.OrderedDict' object has no attribute 'menu_id' it throws the above error
- moazamrana22 4 years, 10 months agothe json object i had inserted was this -->> { "order_id": 7, "waiter": 1, "customer": 1, "cheff": 2, "order_status": "Pending", "order_time": "2020-06-15T13:45:12Z", "orderitems": [ { "order_id": 3, "menu_id": 1, "quantity": 1, "order_items_id": 8 }, { "order_id": 3, "menu_id": 2, "quantity": 2, "order_items_id": 9 } ] }
- moazamrana22 4 years, 10 months agowhy you have this line orderitems_data = validated_data.pop('orderitems')
- bhavana 4 years, 10 months agowasn't it for storing the poped value in orderitems_data ? i don't know i am very new to django rest_framework + django itself i had followed some tutorials .
- moazamrana22 4 years, 10 months agofrom the orderitems it is just having the value of quantity the same that i had provided and order_id and order_items_id are auto increment on the database thats why there value is generated automatically
- moazamrana22 4 years, 10 months agovalidated_data is a dictionary and .pop(key) searches for the key specified and returns and removes it if it is found, otherwise an exception is thrown.
- bhavana 4 years, 10 months agoi think you should focus on Django & Python project. Once you familiar with that, move on to Rest framework. That is my suggestion friend.
- bhavana 4 years, 10 months agoIs there any other way i can recreate the create method i mean with some other logic ? to store the values in orders and orderitems tables.
- moazamrana22 4 years, 10 months agoI have to do it for my FYP , though thanks for your suggestion.
- moazamrana22 4 years, 10 months agoNot sure what was the wrong in your code. lets try this, remove the for loop in OrderSerailizer
and just have this OrderItems.objects.create(order=order, **orderitem_data)
it throws this error ''' TypeError: create() argument after ** must be a mapping, not list '''
- moazamrana22 4 years, 10 months agocan you try pass only order_item from POST call . Also put back the for loop and send me the code after the execution
- bhavana 4 years, 10 months ago{ "order_id": 13, "waiter": 1, "customer": 1, "cheff": 2, "order_status": "Pending", "order_time": "2020-06-15T13:45:12Z", "orderitems": [ { "order_id": 13, "menu_id": null, "quantity": 1, "order_items_id": 15 } ] }
- moazamrana22 4 years, 10 months agostill sending the menu_id=null actually it is getting the value of quantity only
- moazamrana22 4 years, 10 months agofrom orderitems only the value of quantity is being passed in orderitems_data
- moazamrana22 4 years, 10 months agoAdd this in OrderItem serilizer and try this
def validate_menu_id(self, data):
menu_id= self.initial_data.get('menu_id')
print(menu_id)
return data
basically we are trying to see whether we are getting data in OrderItemSerializer or not
- bhavana 4 years, 10 months agoN.p i had written this function but it is not printing any thing i think it should be called somewhere ? talking about validate_menu_id
- moazamrana22 4 years, 10 months agoi had checked output for the print command in the terminal and for the json object in the POSTMAN
- moazamrana22 4 years, 10 months agook try something in your django shell
from rest_framework.renderers import JSONRenderer
data =
{ "order_id": 7, "waiter": 1, "customer": 1, "cheff": 2, "order_status": "Pending", "order_time": "2020-06-15T13:45:12Z", "orderitems": [ { "order_id": 3, "menu_id": 1, "quantity": 1, "order_items_id": 8 }, { "order_id": 3, "menu_id": 2, "quantity": 2, "order_items_id": 9 } ] }
json = JSONRenderer().render(serializer.data)
json
okay just need to tell you that i had printed the validated_data['order_items'] in the first line of create method and it printed only quantity which means it only saves the quantity from the input
- moazamrana22 4 years, 10 months ago''' def create(self, validated_data): print(validated_data['orderitems']) '''
- moazamrana22 4 years, 10 months agosomething which made me worried is that do i need add the serializer of menu in the nested serialization ? because menu_id is a foreign key which comes from menu table just need to know about this !
- moazamrana22 4 years, 10 months agohmm correct you dont have menu_id column at all in your model right?..
- bhavana 4 years, 10 months agoclass OrderItemSerializer(serializers.ModelSerializer): menu_name = serializers.RelatedField(source='menu', queryset=Menu.objects.all())
class Meta:
model = Item
fields = ['order_id','menu_name','quantity','order_items_id']
If you want to retrieve all ForeignKey columns then use above method
- bhavana 4 years, 10 months agoI think this will work i had updated the orderItemsSerializer as you told me now it is returning me the data in jason form like this { "waiter": 2, "customer": 1, "cheff": 1, "order_status": "Pending", "order_time": "2019-06-15T13:45:12Z", "orderitems": [ { "order_id": 50, "menu_id": 2, "quantity": 9, "order_items_id": 2 }, { "order_id": 50, "menu_id": 1, "quantity": 2, "order_items_id": 2 } ] } First it ignores the order_id and the second issue is it is not updating the database
- moazamrana22 4 years, 10 months agoi think it is not enetering in the ceate method in the mother serializer that is:- ''' class OrdersSerializer(serializers.ModelSerializer): orderitems=OrderItemsSerializer(many=True) class Meta: model=Orders fields=['order_id','waiter','customer','cheff','order_status','order_time','orderitems'] def create(self, validated_data): print(validated_data['orderitems']) orderitems_data = validated_data.pop('orderitems') order = Orders.objects.create(*validated_data) for x in orderitems_data: #print(x) OrderItems.objects.create(order=order, *x) return order '''
- moazamrana22 4 years, 10 months agoit is because it is not printing the validated data in the terminal that i had in the create method
- moazamrana22 4 years, 10 months agoplus implementing the above orderitemsSerializer it had blocked my get api' just want to tell you that menu_id was included in the OrdersItems model as a foreign key
- moazamrana22 4 years, 10 months agoi think there is some another issue or the communication gap :p BTW thank you i am going to close the ticket.
- moazamrana22 4 years, 10 months agoThank you. You just need to play around with the examples which we shared, if you adjust your code it should work. Nothing sooper dooper :)
- bhavana 4 years, 10 months agoLooks like quite long conversation. Hopefully it helped you to move forward. Thanks all Techions !!!
- Vengat
Acknowledged.