How to resolve multiple querysets in graphene.Union? - python-3.x

I want to create a graphene.Union type of multiple existing types. I am able to resolve it but it is not in my required format.
Schema
from graphene_django import DjangoObjectType
class ageType(DjangoObjectType):
class Meta:
model = age
class ethnicityType(DjangoObjectType):
class Meta:
model = ethnicity
class combinedType(graphene.Union):
class Meta:
types = (ageType, ethnicityType)
class Query(graphene.ObjectType):
defaultPicker = graphene.List(combinedType)
def resolve_defaultPicker(self, info):
items = []
age_q = age.objects.all()
items.extend(age_q)
ethnicity_q = ethnicity.objects.all()
items.extend(ethnicity_q)
return items
The query I am using in the graphql admin:
{
defaultPicker{
... on ageType{
id
age
}
... on ethnicityType{
id
ethnicity
}
}
}
I want to get a output like this:
{
"data": {
"defaultPicker": [
'ageType': [{
"id": "2",
"ethnicity": "American",
"ethnicityFr": "Test"
}],
'ethnicityType': [{
"id": "1",
"familyPlans": "3 kids",
"familyPlansFr": "3 enfants"
}],
]
}
}
I tried many things but couldn't find a way to resolve it.

Related

Print the output in my desired format using nested serializers?

I am trying to send messages using django-rest framework.I have created serializers for both user and message.I am using django default user model for storing user's details.
I am pasting my model and serializers here:
class MessageModel(models.Model):
message = models.CharField(max_length=100)
created_at = models.DateTimeField(default=now)
updated_at = models.DateTimeField(default=now)
user = models.ForeignKey(User,on_delete=models.CASCADE,related_name='user')
class UserSerializer(ModelSerializer):
class Meta:
model = get_user_model()
fields = ['id','username','email']
class MessageSerializer(ModelSerializer):
created_by = UserSerializer(read_only=True)
class Meta:
model = MessageModel
fields = ['id','message', 'created_at', 'updated_at','user','created_by']
View :
class MessageViewSet(viewsets.ModelViewSet):
authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated]
queryset = MessageModel.objects.all()
serializer_class = MessageSerializer
After creating message,I am getting response like below:
{
"id": 6,
"message": "Lorem ipsum",
"created_at": "2022-11-07T09:21:19.492219Z",
"updated_at": "2022-11-07T09:21:19.492237Z",
"user": 2
}
but my output should looks like in below format,everytime when a new message is created :
{
"id": 102,
"message": "Lorem ipsum",
"created_at": "created time in UTC",
"updated_at": "last updated time in UTC",
"created_by": {
"id": 3,
"username": "testuser",
"email": "test#mail.com",
}
}
In case of any error, return the error message.
The name of the field is user, not created_by, so:
class MessageSerializer(ModelSerializer):
user = UserSerializer(read_only=True)
class Meta:
model = MessageModel
fields = ['id', 'message', 'created_at', 'updated_at', 'user']
or you can specify user as source:
class MessageSerializer(ModelSerializer):
created_by = UserSerializer(read_only=True, source='user')
class Meta:
model = MessageModel
fields = ['id', 'message', 'created_at', 'updated_at', 'created_by']
Note: Models normally have no …Model suffix. Therefore it might be better to rename MessageModel to Message.
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.
Note: The related_name=… parameter [Django-doc]
is the name of the relation in reverse, so from the User model to the MessageModel
model in this case. Therefore it (often) makes not much sense to name it the
same as the forward relation. You thus might want to consider renaming the user relation to messages.

Nested serializer representation for PrimaryKeyRelatedField

I want to add and remove products to an order by only using their ids, but I want the order representation to look like a nested serializer.
My Models:
class Product(models.Model):
title = models.CharField(max_length=200)
price = models.DecimalField(max_digits=1_000, decimal_places=2)
def __str__(self):
return self.title
class Order(models.Model):
date = models.DateField()
products = models.ManyToManyField(Product, blank=True, related_name='orders')
My Serializers:
class ProductSerializer(serializers.ModelSerializer):
price = serializers.DecimalField(max_digits=1_000,
decimal_places=2,
coerce_to_string=False)
class Meta:
model = Product
fields = ['id', 'title', 'price']
class OrderSerializer(serializers.ModelSerializer):
products = serializers.PrimaryKeyRelatedField(queryset=Product.objects.all(), many=True)
class Meta:
model = Order
fields = ['id', 'date', 'products']
I'm trying to get the below representation:
{
"id": 1,
"date": "2021-08-12",
"products": [
{
"id": 1,
"title": "Item 1",
"price": 19.99
},
{
"id": 3,
"title": "Item 3",
"price": 49.99
}
]
}
However, if I want to create the above order the json should look like this:
{
"date": "2021-08-12",
"products":[1, 3]
}
And if I want to add a product with id==2 to the above order it should look like this:
{
"id": 1,
"date": "2021-08-12",
"products":[1, 3, 2]
}
I've tried overriding the to_representation() method and adding a nested serializer there, but I have no idea how to go about it. Should it look something like this, or am I going in a completely wrong direction here?
def to_representation(self, instance):
data = super().to_representation(instance)
data['products'] = ProductSerializer(data=instance['products'])
return data
Ended up fixing it with the to_representation() method. I don't know if this is the best way to do it, but it works for now.
def to_representation(self, instance):
data = super().to_representation(instance)
products_list = []
for product_id in data['products']:
product = instance.products.get(pk=product_id)
products_list.append(
{
'id': product.id,
'title': product.title,
'price': product.price
}
)
data['products'] = products_list
return data
use Nested Serializer Relationships.
and your OrderSerializer serializer class will be like this:
class OrderSerializer(serializers.ModelSerializer):
products = ProductSerializer(many=True)
class Meta:
model = Order
fields = ['id', 'date', 'products']

Scalarize a nested field using marshmallow

