Save multiple values in foreign key django - python

I wanted to save multiple relational objects in a foreign key but unfortunately, I'm getting an error which I attached below. I already have the object with ID of 189 in my DB
error:
{
"tags": [
"Invalid pk \"189\" - object does not exist."
]
}
views.py
queryset = PackageRoom.objects.all()
serializer = PackageRoomSerializer(queryset, many=True)
return Response(serializer.data)
serializers.py
class PackageRoomSerializer(serializers.ModelSerializer):
tags = serializers.PrimaryKeyRelatedField(queryset=PackageRoom.objects.all(), many=True)
class Meta:
model = PackageRoom
fields = ['id', 'name', 'description', 'tags']
models.py
class Tag(models.Model):
name = models.CharField(max_length=255, default='')
description = models.CharField(max_length=255, default='')
singleline = models.ManyToManyField(Singleline)
class Meta:
db_table = 'tags'
class PackageRoom(models.Model):
name = models.CharField(max_length=255, default='')
tags = models.ForeignKey(Tag, on_delete=models.PROTECT)
class Meta:
db_table = 'package_rooms'

It was a silly mistake that I was doing there that I was passing the PackageRoom model in my serializer but I need to pass the Tag model instead.
class PackageRoomSerializer(serializers.ModelSerializer):
tags = serializers.PrimaryKeyRelatedField(queryset=Tag.objects.all(), many=True)
class Meta:
model = PackageRoom
fields = ['id', 'name', 'description', 'tags']

Related

value error. model field must be an instance django

I want to save a list of the relational objects using IDs but unfortunately, I'm getting an error from Django which I attached below.
error:
Cannot assign "[<Tag: Tag object (189)>, <Tag: Tag object (190)>]":
"PackageRoom.tag" must be a "Tag" instance.
models.py
class Tag(models.Model):
name = models.CharField(max_length=255, default='')
description = models.CharField(max_length=255, default='')
singleline = models.ManyToManyField(Singleline)
class Meta:
db_table = 'tags'
class PackageRoom(models.Model):
name = models.CharField(max_length=255, default='')
tag = models.ForeignKey(Tag, on_delete=models.PROTECT)
class Meta:
db_table = 'package_rooms'
serializers.py
class PackageRoomSerializer(serializers.ModelSerializer):
tag = serializers.PrimaryKeyRelatedField(queryset=Tag.objects.all(), many=True)
class Meta:
model = PackageRoom
fields = ['id', 'name', 'description', 'tag']
views.py
serializer = PackageRoomSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
JSON object which is sent from Frontend:
{
"name": "example room",
"description": "lorem lipsum",
"tag": [189, 190]
}

Filtering issue in DRF

The problem I'm having looks like:
TypeError: init() got an unexpected keyword argument 'name'
"GET /apartmentimages/ HTTP/1.1" 500 136691
I have such a model.py class:
class Apartment(models.Model):
apartment_title = models.CharField(max_length=200)
apartment_description = models.TextField()
apartment_location = models.CharField(max_length=200)
apartment_people_quantity = models.PositiveIntegerField()
apartment_price = models.CharField(max_length=200)
apartment_type = models.CharField(max_length=50, null=True)
def __str__(self):
return self.apartment_title
class ApartmentImage(models.Model):
apartment = models.ForeignKey(Apartment, on_delete=models.CASCADE)
image = models.ImageField(upload_to='images/', null=True, blank=True)
And serializers.py class:
class ApartmentSerializer(serializers.ModelSerializer):
class Meta:
model = Apartment
fields = (
'id',
'url',
'apartment_title',
'apartment_description',
'apartment_location',
'apartment_people_quantity',
'apartment_price',
'apartment_type',
)
class ApartmentImageSerializer(serializers.ModelSerializer):
class Meta:
model = ApartmentImage
fields = ('id', 'url', 'apartment', 'image',)
in views.py:
apartment_id = django_filters.CharFilter(name="apartment__id",
queryset=Apartment.objects.all())
class Meta:
model = ApartmentImage
fields = ('apartment_id',)
class ApartmentImageView(viewsets.ModelViewSet):
queryset = ApartmentImage.objects.all()
serializer_class = ApartmentImageSerializer
filter_backends = (DjangoFilterBackend,)
filter_class = ApartmentImageFilter
You have no name as an attribute in django-filters. Maybe what are you looking for is field_name and neither do you need queryset=Apartment.objects.all(). If you are looking for a field that is field_name then your CharFielter should look like this apartment_id = django_filters.CharFilter(field_name="apartment__id", lookup_expr='iexact') and maybe if you haven't overwritten the id generation it should probably be a NumberFilter() if I am not wrong.

Django Model serializer returning ID

