Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Usage RESTfull API #425

Open
lafemmeduviking opened this issue Oct 4, 2023 · 4 comments
Open

Usage RESTfull API #425

lafemmeduviking opened this issue Oct 4, 2023 · 4 comments

Comments

@lafemmeduviking
Copy link

Hello,

I'm trying to use your module with the django rest framework but when I'm creating my entity from a serializer I loose the EAV fields.
Is there any way I can make it work?

Everything works fine from the admin.

thanks for your help

@Dresdn
Copy link
Contributor

Dresdn commented Oct 5, 2023

Since the model itself is registered, any usage should inherit the EAV fields. Have any code or anything to share?

@lafemmeduviking
Copy link
Author

This is my patterbn model :

class Pattern(models.Model):
name = models.CharField(max_length=200, blank=False, null=True)
creator = models.ForeignKey(Creator,
on_delete=models.DO_NOTHING,
blank=True,
null=True,
related_name="creator", default=None)
# category = models.CharField(max_length=100, blank=True, null=True)
# gender = models.CharField(max_length=100, blank=True, null=True)
# format = models.CharField(max_length=100, blank=True, null=True)
size = models.CharField(max_length=50, blank=True, null=True)
level = models.DecimalField(max_digits=2, decimal_places=1, blank=True, default=None, null=True)
is_published = models.BooleanField(default=False)

His advanced registration :

class PatternEavConfig(EavConfig):
manager_attr = 'objects'
manager_only = False
eav_attr = 'eav'
generic_relation_attr = 'eav_values'
generic_relation_related_name = None

@classmethod
def get_attributes(cls, instance=None):
    entity = ContentType.objects.filter(model='pattern').values('id')
    return Attribute.objects.filter(entity_ct=entity[0]["id"])

This the pattern serializer:

class PatternPostSerializer(serializers.ModelSerializer):
"""Pattern creation serializer with material / without images """
creator = serializers.PrimaryKeyRelatedField(queryset=Creator.objects.all())
attributes = AttributeSerializer(many=True, required=False)

class Meta:
    model = Pattern
    fields = ('id', 'name', 'creator', 'attributes', 'size', 'level')

def get_creator(self, object):
    print('object creator: ', object)
    if object.creator is None:
        return None
    else:
        return Creator.objects.filter(id=object.creator_id).values('id', 'name')

def get_attributes(self, object):
    return object.eav_values.all().values('value_enum_id', 'value_enum_value', 'attribute_slug')

def to_representation(self, instance):
    """Set field type for output only"""
    self.fields["creator"] = serializers.SerializerMethodField()
    self.fields["attributes"] = serializers.SerializerMethodField()
    return super().to_representation(instance)

def create(self, validated_data):
    attributes = []
    if 'attributes' in validated_data:
        attributes = validated_data.pop('attributes')
        print('attributes', attributes)

    pattern_instance = Pattern.objects.create(**validated_data)

    for attribute in attributes:
        if attribute:
            Value.objects.create(entity=pattern_instance,
            #                              entity_ct_id=21,
                                 attribute=attribute['attribute'],
                                 value_enum=attribute['value_enum'])
    return pattern_instance

The attributes serializer :

class AttributeSerializer(serializers.ModelSerializer):
class Meta:
model = Value
fields = ['attribute', 'value_enum']

POST example:

Screenshot from 2023-10-05 09-45-57

Thanks a lot

@Dresdn
Copy link
Contributor

Dresdn commented Oct 5, 2023

Thanks for sharing as that helps provide some context. One thing to note, you didn't specify what the actual error message/problem you were having, so I'm going to have guess some.

Focusing on the serializer, it seems like you're trying to manually create a Value object based on the attribute data passed in. This seems like a lot of effort and probably where you're seeing a problem since there's a lot of underlying relationships that the Manager creates for you.

I would say there's 2 paths to take:

  1. If you want to pass in the FK id's, then take a look at how Entity.save_value() handles this.
  2. Alternatively, you use the IDs to get the Attribute by the id and then do a setattr(entity, attribute.slug, value) with a instance.save() at the end

Here's how you could do it based on your code:

def create(self, validated_data):
  attributes = validated_data.pop('attributes', None)
  
  pattern_instance = Pattern(**validated_data)
  # Get the Entity for the instance
  entity = pattern_instance.eav

  for attribute in attributes:
    attr = instance.get_all_attributes().get(id=attribute[attribute]) # You'll want to wrap this in a try in case the Attribute isn't associated with the Entity
    # Code to handle the enum e.g. value = attr.enum_group.values.get(pk=attribute[value_enum])
    setattr(entity, attr.slug, value)

  # Save the object like normal and let the eav manager do it's thing on creating the Value objects
  pattern_instance.save() # wrap in a try to return any validation errors

@lafemmeduviking
Copy link
Author

Thanks a lot for your help ! It works fine.

I had no error, just no new attribute for my entity pattern.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants