eav-django models serialization with django rest framework - django

I'm using eav-django for a project and I need to serialize it's models with DjangoRestFramework, but I got some issues.
My models (models.py) are the standard models needed by eav-django:
class ServiceSchema(BaseSchema):
pass
class ServiceChoice(BaseSchema):
schema = models.ForeignKey(ServiceSchema, related_name='choices')
class ServiceAttr(BaseAttribute):
schema = models.ForeignKey(ServiceSchema, related_name='attrs')
choice = models.ForeignKey(ServiceChoice, related_name='attrs', null=True)
class ServiceEntity(BaseEntity):
title = models.CharField(max_length=100)
attrs = generic.GenericRelation(ServiceAttr, object_id_field='entity_id', content_type_field='entity_type')
#classmethod
def get_schemata_for_model(cls):
return ServiceSchema.objects.all()
def __unicode__(self):
return self.title
class ServiceFacetSet(BaseFacetSet):
def get_queryset(self, **kwargs):
return ServiceEntity.objects.filter(**kwargs)
class HostSchema(BaseSchema):
pass
class HostChoice(BaseChoice):
schema = models.ForeignKey(HostSchema, related_name='choices')
class HostAttr(BaseAttribute):
schema = models.ForeignKey(HostSchema, related_name='attrs')
choice = models.ForeignKey(HostChoice, related_name='attrs', null=True)
class HostEntity(BaseEntity):
title = models.CharField(max_length=100)
attrs = generic.GenericRelation(HostAttr, object_id_field='entity_id', content_type_field='entity_type')
services = models.ManyToManyField(ServiceEntity, null=True, blank=True, default=None, related_name='hosts')
#classmethod
def get_schemata_for_model(cls):
return HostSchema.objects.all()
def __unicode__(self):
return self.title
class HostFacetSet(BaseFacetSet):
def get_queryset(self, **kwargs):
return HostEntity.objects.filter(**kwargs)
And I'm trying to serialize them with this piece of code in serializers.py:
class ServiceSchemaSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = ServiceSchema
class ServiceChoiceSerializer(serializers.HyperlinkedModelSerializer):
schema = ServiceSchemaSerializer(many=False)
class Meta:
model = ServiceChoice
fields = ('schema', )
class ServiceAttrSerializer(serializers.HyperlinkedModelSerializer):
schema = ServiceSchemaSerializer(many=False)
choice = ServiceChoiceSerializer(many=False)
class Meta:
model = ServiceAttr
fields = ('schema', 'choice')
class ServiceEntitySerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = HostEntity
fields = ('title', 'attrs')
class HostSchemaSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = HostSchema
class HostChoiceSerializer(serializers.HyperlinkedModelSerializer):
schema = HostSchemaSerializer(many=False)
class Meta:
model = HostChoice
fields = ('schema', )
class HostAttrSerializer(serializers.HyperlinkedModelSerializer):
schema = HostSchemaSerializer(many=False)
choice = HostChoiceSerializer(many=False)
class Meta:
model = HostAttr
fields = ('schema', 'choice')
class HostEntitySerializer(serializers.HyperlinkedModelSerializer):
services = ServiceEntitySerializer(many=True)
class Meta:
model = HostEntity
fields = ('title', 'attrs', 'services')
Django rest framework error is [...] GenericRelatedObjectManager is not JSON serializable. Ok, got it. But there is some way to accomplish the serialization?

Related

models.E005 The field 'xxx' from parent model 'x.x' clashes with the field 'xxx' from parent model

