Django - Cannot assign, must be a instance - python

This issue was raised several times, though I guess I'm getting it from a different reason, or at least I can't tell how it's related.
Django: 1.10.5, Python: 3.5.2, Postgres: 9.5
So, I have such models (simplified):
class Parent(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
date_created = models.DateTimeField(auto_now=True)
class Child(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
date_created = models.DateTimeField(auto_now=True)
parent = models.ForeignKey(Parent)
def __init__(self, parent, *args, **kwargs):
super(Child, self).__init__(*args, **kwargs)
self.parent = parent
I have a custom queryset:
class ChildQuerySet(models.query.QuerySet):
def find_recent(self):
return self.order_by('-date_created')
Child.objects = ChildQuerySet.as_manager()
Then, I'm trying to test some custom queryset method for child:
class ChildQuerysetDatabaseIntegrationTest(TestCase): # from django.test
default_parent = Parent()
def setUp(self):
super(ChildQuerysetDatabaseIntegrationTest, self).setUp()
self.default_parent.save()
def test_find_recent(self):
# given
for _ in range(1, 10):
child = Child(self.default_parent)
child.save()
# when
recent = Child.objects.find_recent()
ordered = Child.objects.order_by('-date_created')
# then
self.assertEqual(list(ordered), list(recent))
This produces following error on the last line of test (fetching all entities):
ValueError: Cannot assign "UUID('...')": "Child.parent" must be a "Parent" instance.
Usually, when there's some mapping error, the error is thrown during entity saving, but here everything seems to persist successfully, but then fails on retrieval.
The UUID object that is tried to be assigned to parent instance, is actually child's id object, which makes me even more confused.
I tried changing object creation to Parent.objects.create(), but the result didn't change. Calling any function that retrieves a Child object, like ordered.first(), also fails, so I have no clue what's happening.

The problem is your custom constructor for Child. When the ORM is trying to retrieve results, the overridden constructor prevents the ORM from passing in the column values to instantiate the instance properly. In other words, the ORM is trying to pass in the values in the column-specified order, e.g.,
Child(id, date_created, parent)
while the custom constructor expects values to be passed in the following order:
Child(parent, . . .)
To resolve this issue, remove your custom constructor and use
instance = Child(parent=parent)
whenever you want to initialize a child with a parent.

Related

How to bind two models in __init__ via related_name when calling only parent, creating an empty object

I have two models, as below, linked by the OneToOneField relationship. How can I check by related_name
that there is a link to x.RelName before I use x.save (). Everything below ...
models.py
class Parent(models.Model):
name = models.CharField(max_length=255)
member = models.ForeignKey(User, related_name="MemberUsr", blank=True, null=True, default=None, on_delete=models.CASCADE)
class Child(models.Model):
child_name = models.CharField(max_length=255, null=True, blank=True)
parent_name = models.OneToOneField(Parent, related_name='RelName', null=True, on_delete=models.CASCADE)
py manage.py shell
>>> from app1.models import Parent, Child
>>> x = Parent()
And at this point there should be an artificial connection in _ _ init _ _
>>> x.RelName
Should return that it is artificially bound to Child. If I run x.save () it obviously creates linkages.
But I would like to be able to check with related_name before save () that there is a binding.
Update
Solution
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
cls = self.__class__
cls_child = cls._meta.get_field('RelName').related_model
self.RelName = cls_child(self)
def save(self, **kwargs):
super().save(**kwargs)
cls = self.__class__
cls_child = cls._meta.get_field('RelName').related_model
RelName = cls_child(parent_name=self)
RelName.save()
OK, I think you are misunderstanding the creation of objects. The error that mention you it is because you are not creating the parent instance before.
Check the documentation about How save objects.
For example, in your case:
from app1.models import Parent, Child
parent = Parent(name='Parent example', member= instance_user)
parent.save()
child = Child(child_name='Child', parent_name=parent)
child.save()
At this moment, you can write verify the relationship child.RelName
Other observation: you should rename your fields in model Child, just named as 'name' and 'parent'.
Update:
The documentation of python:
You may be tempted to customize the model by overriding the init
method. If you do so, however, take care not to change the calling
signature as any change may prevent the model instance from being
saved.
So, you could consider the options here: creating objects.

Passing instance method result to class attribute

Let's say I have two models, the first referencing a third User model:
class Parent(models.Model):
user = models.ForeignKey(User)
...
class Child(models.Model):
parent = models.ForeignKey(
Parent,
limit_choices_to={'user': get_user()}
)
def get_user(self):
return self.request.user
I want to limit choices for the child model to instances bound to current user. One way to do it would be to pass the request to the form class and solve it inside __init__, but it present's other limitations. Is there a way to do this inside the model class, kind of like in the example above?

Automatically create child object from parent - Django 1.11

I have a parent class:
class Parent(models.Model):
field1 = model.CharField()
field2 = model.CharField()
And a child:
class Child1(Parent):
pass
Is there a possible way to create a child object whenever a perent is saved?
The child inherits all the fields from the parent, but, regardless if filled or not, I would need to create a new child object whenever a parent is saved.
Any ideas?
You can use signals or you can override save method of Parent model to do that.
#receiver(models.signals.post_save, sender=Parent)
def post_parent_save(sender, instance, created, *args, **kwargs):
# Create child here
Or,
class Parent(models.Model):
def save(self, *args, **kwargs):
super(Parent, self).save(*args, **kwargs)
# Create child here
In both options, if you want to create a child only when a parent is created (not updated), you need to add extra login. For signals, you can use the created parameter, for overriding save method, you need to check if the model instance has an id field before calling super save method.
I'm wondering if something like this would work for you:
class Child1(Parent):
class Meta:
db_table = 'whateverappparentisin_parent'
managed = False
I'm not sure what Django would do with this, but the idea is that you get a model with the exact same fields, backed by the same database table (so everything else e.g. deletes on Parent would also immediately be "visible" on Child1), without Django wanting to make migrations for it.
But I don't know if it's allowed.

How to Filter in DRF Serializer using a Self Referencing Recursive Field

Using Python 3.x and the Django Rest Framework. I have a serializer with a Recursive Field (on self) which works as expected. However, I need a way to initially filter the nested children it returns by active = True.
I've tried different ways to filter children by active=True, but I'm unable to get this working on the nested children that are returned in the serializer.
Here is what I have.
class MenuListSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='menu_detail')
children = RecursiveField(many=True, required=False)
class RecursiveField(serializers.Serializer):
"""
Self-referential field for MPTT.
"""
def to_representation(self, value):
serializer = self.parent.parent.__class__(value, context=self.context)
return serializer.data
This is what I have tried but get the error ListSerializer' object has no attribute 'queryset' However, I'm not even sure this would work.
class MenuListSerializer(serializers.ModelSerializer):
def __init__(self, *args, request_user=None, **kwargs):
# try and filter active in chrildrend before query set is passed
super(MenuListSerializer, self).__init__(*args, **kwargs)
# print(self.fields['children'].parent)
self.fields['children'].queryset = self.fields['children'].queryset.filter(active=True)
url = serializers.HyperlinkedIdentityField(view_name='menu_detail')
children = RecursiveField(many=True, required=False)
If I understand well, your are trying to serialize Menu objects in a hierarchical way.
To do that, I guess you serialize recursively your top level Menu objects, don't you? (or else you will get all Menu objects at the top level).
To be able to filter active children only, I would suggest to create a active_children property on your model:
class Menu(MPTTModel, TimeStampedModel):
name = models.CharField(max_length=100)
active = models.BooleanField(default=1)
parent = TreeForeignKey('self', null=True, blank=True, related_name='children')
#property
def active_children(self):
return self.children.filter(active=True)
Then you can use that as a source for your children field in you serializer:
class MenuListSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='menu_detail')
children = RecursiveField(many=True, required=False, source='active_children')
Now you should only have active children when serializing.
Note that you should also filter top level objects in your queryset as the filtering above only works for the children in Menu objects.
There is a more dynamic solution for this issue. When you send the many=True kwarg to the RecursiveField (Serializer), it uses the ListSerializer with the same args and kwargs (with some limitations) for getting the objects and then uses the RecursiveField for all children. In this flow the ListSerializer is the default listing serializer, you can change it by the Meta of the RecursiveField. (you can see in the code)
The ordering will be applied in the to_representation method of the ListSerializer, we have to provide the ordering value, and the only way to send the ordering value is by sending it to RecursiveField. Kwargs are sent to ListSerializer in the __new__ method so, we can pop the ordering value in __init__, thus RecursiveField will not raise an unexpected kwarg error.
The ListSerializer kwargs are limited with constants in the rest_framework.serializers.LIST_SERIALIZER_KWARGS, we have to add ordering kwarg there too, in order to work with ordering value in the ListSerializer. Then we can order the data without any scenario specific code.
import rest_framework
rest_framework.serializers.LIST_SERIALIZER_KWARGS += ('ordering',)
class RecursiveListField(serializers.ListSerializer):
def __init__(self, *args, **kwargs):
self.ordering = kwargs.pop('ordering', None)
super(RecursiveListField, self).__init__(*args, **kwargs)
def to_representation(self, data):
data = self.ordering and data.order_by(*self.ordering) or data
return super(RecursiveListField, self).to_representation(data)
class RecursiveField(serializers.Serializer):
def __init__(self, *args, **kwargs):
kwargs.pop('ordering', None)
super(RecursiveField, self).__init__(*args, **kwargs)
def to_representation(self, value):
serializer = self.parent.parent.__class__(value, context=self.context)
return serializer.data
class Meta:
list_serializer_class = RecursiveListField
You can use the recursive field like this, anywhere you want:
class SomeSerializer(serializers.ModelSerializer):
children = RecursiveField(many=True, ordering=('id'))

