Say I have model Team and it has a one-to-many relation with Player and Standin
I can serialize them like this:
class TeamSerializer(serializers.ModelSerializer):
...
players = PlayerSerializer(many=True)
standins = StandinSerializer(many=True)
class Meta:
model = Team
fields = '__all__'
So output will be:
{
"id": 17,
...
"players": [...],
"standins": [...]
}
How could i get:
{
"id": 17,
...
"roster": {
"players": [...],
"standins": [...]
}
}
override the to_representation method on your sereializer:
def to_representation(self, instance):
ret = super(TeamSerializer, self).to_representation(instance)
ret['roster'] = {
'players': ret['players'],
'standins': ret['standins']
}
del ret['players']
del ret['standins']
return ret
Related
I have the models:
class Boss(models.Model):
fullname = models.TextField()
class Shop(models.Model):
name = models.TextField()
address = models.TextField()
phone = models.TextField()
boss = models.ForeignKey(
Boss, on_delete=models.CASCADE, related_name="shops"
)
class Employee(models.Model):
name = models.TextField()
phone = models.TextField()
shop = models.ForeignKey(
Shop, on_delete=models.CASCADE, related_name="employees"
)
class WorkSpace(models.Model):
name = models.TextField()
employee = models.ForeignKey(
Shop, on_delete=models.CASCADE, related_name="work_spaces"
)
Serializers:
class WorkSpaceSerializer(serializers.ModelSerializer):
class Meta:
model = WorkSpace
fields = ["id","type"]
class EmployeeSerializer(serializers.ModelSerializer):
work_spaces = WorkSpaceSerializer(many=True, read_only=True)
class Meta:
model = Employee
fields = ["id","work_spaces","name","phone"]
class ShopSerializer(serializers.ModelSerializer):
employees = EmployeeSerializer(many=True, read_only=True)
class Meta:
model = Shop
fields = ["id","employees","phone","name","address"]
class BossSerializer(serializers.ModelSerializer):
shops = ShopSerializer(many=True, read_only=True)
class Meta:
model = Boss
fields = ["id","fullname","shops"]
View
class BossListView(
ListModelMixin,
GenericViewSet,
):
queryset = Boss.objects.all()
serializer_class = BossSerializer
permission_classes = [IsAuthenticated]
def get_queryset(self):
workspace_type = self.request.query_params.get("workspace_type")
qs = super().get_queryset()
if workspace_type:
qs = qs.filter(shops__employees__work_spaces__type=workspace_type).distinct()
return qs
I filtered with
Boss.objects.filter(shops__employees__work_spaces__type=C1)
and got:
{
"shops": [
{
"id": 32,
"name": "Garden flowers",
"address": "5 st. Hool-Maa",
"phone": "879124851861598",
"employees": [
{
"id": 150,
"name": "Mike",
"phone": "8154451246",
"work_spaces": [
{
"id": 497,
"type": "B12"
},
{
"id": 15,
"type": "Z5"
},
{
"id": 33,
"type": "C1"
}
]
}
]
}
]
}
But I only need C1 from work_spaces:
[{
"id": 33,
"type": "C1"
}]
How can I exclude other work_spaces from the queryset or do I need to convert the result to a list and then filter using a for loop? There can be many workspaces, and I don't need to show them all to the user, I need information about the Boss, the Shop, the Employee..
According to your view, you are applying the lower() method on the workspace_type.
So if you have workspace_type=C1, applying lower() will make workspace_type=c1, and your filter won't match any record.
I make here the assumption that your values have a capital letter.
I'm trying to make a query and the response as follows:
get_data = request.get_json()
email = get_data.get('email')
result = User.query.join(User_Preference).filter(User.email==email).first()
dump_data = developer_schema.dump(result)
return jsonify({'data' : dump_data})
from the following two tables defined as follows:
class User_Preference(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey(User.id))
preference = db.Column(db.String(45))
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(50), unique=True)
password = db.Column(db.String(256))
experience = db.Column(db.Integer)
avatar = db.Column(db.String(256))
revenue = db.Column(db.Integer)
preferences = relationship("User_Preference")
These are the marshmallow schemas I am using:
class DeveloperPreferences(ma.Schema):
class Meta:
fields = ('user_id', 'preference')
class DeveloperSchema(ma.Schema):
class Meta:
fields = ('id', 'email', 'avatar')
#model = User
preferences = ma.Nested(DeveloperPreferences, many = True)
However, the return I am getting is as follows:
{
"data": {
"avatar": "example.com",
"email": "example#test.com",
"id": 10
}
}
That is only the user part of the query is being returned not the preferences. Anyone have any idea on how to solve this?
In order to also display the preferences in the result, it is necessary to also specify the field in the fields to be displayed.
When defining the nested fields, you slipped into the meta specification with the indentation. However, the fields are set at the schema level.
class DeveloperPreferenceSchema(ma.Schema):
class Meta:
fields = ('user_id', 'preference')
class DeveloperSchema(ma.Schema):
class Meta:
fields = ('id', 'email', 'avatar', 'preferences')
preferences = ma.Nested(DeveloperPreferenceSchema, many=True)
The result should then be as follows.
{
"data": {
"avatar": "example.com",
"email": "example#test.com",
"id": 10,
"preferences": [
{
"preference": "anything",
"user_id": 10
},
{
"preference": "something",
"user_id": 10
}
]
}
}
Couldn't find problem like this, so here is my problem:
models.py (simplified)
class Root(models.Model):
name = models.CharField()
class TextFile(models.Model):
root = models.ForeignKey(Root)
name = models.CharField()
class ImageFile(models.Model):
root = models.ForeignKey(Root)
name = models.CharField()
serializers.py
class TextFileSerializer(serializers.Modelserializer):
class Meta:
model = TextFile
fields = '__all__'
class ImageFileSerializer(serializers.Modelserializer):
class Meta:
model = ImageFile
fields = '__all__'
class FilesSerializer(serializers.Modelserializer):
Texts = TextFileSerializer(source='textfile_set', many=True, read_only=True)
Images = ImageFileSerializer(source='imagefile_set', many=True, read_only=True)
class Meta:
model = Root
fields = '__all__'
class RootSerializer(serializers.Modelserializer):
files = FilesSerializer(many=True, read_only=True)
class Meta:
model = Root
fields = '__all__'
I've got only root 'id' and 'name' in output but no 'files'.
I expect output like this:
{
'id': 0,
'name': 'Root instance 1',
'files': {
'Texts': [
{'id': 0, 'name': 'Text1'},
{'id': 1, 'name': 'Text2'},
...
],
'Images': [
{'id': 0, 'name': 'Image1'},
{'id': 1, 'name': 'Image2'},
...
]
}
}
Can anyone help me with that?
Your FilesSerializer field in RootSerializer is always returning None because Root have no property named 'files'. DRF serializer don't add None fields in the response by default. Your FileSerializer ask for a RootModel.
What you want is a way to retrieve files from your root model, so what you can do is using a SerializerMethodField, and in this method, fetch the data you need, and serializer them using your FileSerializer (but as a normal serializer).
Like so :
class TextFileSerializer(serializers.ModelSerializer):
class Meta:
model = TextFile
fields = '__all__'
class ImageFileSerializer(serializers.ModelSerializer):
class Meta:
model = ImageFile
fields = '__all__'
class FilesSerializer(serializers.Serializer):
Texts = TextFileSerializer(source='textfile_set', many=True)
Images = ImageFileSerializer(source='imagefile_set', many=True)
class Meta:
fields = '__all__'
class RootSerializer(serializers.ModelSerializer):
files = serializers.SerializerMethodField()
class Meta:
model = Root
fields = '__all__'
def get_files(self, instance):
return FilesSerializer(instance).data
It returns
[
{
"id": 1,
"files": {
"Texts": [],
"Images": [
{
"id": 1,
"name": "testimage",
"root": 1
}
]
},
"name": ""
}
]
I want to send all the data in a response as string, like in database id is stored as integers but I want to send it as string in response.
eg: I have the response as
{
"categories": [
{
"id": 1,
"category": "xya",
"quantity": 25
}
]
}
I want it to be as:
{
"categories": [
{
"id": "1",
"category": "xya",
"quantity": "25"
}
]
}
I am using ModelSerializer to send all the fields.
Another option is to convert int to str using the to_representation method of your model serializer.
class YourSerializer(serializers.ModelSerializer):
# other fields
def to_representation(self, instance):
""" Override `to_representation` method """
repr = super().to_representation(instance)
repr['id'] = str(repr['id'])
repr['quantity'] = str(repr['quantity'])
return repr
You can explicitly define id field in your serializer to be CharField()
Like this
class YourSerializer(serializers.ModelSerializer):
# other fields
id = serializers.CharField()
class Meta:
model = SomeModel
fields = ('id', ..... other fields)
In below json response I want to update quantity of all productNumbers, Item count in response varies it could be 1 or more than 1, it depends on the input. how can I do that in Karate. I tried my way it did not work, so please provide a solution.(I provided my approach below please ignore if it is wrong approach)
{
"userProfileId": "12313123123",
"items": {
"47961": {
"products": {
"productNumber": "0000",
"productSummary": {
"productSubTotal": "$68.64",
"quantity": 3,
"productrice": "$22.88"
}
}
},
"47962": {
"products": {
"productNumber": "12345",
"productSummary": {
"productSubTotal": "$68.64",
"quantity": 3,
"productPrice": "$22.88"
}
}
},
"47963": {
"products": {
"productNumber": "1111",
"productSummary": {
"productSubTotal": "$68.64",
"quantity": 3,
"productPrice": "$22.88"
}
}
},
"47964": {
"products": {
"productNumber": "2222",
"productSummary": {
"productSubTotal": "$68.64",
"quantity": 3,
"productPrice": "$22.88"
}
}
}
}
}
I tried with like below by creating JS file and passing required values to it but it failing when I trying to call a feature file withing java script.(may be the way i am calling is incorrect)
Feature: Update
Scenario: Update all items in cart
* print 'config in called function '+upConfig
* print 'in called function '+orderItemIDs
* def updateAttempt =
"""
function(productNumbers,upConfig,firstOrderID){
for(i=0;i<orderItemIDs.length;i++){
karate.log('Run test round: '+(i+1));
var itemID = productNumbers[i];
karate.log('Order Item IDs :'+productNumbers[i]);
karate.log('Config log-'+upConfig);
karate.log('firstOrderItemID-'+firstOrderID);
karate.call('UpdateProductQuantity.feature') upConfig;
}
java.lang.Thread.sleep(1*1000);
}
"""
* def itemPrice = call updateAttempt(orderItemIDs,upConfig,firstOrderID)
Feature: test update
Scenario Outline: Update with all values
* def encodedURL = ''
* def gID = ''
* def upConfig = ''
* def firstOrderItemID = [47961]
* json productNumbers= orderItemIDs
* print 'productNumbers--'+orderItemIDs
* def list = call read('Update.feature') upConfig
* def result = call list productNumbers
* def result = call result firstOrderItemID
* print 'Result -'+result.response
Here you go:
* def response =
"""
{
"userProfileId":"12313123123",
"items": {
"47961": {
"products": {
"productNumber":"0000",
"productSummary": {
"productSubTotal":"$68.64",
"quantity":3,
"productPrice":"$22.88"
}
}
},
"47962": {
"products": {
"productNumber":"12345",
"productSummary": {
"productSubTotal":"$68.64",
"quantity":3,
"productPrice":"$22.88"
}
}
}
}
}
"""
* def fun = function(k, v){ response.items[k].products.productSummary.quantity = 100 }
* eval karate.forEach(response.items, fun)
* match each response..quantity == 100