Django inheritance error: (models.E005)
Do you have a solution to get around this problem, is there a way to add a prefix or idk because I must have several User with the same heritage?
Django dont like this:
class Dispositif(Infos, ChefGO, ADJChefGO):
bcs ChefGO and ADJChefGO depend on the same class Member, but i realy need two member
class Members(models.Model):
phone_regex = RegexValidator(regex=r'^[0-9]{10}$', message="Error: Format 0611223344")
indicative = models.CharField(max_length=16, default="Default indicative")
phone = models.CharField(max_length=10, validators=[phone_regex])
class Meta:
abstract = True
class ChefGO(Members):
pass
class ADJChefGO(Members):
pass
class Dispositif(Infos, ChefGO, ADJChefGO):
name = models.CharField(max_length=32, default="Name")
place = models.CharField(max_length=64)
start_date = models.DateTimeField(default=datetime.datetime.now)
end_date = models.DateTimeField(default=datetime.datetime.now)
Thanks
Are foreign keys a workaround there ?
# model
class Dispositif(Infos):
myChefGO = models.ForeignKey(ChefGO, on_delete=models.CASCADE)
myADJChefGO = models.ForeignKey(ADJChefGO, on_delete=models.CASCADE)
# instanciation
dispositif = Dispositif(Infos)
dispositif.myChefGO = A
dispositif.myADJChefGO = B
I have found solution with this method:
1- Create "Device" class with 'Fields' and 'Forms'
class Device:
#staticmethod
class Fields:
#staticmethod
class Member:
#staticmethod
def indicative():
return models.CharField(max_length=16, default="Default indicative")
#staticmethod
def phone():
phone_regex = RegexValidator(regex=r'^[0-9]{10}$', message="Error: Format 0611223344")
return models.CharField(max_length=10, validators=[phone_regex])
#staticmethod
def function():
return models.CharField(max_length=10)
#staticmethod
class Forms:
#staticmethod
class Member:
#staticmethod
def indicative():
return django.forms.TextInput(attrs={'placeholder': 'indivatif'})
#staticmethod
def phone(placeholder="06 12 34 56 78"):
return django.forms.TextInput(attrs={'placeholder': placeholder})
#staticmethod
def function():
return django.forms.TextInput(attrs={'placeholder': 'fonction'})
2- Use 'Device' Fields like this
class ChefGO(models.Model):
cgo_indicative = Device.Fields.Member.indicative()
cgo_phone = Device.Fields.Member.phone()
cgo_function = Device.Fields.Member.function()
class Meta:
abstract = True
class ADJChefGO(models.Model):
adjcgo_indicative = Device.Fields.Member.indicative()
adjcgo_phone = Device.Fields.Member.phone()
adjcgo_function = Device.Fields.Member.function()
class Meta:
abstract = True
3- Inheritance
class Dispositif(ChefGO, ADJChefGO):
pass
4- "Bonus"
You can use'it in ModelForm like that:
class DispositifForm(ModelForm):
class Meta:
model = Dispositif
fields = [
'cgo_phone', 'cgo_indicative', 'cgo_function',
'adjcgo_phone', 'adjcgo_indicative', 'adjcgo_function',
'dso_phone', 'dso_indicative', 'dso_function'
]
widgets = {
'cgo_phone': Device.Forms.Member.phone(),
'cgo_indicative': Device.Forms.Member.indicative(),
'cgo_function': Device.Forms.Member.function(),
'adjcgo_phone': Device.Forms.Member.phone(),
'adjcgo_indicative': Device.Forms.Member.indicative(),
'adjcgo_function': Device.Forms.Member.function(),
'dso_phone': Device.Forms.Member.phone(),
'dso_indicative': Device.Forms.Member.indicative(),
'dso_function': Device.Forms.Member.function()
}

checking if a certain many to many foreign key is present on django-polymorphic models

