Monday, February 27, 2017

Re: Flattening model relationships (in APIs)

I'm not sure you want to read my answer, really...  I've finally stopped using DRF and wrote own library which is focused on resources, linking and representations.
I think you can do some customization in DRF, probably you ca declare custom serializer class, but this is a hard way, IMO.

I like simple things, so with my lib I can just do something like that:

payments = api.resource('/payments/')
customer = api.resource('/customers/:pk')


@payments.representation
def payment_as_json(payment, ctx):
    return {
        'customer_address': payment.customer.address,
        'customer_url': ctx.link_to(customer, pk=payment.customer_id), # link resources
        'value': payment.value,  # write here
        'and_so_on': True,  # what do you want
    }

Yes, it does not validate automatically and this example is not restful, but you may follow semantic structures like jsonld without any limitation, and apply validation in a controller:

@payments.post(accept='application/json')
def add_payment(ctx):
    form = PaymentForm(data=ctx.body)
    form.is_valid() and form.save(0
    [...]

Where PaymentForm may be a typical Django Form or ModelForm, or even a Colander Schema. 
There is more code to write, but implementation is more explitic.

PEP20: Explicit is better than implicit. Simple is better than complex. Flat is better than nested. Readability counts.  And so on...

BR,
Marcin



On Monday, February 27, 2017 at 2:52:46 PM UTC+1, Ankush Thakur wrote:
Marcin, that's exactly where I'm stuck! I know endpoints should never be 1:1 serialization of models, but I just don't know how to do that. I mean, I've been able to create endpoints like "/customers/1/payments/" where I use model relationships to generate JSON structures where Customer contains a Payments array field. My Address endpoint seems to be an oddity, as API consumers don't expect the city to contain state and the state to contain country as a JSON structure. How can I add these to the top-level Address entity directly while serialization? That's where I have no answers. Would it be possible for you to point me towards some article that does that? Thanks in advance!

Regards,
Ankush

On Monday, February 27, 2017 at 3:41:49 AM UTC+5:30, marcin....@gmail.com wrote:


On Tuesday, February 21, 2017 at 8:13:25 PM UTC+1, Ankush Thakur wrote:
If the relationship chain was even deeper, there would be even more nesting, which I feel isn't great for API consumers. What is the best practice here to put state and country at the same level as the city? 

Just follow REST design. 
Forget django models, think about encapsulation.
Think about representation of a resource, not about serializing a model(s).
Make semantic representations, as good as possible.

You are not forced to do any nested nasty things. This has nothing to do with REST api.
You may feel that DRF is limiting you. You'll be on a good path, if so. :)

Good luck!
Marcin

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/a0b23023-8a5c-4257-ad6d-d72639f85925%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

No comments:

Post a Comment