Search code examples
pythondjangotastypie

Django TastyPie Patch to a Many-to-Many


I'm trying to use TastyPie Patch to a many-to-many, but I get this error:

"error_message": "Tastypie requires a Python-style path () to lazy load related resources. Only given 'SchemeResource'.",

Why?

The patch I'm making:

/participant/84
POST: {"email":"[email protected]",  "schemes":{"id":"12", "schemes"}}

Resource:

class ParticipantResource(ModelResource):

    schemes = fields.ToManyField('SchemeResource', attribute='schemes', full=True, null=True)

    class Meta:
        queryset = Participant.objects.all()
        resource_name = 'participant'
        allowed_methods = ['post', 'get', 'put', 'patch']

2nd Resource:

class SchemeResource(ModelResource):

    user = fields.ToOneField(UserResource, 'user', full=True)
    link = fields.ToOneField(SchemeLinkResource, 'link', full=True)

    class Meta:
        queryset = Scheme.objects.all()
        resource_name = 'scheme'

Model:

class Participant(models.Model):

    email = models.EmailField(unique=True)
    mobile = PhoneNumberField(null=True, blank=True)
    date_joined = models.DateTimeField(_('date joined'), default=timezone.now)

    schemes = models.ManyToManyField(Scheme)

Solution

  • You must use brackets such as

    [] 
    

    around your schemes items (even if singular) when posting to a m2m field.

    Request would then look like :

    {"email":"[email protected]",  "schemes":[{"id":"12", "schemes"}]}
    

    When you want to know what a request should look like, make a GET request on url/of/api/modelresource/schema/

    If I recall correctly (and although you wrote "POST" in your request), PATCH request must have

    {"objects": [...]}
    

    enclosing the body.

    EDIT :

    Here's an example of what works for me :

    Resources :

    class VATCertificateResource(ModelResource):
        class Meta:
            queryset = VATCertificate.objects.all()
            resource_name = 'vatcertificate'
            authorization = Authorization()
    
    class InterventionResource(ModelResource):
    
        vatcertificates = fields.ToManyField('core.api.VATCertificateResource', 'vatcertificates',
                                         related_name='intervention', null=True, blank=True, full=True)
    

    Models :

    class VATCertificate(Document):
        intervention = models.ForeignKey(Intervention, related_name='vatcertificates', blank=True, null=True)
    
    class Intervention(models.Model):
        pass
    

    Hope this helps,

    Regards,