So in order to create an object model, I have to first see if a supplier has a relation of type many to many from BusinessModel, WarehouseModel or StoreModel to in a django-polymorphic
My main idea is to check if BusinessModel, which is connected to Order through BusinessOrderModel, StoreModel, which is connected to Order through StoreOrderModel or WarehouseModel which is connected directly to Order, have FKs on a many to many relationship going to the article that we want to order through a POST request.
class ArticleModel(models.Model):
id = models.AutoField(primary_key=True)
code = models.IntegerField(unique=True)
description = models.TextField()
def __str__(self):
return str(self.code)
class OrderModel(models.Model):
id = models.AutoField(primary_key=True)
order_to = models.ForeignKey('OrderToModel', on_delete=models.CASCADE)
article = models.ForeignKey('ArticleModel', on_delete=models.CASCADE)
quantity= models.IntegerField()
class OrderToModel(PolymorphicModel):
id = models.AutoField(primary_key=True)
class WarehouseModel(OrderToModel):
warehouse_num = models.IntegerField(unique=True)
name = models.CharField(max_length=100)
address = models.TextField()
articles = models.ManyToManyField(ArticleModel)
def __str__(self):
return "Warehouse"+ str(self.warehouse_num)
class StoreOrderModel(OrderToModel):
reference = models.IntegerField(unique=True)
store_num = models.ForeignKey('StoreModel', on_delete=models.CASCADE)
def __str__(self):
return str(self.reference)
class StoreModel(models.Model):
store_num = models.IntegerField(primary_key=True)
name = models.CharField(max_length=100)
address = models.TextField()
articles = models.ManyToManyField(ArticleModel)
def __str__(self):
return str(self.store_num)
class BusinessOrderModel(OrderToModel):
reference = models.IntegerField(unique=True)
business_num = models.ForeignKey('BusinessModel', on_delete=models.CASCADE)
def __str__(self):
return str(self.reference)
class BusinessModel(models.Model):
Business_num = models.IntegerField(primary_key=True)
name = models.CharField(max_length=100)
address = models.TextField()
articles = models.ManyToManyField(ArticleModel)
def __str__(self):
return str(self.Business_num)
Here's my serializers:
class WarehouseSerializer(serializers.ModelSerializer):
class Meta:
model = WarehouseModel
fields = ('id', 'warehouse_num')
class StoreOrderSerializer(serializers.ModelSerializer):
class Meta:
model = StoreOrderModel
fields = ('id', 'reference', 'store_num')
class DetailSerializer(serializers.ModelSerializer):
class Meta:
model = DetailModel
fields = ('id', 'detail')
class BusinessOrderSerializer(serializers.ModelSerializer):
details = DetailSerializer(many=True, read_only=True)
class Meta:
model = BusinessOrderModel
fields = ('reference', 'business_num','details')
class OrderToPolymorphicSerializer(PolymorphicSerializer):
model_serializer_mapping = {
WarehouseModel: WarehouseSerializer,
StoreOrderModel: StoreOrderSerializer,
BusinessOrderModel: BusinessOrderSerializer
}
and here's my view:
class OrderCreateView(generics.CreateAPIView):
queryset = OrderModel.objects.all()
serializer_class = OrderCreateSerializer

How to fix "the `.create()` method does not support writable nested fields by default" in Django API

I have a problem with creating new ratings for cars.
When i try to send a post request from Postman in order to create/add a new rating for a specific car i get the error:
The `.create()` method does not support writable nested fields by default.
These are my models:
class Car(models.Model):
name = models.CharField(max_length=50)
symbol = models.CharField(max_length = 5)
def __str__(self):
return self.name
class Type(models.Model):
name = models.CharField(max_length = 50)
fuel = models.CharField(max_length = 1)##1 or 2 for fuel type
car = models.ManyToManyField(Car)
def __str__(self):
return self.name
class Rating(models.Model):
rating = models.IntegerField(validators=[
MaxValueValidator(10),
MinValueValidator(0)
])
car = models.ForeignKey(Car, on_delete=models.CASCADE)
type = models.ForeignKey(Type, on_delete=models.CASCADE)
def __int__(self):
return self.rating
My serializers:
class CarSerializer(serializers.ModelSerializer):
class Meta:
model = Car
fields = ('id','name')
class TypeSerializer(serializers.ModelSerializer):
car = CarSerializer(many=True)
class Meta:
model = Type
fields = ('id','name', 'fuel', 'car')
#depth=2
class RatingSerializer(serializers.ModelSerializer):
type = TypeSerializer()
class Meta:
model = Rating
fields = ('id','rating', 'car', 'type')
def create(self, validated_data):
type_data = validated_data.pop('type')
rating = Rating.objects.create(**validated_data)
for t_data in type_data:
Type.objects.create(rating=rating, **t_data)
return rating
When i try to do a post request to rating such as :
{"rating":5, "car": 2,"type":{"id":1,"name":"OffRoad","fuel":"1","car":[{"id":2,"name":"Ford"}] } }
I get:
The `.create()` method does not support writable nested fields by default.
Please help if you can, ive been trying to fix this all day. Thank you!