DRF: Simple foreign key assignment with nested serializers?

With Django REST Framework, a standard ModelSerializer will allow ForeignKey model relationships to be assigned or changed by POSTing an ID as an Integer.
What's the simplest way to get this behavior out of a nested serializer?
Note, I am only talking about assigning existing database objects, not nested creation.
I have hacked away around this in the past with additional 'id' fields in the serializer and with custom create and update methods, but this is such a seemingly simple and frequent issue for me that I'm curious to know the best way.
class Child(models.Model):
name = CharField(max_length=20)
class Parent(models.Model):
name = CharField(max_length=20)
phone_number = models.ForeignKey(PhoneNumber)
child = models.ForeignKey(Child)
class ChildSerializer(ModelSerializer):
class Meta:
model = Child
class ParentSerializer(ModelSerializer):
# phone_number relation is automatic and will accept ID integers
children = ChildSerializer() # this one will not
class Meta:
model = Parent
Updated on July 05 2020
This post is getting more attention and it indicates more people have a similar situation. So I decided to add a generic way to handle this problem. This generic way is best suitable for you if you have more serializers that need to change to this format
Since DRF doesn't provide this functionality out of the box, we need to create a serializer field first.
from rest_framework import serializers
class RelatedFieldAlternative(serializers.PrimaryKeyRelatedField):
def __init__(self, **kwargs):
self.serializer = kwargs.pop('serializer', None)
if self.serializer is not None and not issubclass(self.serializer, serializers.Serializer):
raise TypeError('"serializer" is not a valid serializer class')
super().__init__(**kwargs)
def use_pk_only_optimization(self):
return False if self.serializer else True
def to_representation(self, instance):
if self.serializer:
return self.serializer(instance, context=self.context).data
return super().to_representation(instance)
I am not well impressed with this class name, RelatedFieldAlternative, you can use anything you want.
Then use this new serializer field in your parent serializer as,
class ParentSerializer(ModelSerializer):
child = RelatedFieldAlternative(queryset=Child.objects.all(), serializer=ChildSerializer)
class Meta:
model = Parent
fields = '__all__'
Original Post
Using two different fields would be ok (as #Kevin Brown and #joslarson mentioned), but I think it's not perfect (to me). Because getting data from one key (child) and sending data to another key (child_id) might be a little bit ambiguous for front-end developers. (no offense at all)
So, what I suggest here is, override the to_representation() method of ParentSerializer will do the job.
def to_representation(self, instance):
response = super().to_representation(instance)
response['child'] = ChildSerializer(instance.child).data
return response
Complete representation of Serializer
class ChildSerializer(ModelSerializer):
class Meta:
model = Child
fields = '__all__'
class ParentSerializer(ModelSerializer):
class Meta:
model = Parent
fields = '__all__'
def to_representation(self, instance):
response = super().to_representation(instance)
response['child'] = ChildSerializer(instance.child).data
return response
Advantage of this method?
By using this method, we don't need two separate fields for creation and reading. Here both creation and reading can be done by using child key.
Sample payload to create parent instance
{
"name": "TestPOSTMAN_name",
"phone_number": 1,
"child": 1
}
Screenshot
The best solution here is to use two different fields: one for reading and the other for writing. Without doing some heavy lifting, it is difficult to get what you are looking for in a single field.
The read-only field would be your nested serializer (ChildSerializer in this case) and it will allow you to get the same nested representation that you are expecting. Most people define this as just child, because they already have their front-end written by this point and changing it would cause problems.
The write-only field would be a PrimaryKeyRelatedField, which is what you would typically use for assigning objects based on their primary key. This does not have to be write-only, especially if you are trying to go for symmetry between what is received and what is sent, but it sounds like that might suit you best. This field should have a source set to the foreign key field (child in this example) so it assigns it properly on creation and updating.
This has been brought up on the discussion group a few times, and I think this is still the best solution. Thanks to Sven Maurer for pointing it out.
Here's an example of what Kevin's answer is talking about, if you want to take that approach and use 2 separate fields.
In your models.py...
class Child(models.Model):
name = CharField(max_length=20)
class Parent(models.Model):
name = CharField(max_length=20)
phone_number = models.ForeignKey(PhoneNumber)
child = models.ForeignKey(Child)
then serializers.py...
class ChildSerializer(ModelSerializer):
class Meta:
model = Child
class ParentSerializer(ModelSerializer):
# if child is required
child = ChildSerializer(read_only=True)
# if child is a required field and you want write to child properties through parent
# child = ChildSerializer(required=False)
# otherwise the following should work (untested)
# child = ChildSerializer()
child_id = serializers.PrimaryKeyRelatedField(
queryset=Child.objects.all(), source='child', write_only=True)
class Meta:
model = Parent
Setting source=child lets child_id act as child would by default had it not be overridden (our desired behavior). write_only=True makes child_id available to write to, but keeps it from showing up in the response since the id already shows up in the ChildSerializer.
There is a way to substitute a field on create/update operation:
class ChildSerializer(ModelSerializer):
class Meta:
model = Child
class ParentSerializer(ModelSerializer):
child = ChildSerializer()
# called on create/update operations
def to_internal_value(self, data):
self.fields['child'] = serializers.PrimaryKeyRelatedField(
queryset=Child.objects.all())
return super(ParentSerializer, self).to_internal_value(data)
class Meta:
model = Parent
A few people here have placed a way to keep one field but still be able to get the details when retrieving the object and create it with only the ID. I made a little more generic implementation if people are interested:
First off the tests:
from rest_framework.relations import PrimaryKeyRelatedField
from django.test import TestCase
from .serializers import ModelRepresentationPrimaryKeyRelatedField, ProductSerializer
from .factories import SomethingElseFactory
from .models import SomethingElse
class TestModelRepresentationPrimaryKeyRelatedField(TestCase):
def setUp(self):
self.serializer = ModelRepresentationPrimaryKeyRelatedField(
model_serializer_class=SomethingElseSerializer,
queryset=SomethingElse.objects.all(),
)
def test_inherits_from_primary_key_related_field(self):
assert issubclass(ModelRepresentationPrimaryKeyRelatedField, PrimaryKeyRelatedField)
def test_use_pk_only_optimization_returns_false(self):
self.assertFalse(self.serializer.use_pk_only_optimization())
def test_to_representation_returns_serialized_object(self):
obj = SomethingElseFactory()
ret = self.serializer.to_representation(obj)
self.assertEqual(ret, SomethingElseSerializer(instance=obj).data)
Then the class itself:
from rest_framework.relations import PrimaryKeyRelatedField
class ModelRepresentationPrimaryKeyRelatedField(PrimaryKeyRelatedField):
def __init__(self, **kwargs):
self.model_serializer_class = kwargs.pop('model_serializer_class')
super().__init__(**kwargs)
def use_pk_only_optimization(self):
return False
def to_representation(self, value):
return self.model_serializer_class(instance=value).data
The usage is like so, if you have a serializer somewhere:
class YourSerializer(ModelSerializer):
something_else = ModelRepresentationPrimaryKeyRelatedField(queryset=SomethingElse.objects.all(), model_serializer_class=SomethingElseSerializer)
This will allow you to create an object with a foreign key still only with the PK, but will return the full serialized nested model when retrieving the object you created (or whenever really).
There is a package for that! Check out PresentablePrimaryKeyRelatedField in Drf Extra Fields package.
https://github.com/Hipo/drf-extra-fields
I think the approach outlined by Kevin probably would be the best solution, but I couldn't ever get it to work. DRF kept throwing errors when I had both a nested serializer and a primary key field set. Removing one or the other would function, but obviously didn't give me the result I needed. The best I could come up with is creating two different serializers for reading and writing, Like so...
serializers.py:
class ChildSerializer(serializers.ModelSerializer):
class Meta:
model = Child
class ParentSerializer(serializers.ModelSerializer):
class Meta:
abstract = True
model = Parent
fields = ('id', 'child', 'foo', 'bar', 'etc')
class ParentReadSerializer(ParentSerializer):
child = ChildSerializer()
views.py
class ParentViewSet(viewsets.ModelViewSet):
serializer_class = ParentSerializer
queryset = Parent.objects.all()
def get_serializer_class(self):
if self.request.method == 'GET':
return ParentReadSerializer
else:
return self.serializer_class
Here's how I've solved this problem.
serializers.py
class ChildSerializer(ModelSerializer):
def to_internal_value(self, data):
if data.get('id'):
return get_object_or_404(Child.objects.all(), pk=data.get('id'))
return super(ChildSerializer, self).to_internal_value(data)
You'll just pass your nested child serializer just as you get it from the serializer ie child as a json/dictionary. in to_internal_value we instantiate the child object if it has a valid ID so that DRF can further work with the object.
I started by implementing something similar to JPG's solution before I found this answer, and noticed that it breaks the built-in Django Rest Framework's templates. Now, that isn't such a big deal (as their solution works wonderfully via requests/postman/AJAX/curl/etc.), but if someone's new (like me) and wants the built-in DRF form to help them along the way, here's my solution (after cleaning it up and integrating some of JPG's ideas):
class NestedKeyField(serializers.PrimaryKeyRelatedField):
def __init__(self, **kwargs):
self.serializer = kwargs.pop('serializer', None)
if self.serializer is not None and not issubclass(self.serializer, serializers.Serializer):
raise TypeError('You need to pass a instance of serialzers.Serializer or atleast something that inherits from it.')
super().__init__(**kwargs)
def use_pk_only_optimization(self):
return not self.serializer
def to_representation(self, value):
if self.serializer:
return dict(self.serializer(value, context=self.context).data)
else:
return super().to_representation(value)
def get_choices(self, cutoff=None):
queryset = self.get_queryset()
if queryset is None:
return {}
if cutoff is not None:
queryset = queryset[:cutoff]
return OrderedDict([
(
self.to_representation(item)['id'] if self.serializer else self.to_representation(item), # If you end up using another column-name for your primary key, you'll have to change this extraction-key here so it maps the select-element properly.
self.display_value(item)
)
for item in queryset
])
and an example below,
Child Serializer class:
class ChildSerializer(serializers.ModelSerializer):
class Meta:
model = ChildModel
fields = '__all__'
Parent Serializer Class:
class ParentSerializer(serializers.ModelSerializer):
same_field_name_as_model_foreign_key = NestedKeyField(queryset=ChildModel.objects.all(), serializer=ChildSerializer)
class Meta:
model = ParentModel
fields = '__all__'
Based on the answers of both JPG and Bono, I came up with a solution that handles the OpenAPI Schema generator of DRF as well.
The actual field class is:
from rest_framework import serializers
class ModelRepresentationPrimaryKeyRelatedField(serializers.PrimaryKeyRelatedField):
def __init__(self, **kwargs):
self.response_serializer_class = kwargs.pop('response_serializer_class', None)
if self.response_serializer_class is not None \
and not issubclass(self.response_serializer_class, serializers.Serializer):
raise TypeError('"serializer" is not a valid serializer class')
super(ModelRepresentationPrimaryKeyRelatedField, self).__init__(**kwargs)
def use_pk_only_optimization(self):
return False if self.response_serializer_class else True
def to_representation(self, instance):
if self.response_serializer_class is not None:
return self.response_serializer_class(instance, context=self.context).data
return super(ModelRepresentationPrimaryKeyRelatedField, self).to_representation(instance)
The extended AutoSchema class is:
import inspect
from rest_framework.schemas.openapi import AutoSchema
from .fields import ModelRepresentationPrimaryKeyRelatedField
class CustomSchema(AutoSchema):
def _map_field(self, field):
if isinstance(field, ModelRepresentationPrimaryKeyRelatedField) \
and hasattr(field, 'response_serializer_class'):
frame = inspect.currentframe().f_back
while frame is not None:
method_name = frame.f_code.co_name
if method_name == '_get_request_body':
break
elif method_name == '_get_responses':
field = field.response_serializer_class()
return super(CustomSchema, self)._map_field(field)
frame = frame.f_back
return super(CustomSchema, self)._map_field(field)
Then on your Dganjo's project settings you can define this new Schema class to be used globally like:
REST_FRAMEWORK = {
'DEFAULT_SCHEMA_CLASS': '<path_to_custom_schema>.CustomSchema',
}
Lastly from within your models you can use the new field type like:
class ExampleSerializer(serializers.ModelSerializer):
test_field = ModelRepresentationPrimaryKeyRelatedField(queryset=Test.objects.all(), response_serializer_class=TestListSerializer)
I have been also stuck in the same situation. But what i have done that i have created two serializers for the following models as follow:
class Base_Location(models.Model):
Base_Location_id = models.AutoField(primary_key = True)
Base_Location_Name = models.CharField(max_length=50, db_column="Base_Location_Name")
class Location(models.Model):
Location_id = models.AutoField(primary_key = True)
Location_Name = models.CharField(max_length=50, db_column="Location_Name")
Base_Location_id = models.ForeignKey(Base_Location, db_column="Base_Location_id", related_name="Location_Base_Location", on_delete=models.CASCADE)
This is my parent serializer
class BaseLocationSerializer(serializers.ModelSerializer):
class Meta:
model = Base_Location
fields = "__all__"
I'm using this serializer only for get request so in response i got data with foreign key also because of nested serializer
class LocationSerializerList(serializers.ModelSerializer): <-- using for get request
Base_Location_id = BaseLocationSerializer()
class Meta:
model = Location
fields = "__all__"
Screenshot of get method request and response in postman
I'm using this serializer only for post request so while sending post request i do not need to include any additional information rather than primary key field value
class LocationSerializerInsert(serializers.ModelSerializer): <-- using for post request
class Meta:
model = Location
fields = "__all__"
Screenshot of post method request and response in postman
Here's what I'm using all over. This may be the simplest, most straight forward method which needs no hacks etc, and is directly using DRF without jumping thru hoops. Happy to hear disagreements with this approach.
In the view's perform_create (or equivalent), fetch the FK model database object corresponding to the field sent in the POST request, and then send that into the Serializer. The field in the POST request can be anything that can be used to filter and locate the DB object, need not be an ID.
This is documented here: https://www.django-rest-framework.org/api-guide/generic-views/#genericapiview
These hooks are particularly useful for setting attributes that are
implicit in the request, but are not part of the request data. For
instance, you might set an attribute on the object based on the
request user, or based on a URL keyword argument.
def perform_create(self, serializer):
serializer.save(user=self.request.user)
This method also has the advantage of maintaining parity between the read and write side, by not sending a nested representation for child in the response to the GET or POST.
Given the example posted by the OP:
class Child(models.Model):
name = CharField(max_length=20)
class Parent(models.Model):
name = CharField(max_length=20)
phone_number = models.ForeignKey(PhoneNumber)
child = models.ForeignKey(Child)
class ChildSerializer(ModelSerializer):
class Meta:
model = Child
class ParentSerializer(ModelSerializer):
# Note this is different from the OP's example. This will send the
# child name in the response
child = serializers.ReadOnlyField(source='child.name')
class Meta:
model = Parent
fields = ('name', 'phone_number', 'child')
In the View's perform_create:
class SomethingView(generics.ListCreateAPIView):
serializer_class = ParentSerializer
def perform_create(self, serializer):
child_name = self.request.data.get('child_name', None)
child_obj = get_object_or_404(Child.objects, name=child_name)
serializer.save(child=child_obj)
PS: Please note that I've not tested this above snippet, however its based on a pattern I'm using in many places so it should work as is.

Categories