i've created the models and serializers as below
serializers.py
class ProductCategorySerializer(ModelSerializer):
class Meta:
model = ProductCategory
fields = ['id', 'name']
#staticmethod
def get_product_category_name(obj):
return obj.product_categories.name
class ProductSerializer(ModelSerializer):
product_categories = ProductCategorySerializer
class Meta:
model = Product
fields = ['id', 'name', 'default_price', 'description', 'product_categories']
models.py
class ProductCategory(models.Model):
class Meta:
db_table = 'itw_product_category'
verbose_name = 'product category'
verbose_name_plural = 'product categories'
name = models.CharField(max_length=50)
def __str__(self):
return self.name
class Product(models.Model):
class Meta:
db_table = 'itw_product'
verbose_name = 'product'
verbose_name_plural = 'products'
name = models.CharField(max_length=50)
default_price = models.FloatField(max_length=10)
description = models.TextField(max_length=50)
deleted = models.BooleanField(default=False)
product_categories = models.ManyToManyField(ProductCategory, verbose_name='product_categories', related_name='products')
Now, when i try to create a new model, product_categories returns only the id and not the name, what should i change?
Example:
{
"id": 25,
"name": "kms",
"default_price": 932.0,
"description": "kms",
"product_categories": [
5
]
}
You can display the string value in manytomanyfield fields with this method.
However, since you can update it with its numeric value when you want to update it, you will need to use a method or a separate serializer and view for updating, deleting and creating data to view the data.
class ProductCategory(models.Model):
product_categories = StringRelatedField(many=True)
class Meta:
db_table = 'itw_product_category'
verbose_name = 'product category'
verbose_name_plural = 'product categories'
name = models.CharField(max_length=50)
def __str__(self):
return self.name
Hope this can help you. Also, please read nested relationship.
class ProductSerializer(ModelSerializer):
product_categories = ProductCategorySerializer(many=True)

AttributeError at /apiv2/api/processorder/order/