Django response nested models

I have the following models:
class Asset(models.Model):
isin = models.CharField(max_length=100)
asset_type = models.CharField(max_length=50)
last_price = models.FloatField
security_weight = models.FloatField
update_date = models.DateTimeField
def __str__(self):
return self.isin
class Meta:
ordering = ('isin',)
class PortfolioElement(models.Model):
nominal = models.FloatField
weight = models.FloatField
asset = models.OneToOneField(
Asset,
on_delete=models.CASCADE,
primary_key=True,
)
def __str__(self):
return self.asset.isin
class Meta:
ordering = ('asset',)
class Portfolio(models.Model):
number = models.CharField(max_length=100)
update_date = models.DateTimeField
elements = models.ManyToManyField(PortfolioElement)
def __str__(self):
return self.number
class Meta:
ordering = ('number',)
class Client(models.Model):
number = models.CharField(max_length=100)
update_date = models.DateTimeField
portfolios = models.ManyToManyField(Portfolio)
def __str__(self):
return self.number
class Meta:
ordering = ('number',)
and the following serializer:
class ClientSerializer(serializers.ModelSerializer):
class Meta:
model = Client
fields = ('number', 'portfolios')
depth = 1
However, I would like to see the actual data in the portfolios (and portfolio elements). But when I try to make a GET request on an arbitrary Client (by the (Client).number field) I can only see the following:
{
"number": "28101317",
"portfolios": [
{
"id": 14,
"number": "5471-339425",
"elements": [
{
"asset": 326
},
{
"asset": 327
}, ... (and so on)
How can a tweak my code, so that I also can get the actual "asset" information?
/Niclas
You can try this:
class AssetSerializer(serializers.ModelSerializer):
class Meta:
model = Asset
fields = '__all__'
class PortfolioElementSerializer(serializers.ModelSerializer):
asset = AssetSerializer()
class Meta:
model = PortfolioElement
fields = ('nominal', 'weight', 'asset')
class PortfolioSerializer(serializers.ModelSerializer):
elements = PortfolioElementSerializer(many=True)
class Meta:
model = Portfolio
fields = ('number', 'update_date', 'elements')
class ClientSerializer(serializers.ModelSerializer):
portfolios = PortfolioSerializer(many=True)
class Meta:
model = Client
fields = ('number', 'portfolios')

Accessing model subclass attributes with django tastypie

I have a model that is sublcassed
class Foo(models.Model):
name = models.CharField(max_length=255)
child_model = models.CharField(max_length=255)
class Bar(Foo):
woots = models.ManyToManyField(Woot)
class Woot(models.Model):
color = models.CharField(max_length=255)
And some tastypie resources:
class FooResource(ModelResource):
class Meta:
queryset = Foo.objects.all()
class BarResource(ModelResource):
class Meta:
queryset = Foo.objects.all()
class WootResource(ModelResource):
class Meta:
queryset = Woot.objects.all()
When accessing the FooResource, I'd ideally like it to 'reroute' and return a BarResource instead if the child_model attribute == bar.
If I can't do that, then any way that I can get an array of woots serialized and into the bundle (when child_model attribute == bar) would be fine by me.
Try this:
class FooResource(ModelResource):
class Meta:
queryset = Foo.objects.all()
def dehydrate(self, bundle):
if bundle.data['child_model']=="bar":
return json.loads(BarResource().dispatch_list(bundle.request).content)
return bundle