Discussion:
How to post to a model which contains a GenericForeignKey Content Type field?
kharis
2018-07-04 02:28:08 UTC
Permalink
Hi, I have a model in my application that has a Generic Relation, it uses
django content type framework and model view set
the official documentation I didn't understand how to do it after reading
http://www.django-rest-framework.org/api-guide/relations/#generic-relationships
, I find no section explaining how to POST the data.

class Bar1(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=
False)
data = models.CharField(max_length=20)

class Bar2(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=
False)
data = models.IntegerField()

class Foo(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=
False)
content_type = models.ForeignKey(ContentType, on_delete=models.PROTECT)
object_id = models.UUIDField()
contentObject = GenericForeignKey()


class FooViewSet(viewsets.ModelViewSet):
serializer_class = FooSerializer
queryset = Foo.objects.all()

class FooSerializer(serializers.ModelSerializer):
class Meta:
model = Foo
fields = ('__all__')


How can I post data to it?
I tried to post another object uuid (Bar1/Bar2) to it,

{
"content_type": "<<uuid>>",
"object_id" : "<<uuid>>
}

it doesn't work. it returns "Incorrect type. Expected pk value, received
str."

then I tried to get the content type object in serializer

def create(self, validated_data):
content_type = validated_data.get("object_id")
taggedObject = Bar1.objects.get(id=content_type) if
Bar1.objects.filter(id=content_type).count() > 0 else None
taggedObject = Bar2.objects.get(id=content_type) if
Bar2.objects.filter(id=content_type).count() > 0 and taggedObject == None
else None

if taggedObject is not None:
contentType = ContentType.objects.get_for_model(taggedObject)
if contentType is not None:
validated_data["content_type"] = contentType
validated_data["object_id"] = taggedObject
return super(FooSerializer, self).create(validated_data)

class Meta:
model = Foo
fields = ('__all__')
extra_kwargs = {
'content_type': {'required': False},
}

but it returns attribute error: UUID object has no attribute int.
If anyone knows how to do it, kindly share here :) thanks for checking out
my post

How to post to a model which contains a GenericForeignKey Content Type
field?
--
This message and any attachments may contain confidential information and
are intended only for the use of the intended recipient(s). Any disclosure,
distribution or copying of this message and any attachments is strictly
prohibited without approval from PT. Wisanamitra Argakarya. If you are not
the intended recipient, you should notify the sender and delete this
message immediately. PT. Wisanamitra Argakarya is not liable for any damage
caused by any virus or malicious file transmitted by this message. Any
views, opinions, or commitments expressed in this message do not
necessarily reflect the views of PT. Wisanamitra Argakarya.
--
You received this message because you are subscribed to the Google Groups "Django REST framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-rest-framework+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Jason
2018-07-04 11:26:44 UTC
Permalink
that documentation link shows how to do it, you just need to scroll down to
the TaggedObjectRelatedField example.

But I also think you have an issue with your model:

contentObject = GenericForeignKey()

should have the fields you want acting as FKs as parameters for GFK

there's also a package that could handle this for you:
https://github.com/Ian-Foote/rest-framework-generic-relations
--
You received this message because you are subscribed to the Google Groups "Django REST framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-rest-framework+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
kharis
2018-07-05 01:33:09 UTC
Permalink
Post by Jason
that documentation link shows how to do it, you just need to scroll down
to the TaggedObjectRelatedField example.
contentObject = GenericForeignKey()
should have the fields you want acting as FKs as parameters for GFK
https://github.com/Ian-Foote/rest-framework-generic-relations
I thought when using GenericForeignKey with no parameter, it searches for
the default field 'content_type' and 'object_id'
and the TaggedObjectRelatedField example is for converting object to
primitive dictionary. Isn't it used when returning GET request?

Thanks for the package reference, I might try that :)
--
This message and any attachments may contain confidential information and
are intended only for the use of the intended recipient(s). Any disclosure,
distribution or copying of this message and any attachments is strictly
prohibited without approval from PT. Wisanamitra Argakarya. If you are not
the intended recipient, you should notify the sender and delete this
message immediately. PT. Wisanamitra Argakarya is not liable for any damage
caused by any virus or malicious file transmitted by this message. Any
views, opinions, or commitments expressed in this message do not
necessarily reflect the views of PT. Wisanamitra Argakarya.
--
You received this message because you are subscribed to the Google Groups "Django REST framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-rest-framework+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
kharis
2018-07-05 09:08:02 UTC
Permalink
So apparently I just miss assigned the validated_data["object_id"]. It
should be assigned with an id not the instance. After I updated the create
def create(self, validated_data):
content_type = validated_data.get("object_id")
taggedObject = Bar1.objects.get(id=content_type) if Bar1.objects.
filter(id=content_type).count() > 0 else None
taggedObject = Bar2.objects.get(id=content_type) if Bar2.objects.
filter(id=content_type).count() > 0 and taggedObject == None else None


if taggedObject is not None:
contentType = ContentType.objects.get_for_model(taggedObject)
if contentType is not None:
validated_data["content_type"] = contentType
validated_data["object_id"] = taggedObject.id
return super(FooSerializer, self).create(validated_data)

It now works! Thanks!
--
This message and any attachments may contain confidential information and
are intended only for the use of the intended recipient(s). Any disclosure,
distribution or copying of this message and any attachments is strictly
prohibited without approval from PT. Wisanamitra Argakarya. If you are not
the intended recipient, you should notify the sender and delete this
message immediately. PT. Wisanamitra Argakarya is not liable for any damage
caused by any virus or malicious file transmitted by this message. Any
views, opinions, or commitments expressed in this message do not
necessarily reflect the views of PT. Wisanamitra Argakarya.
--
You received this message because you are subscribed to the Google Groups "Django REST framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-rest-framework+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Jason
2018-07-05 12:22:34 UTC
Permalink
nice find, and thanks for posting the solution :-)
So apparently I just miss assigned the validated_data["object_id"]. It
should be assigned with an id not the instance. After I updated the create
content_type = validated_data.get("object_id")
taggedObject = Bar1.objects.get(id=content_type) if Bar1.objects.
filter(id=content_type).count() > 0 else None
taggedObject = Bar2.objects.get(id=content_type) if Bar2.objects.
filter(id=content_type).count() > 0 and taggedObject == None else None
contentType = ContentType.objects.get_for_model(taggedObject)
validated_data["content_type"] = contentType
validated_data["object_id"] = taggedObject.id
return super(FooSerializer, self).create(validated_data)
It now works! Thanks!
--
You received this message because you are subscribed to the Google Groups "Django REST framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-rest-framework+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Loading...