I am trying to post multiple data into my DataBase Using Django Rest framework (DRF).
AttributeError at /apiv2/api/processorder/order/
Got AttributeError when attempting to get a value for field subcategory on serializer MyProcessOrderSerializer.
The serializer field might be named incorrectly and not match any attribute or key on the list instance.
Original exception text was: 'list' object has no attribute 'subcategory'.
models.py
class SubCategory(models.Model):
category = models.ForeignKey(Category, related_name='subcategory', on_delete=models.CASCADE)
name = models.CharField("Food Name", max_length=50, help_text="Name of The Food")
price = models.DecimalField("Food Price", max_digits=5, decimal_places=2)
quantity = models.PositiveIntegerField("Qty.", help_text="Quantity of the food Item you want")
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return f'{self.name}'
class Meta:
verbose_name = 'SubCategory'
verbose_name_plural = 'SubCategories'
class Order(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
bike = models.ForeignKey(User, related_name='bike', on_delete=models.CASCADE, blank=True, null=True)
package = models.ForeignKey(PackageType, related_name='package', on_delete=models.CASCADE, blank=True, null=True)
total_price = models.DecimalField(max_digits=10, decimal_places=2, default=0000.0)
qty = models.PositiveIntegerField(default=1)
shipping_address = models.CharField("Delivery Address", max_length=150)
paid = models.BooleanField(default=False)
ordernote = models.TextField("Order Notes", null=True)
shipped = models.BooleanField(default=False)
complete = models.BooleanField(default=False)
received = models.BooleanField(default=False)
refund_requested = models.BooleanField(default=False)
refund_granted = models.BooleanField(default=False)
ref_code = models.CharField(max_length=20, blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ('-created_at',)
def __str__(self):
return '{}'.format(self.id)
def order(self):
if not hasattr(self, '_order'):
self._order = self.order.all()
return self._order
'''
def get_total_cost(self):
total_cost = sum(orders.get_cost() for orders in self.order.all())
return total_cost
'''
class ProcessOrder(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
order = models.ForeignKey(Order, related_name='order', on_delete=models.CASCADE)
quantity = models.PositiveIntegerField("Qty.", default=1, help_text="Quantity of the food Item you want")
#category = models.ForeignKey(Category, related_name='category', on_delete=models.CASCADE)
subcategory = models.ForeignKey(SubCategory, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return f'{self.order} -- {self.subcategory.name}'
serializers.py
class MyProcessOrderSerializer(serializers.ModelSerializer):
#subcategory_name = serializers.RelatedField(source='subcategory.id', read_only=True)
#subcategory_set = SubCategoryOrderSerializer(many=True)
class Meta:
model = ProcessOrder
fields = ('quantity', 'subcategory', 'user')
read_only_fields = ('user', )
def create(self, validated_data):
return ProcessOrder.objects.create(**validated_data)
view.pf
#api_view(['POST'])
#permission_classes([IsAuthenticated])
def processorder_view(request):
orderuser = User.objects.get(id=request.user.id)
serializer = MyProcessOrderSerializer(data=request.data, many=True)
if serializer.is_valid():
order = Order.objects.create(user=orderuser, ref_code=create_ref_code())
order.save()
processorder = serializer.save(order=order, user=orderuser)
return Response(MyProcessOrderSerializer(processorder).data, status=status.HTTP_201_CREATED)
else: #return Response("Process Order Created Successfully")
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
I am now trying to make a POST such as this but getting the above error.
[{
"quantity": 16,
"subcategory": 1
},
{
"quantity": 14,
"subcategory": 3
}
]
You have to explicitly specify the relation in the serializer either with one of the built-in serializer:
Serializer relations
class MyProcessOrderSerializer(serializers.ModelSerializer):
# StringRelatedField and PrimaryKeyRelatedField are some of the built in ones.
subcategory = serializers.StringRelatedField(source='subcategory.id', read_only=True)
user = serializer.PrimaryKeyRelatedField()
class Meta:
model = ProcessOrder
fields = ('quantity', 'subcategory', 'user')
read_only_fields = ('user', )
def create(self, validated_data):
# If you want to accect new subcategory object via the endpoint you need further action here, see the docs.
return ProcessOrder.objects.create(**validated_data)
or by creating a custom subcategory serializer and then in serializer:
class UserSerializer(serializers.ModelSerializer):
class Meta:
fields = ('id', 'email', 'password', 'first_name', 'last_name')
class SubCategorySerializer(serializers.ModelSerializer):
class Meta:
fields = # whatever fields youd'e like to include
class MyProcessOrderSerializer(serializers.ModelSerializer):
# StringRelatedField is One of the built in ones.
sybcategory = SubCategorySerializer()
user = UserSerializer()
class Meta:
model = ProcessOrder
fields = ('quantity', 'subcategory', 'user')
read_only_fields = ('user', )
def create(self, validated_data):
# If you want to accect new subcategory object via the endpoint you need further action here, see the docs.
return ProcessOrder.objects.create(**validated_data)
And, I noticed you have Foreign Key to User in process order and order itself,
You could delete the user field from the process order and access it via the order relation, for that you can specify the user field in the subcategory serializer and the subcategory serializer in the process order serializer as I showed above.
And if I understand the purpose of creating a process order model, the relation should be a One to One and not Foreign key, But maybe I'm not seeing the whole picture here.
I think the problem apear in request.data in this line :
serializer = MyProcessOrderSerializer(data=request.data, many=True)
You should loop throught your object list and pass just the object not the whole list .
exemple :
{ "list_":[{"quantity": 7 ,"subcategory": 3}, {"quantity": 7 ,"subcategory": 3}] }
To get the first object from the request :
request.data.get('list_')[0]
I was able to solve the problem with this code both in my views and serialize
views.py
#api_view(['POST'])
#permission_classes([IsAuthenticated])
def processorder_view(request):
orderuser = User.objects.get(id=request.user.id)
data = request.data
order = Order.objects.create(user=orderuser, ref_code=create_ref_code())
if isinstance(data, list):
serializer = MyProcessOrderSerializer(data=request.data, many=True)
else:
serializer = MyProcessOrderSerializer(data=request.data)
if serializer.is_valid():
processorder = serializer.save(order=order, user=request.user)
return Response(status=status.HTTP_201_CREATED)
#return HttpResponse("Question created", status=201)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
serializers.py
class MyProcessOrderSerializer(serializers.ModelSerializer):
#subcategory_name = serializers.RelatedField(source='subcategory.id', read_only=True)
#subcategory_set = SubCategoryOrderSerializer(many=True)
#subcategory = serializers.StringRelatedField(source='subcategory.id', read_only=True)
class Meta:
model = ProcessOrder
fields = ('quantity', 'subcategory', 'user')
read_only_fields = ('user', )
def create(self, validated_data):
return ProcessOrder.objects.create(**validated_data)
Then, I was able to send multiple data with this sample.
[
{
"subcategory": 1,
"quantity": 12
},
{
"subcategory": 3,
"quantity": 12
}
]

Django's double-underscore notation not working here

I have combined these two answers: one and two In the attempt to select only certain fields from nested objects without any success at all, the result is returning ALL fields from all tables.
serializers:
class NameTestTypeSerializer(serializers.ModelSerializer):
class Meta:
model = TestTypeModel
fields = 'name'
class ExecutedTestSerializer(serializers.ModelSerializer):
test_type = NameTestTypeSerializer
class Meta:
model = ExecutedTestModel
fields = ('id', 'result', 'test_type')
depth = 1
models:
class TestTypeModel(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(null=False, max_length=255, unique=True)
........
class Meta:
db_table = 'TestType'
class ExecutedTestModel(models.Model):
id = models.AutoField(primary_key=True)
test_type = models.ForeignKey(TestTypeModel, to_field='id')
result = models.IntegerField(null=False)
class Meta:
db_table = 'ExecutedTest'
viewset:
class ExecutedTestViewSet(viewsets.ModelViewSet):
permission_classes = (IsAuthenticatedOrReadOnly,)
serializer_class = ExecutedTestSerializer
def get_queryset(self):
queryset = ExecutedTestModel.objects.all().select_related('test_type').defer('test_type__executable' )
return queryset
How did you check that executable is fetched? In django you can access deferred fields, they are loaded from db on demand.
I believe the problem isn't in underscore notation, instead it is in the definition of the serializers.

Categories

Resources