I have two Database Models like this
class Setting(db.Model):
id = db.Column(db.Integer, id=True)
container_id = ST_db.Column(ST_db.Integer, db.ForeignKey('settings_container.id'))
setting_name = ST_db.Column(ST_db.String(50))
setting_value = ST_db.Column(ST_db.String(50))
class SettingsContainer(db.Model):
id = db.Column(db.Integer, id=True)
settings = db.relationship('Settings', backref='container', cascade='all, delete')
When I serialize the model SettingsContainer using the following schemas
class Setting(ma.Schema):
class Meta:
fields = (
'setting_name',
'setting_value',
)
class SettingsContainer(ma.Schema):
settings = ST_ma.Nested(Setting, many=True)
class Meta:
fields = (
'id',
'settings'
)
What I get is
[
{
"id": 1
"settings": [
{
"setting_name": 'name1',
"setting_value": 'value1'
},
{
"setting_name": 'name2',
"setting_value": 'value2'
},
}
"id": 2
"settings": [
{
"setting_name": 'name3',
"setting_value": 'value3'
},
{
"setting_name": 'name4',
"setting_value": 'value4'
},
]
But I want to get data in the format of
[
{
"id": 1
"settings": [['name1', 'value1'], ['name2', 'value2']]
}
{
"id": 2
"settings": [['name3', 'value3'], ['name4', 'value4']]
}
]
I want to able to extract the Nested fields, I don't understand how to do it using the ma.Function method, thanks a lot to everyone in advance.
Okay so I found out the answer, what I have to do is to use ma.Function with ma.Pluck
The appropriate serializers are.
class Setting(ma.Schema):
complete_setting = ma.Function(lambda setting:(
setting.setting_name,
setting.setting_value,
))
class SettingsContainer(ma.Schema):
settings = ma.List(ma.Pluck(Setting, 'complete_setting'))
class Meta:
fields = (
'id',
'settings'
)

Not able to pass last inserted_id from parent serializer to children serializer with Django restframework

I am trying to save parent (VisVisits) and children (VisVistiData) table with same api call. Data is coming into json format. I am able to save both the table except one column visit_id in the children (VisVisitData) table. visit_id does not come from the json. It is auto number type field in parent table(VisVisits) and I want to take visit_id from parent(after gets insert) table and save it to their children ids with other column in children table (VisVisitData)
I really need help to fix this issue.
Serializer
class VisVisitsSerializer(serializers.ModelSerializer):
data = VisVisitDataSerializer(many=True)
class Meta:
model = VisVisits
fields = ('visit_id','user','data')
read_only_fields = ['visit_id']
def create(self, validated_data):
visits_data = validated_data.pop('data')
visit = VisVisits.objects.create(**validated_data)
for visit_data in visits_data:
VisVisitData.objects.create(visit_id=visit.visit_id, **visit_data)
return visit
class VisVisitDataSerializer(serializers.ModelSerializer):
class Meta:
model = VisVisitData
fields = ('__all__')
model
class VisVisits(models.Model):
visit_id = models.IntegerField(primary_key=True,auto_created=True)
user = models.ForeignKey(UsrUsers, models.DO_NOTHING, blank=False, null=False)
def __str__(self):
return str(self.visit_id)
class VisVisitData(models.Model):
vdata_id = models.IntegerField(primary_key=True,auto_created=True)
visit = models.ForeignKey('VisVisits', models.DO_NOTHING, blank=True, null=True, related_name='data')
def __str__(self):
return str(self.vdata_id)
json
{
"user": "1",
"visits": [
{
"action": "i",
"local_id": "170",
"data": [
{
"Active": "1",
"LocalID": "1905",
"VisitDataID": "",
},
{
"Active": "1",
"LocalID": "1906",
"VisitDataID": "",
},
{
"Active": "1",
"LocalID": "1907",
"VisitDataID": "",
},
{
"Active": "1",
"LocalID": "1908",
"VisitDataID": "",
},
{
"Active": "1",
"LocalID": "1909",
"VisitDataID": "",
}
]
}

flask-marshmallow custom fields

I use flask-marshmallow and mongoengine.
Also flask-restplus for my API server.
Here is my api.py
class BoardSchema(ma.Schema):
class Meta:
fields = ('no', 'title', 'body', 'tags', 'created_at', 'views')
board_schema = BoardSchema()
boards_schema = BoardSchema(many=True)
class ArticleList(Resource):
def get(self):
articles = Board.objects.all()
return boards_schema.jsonify(articles)
model.py
from datetime import datetime
from mongoengine import *
from config import DB_NAME
connect(DB_NAME)
class Board(Document):
d = datetime.now()
date = "{}-{}-{}".format(d.year, d.month, d.day)
no = SequenceField()
title = StringField(required=True)
body = StringField(required=True)
tags = ListField(StringField())
likes = ListField(StringField())
views = ListField(StringField())
password = StringField(required=True)
created_at = DateTimeField(default=date)
updated_at = DateTimeField(default=date)
When I access to /article, it's result like this ->
{
"body": "123",
"created_at": "2018-08-20T00:00:00+00:00",
"no": 1,
"tags": [
"MySQL",
"C"
],
"title": "\ud14c\uc2a4\ud2b8",
"views": [
"127.0.0.1"
]
}
in "views", ip will be added who read article.
But I want to count of all the list of views and include it to my result.
The result I wanted is here.
{
"body": "123",
"created_at": "2018-08-20T00:00:00+00:00",
"no": 1,
"tags": [
"MySQL",
"C"
],
"title": "\ud14c\uc2a4\ud2b8",
"views": 20
}
I'm new at flask-marshmallow so I'm so confused how can I solve this issue.
Thanks.
Maybe you can try like this:
class BoardSchemaCustom(ma.ModelSchema):
class Meta:
model = Board
views = ma.fields.method(deserialize="_custom_serializer")
def _custom_serializer(self, obj):
return len(obj.views)
Create instance of your custom schema:
custom_board_schema = BoardSchemaCustom()
and dump it:
dump, errors = custom_board_schema.schema.dump(Board.query.first())
>>> dump
i've got the same problem. and my code works after installing marshmallow-sqlalchemy
pip install marshmallow-sqlalchemy
see from offical documentation
https://flask-marshmallow.readthedocs.io/en/latest/
Below snippet would also work:
class BoardSchemaCustom(ma.ModelSchema):
class Meta:
model = Board
views = ma.fields.Function(lambda obj: len(obj.views))

Resources