Hacker News new | past | comments | ask | show | jobs | submit login
Django REST framework 3.5 (django-rest-framework.org)
243 points by cdnsteve on Oct 20, 2016 | hide | past | favorite | 66 comments



I like DRF, but I think its allow-by-default mentality is a security risk. If you use it, keep in mind that:

* ModelViewSet is read/write, you should use the more verbose ReadOnlyModelViewSet until you know you want to allow writing.

* Fields specified in the "fields" member are read/write by default. You have to explicitly declare the field on the ViewSet and pass "readonly=true" to make it read-only. This is especially dangerous for ForeignKey fields, which can be used to change object ownership if you aren't careful.

When I was responsible for a DRF-based API I wrote some custom Fields and ViewSets to use safer defaults, and I recommend others do the same.


If you want to get even more granular, I would suggest using the mixins. I almost never use the broad viewsets anymore.

Example:

  class FooViewset(  
          mixins.CreateModelMixin,  
          mixins.ListModelMixin,  
          mixins.DestroyModelMixin,  
          mixins.RetrieveModelMixin,  
          viewsets.GenericViewSet)
Subtract as necessary.


This is a good way to control what methods are allowed on the ViewSet, but still doesn't address the problem of fields being writable by default when the ViewSet allows writing.


This seems like the expected behavior. If allowing for writing didn't actually allow you to write anything, that would be pretty strange, wouldn't it? Or do I misunderstand?


You may want to expose some fields that you don't allow changing, such as what account owns the resource. When fields are writable by default, it is easy for someone to miss that they've made a field writable when they just meant to expose it for reading.


I think it's better to define field specific read/write permissions through the serializers. In the serializer's Meta class, you can define a readonly_fields tuple containing the string names of the read only fields


You can also route only read-only methods in urls.py, for example via:

    url(
        r'path/$',
        TheModelViewSetView.as_view({"get": "list"}),
        name="thename"
    )
or "retrieve" instead of "list" for a route which includes PK.

This of course makes the entire path read-only so it's not a way to make some fields writable and others not.


yeah, I think they're saying instead of having the Meta fields list create writable fields by default, it should be read-only by default, after which you could add a "writable_fields" list


> I like DRF, but I think its allow-by-default mentality is a security risk.

Completely agree. But DRF is useful even if you don't use any of the serializers. E.g. you can just use it to handle auth, requests, and responses, and then validate things by hand and save them directly to the Django model. You still pretty much need serializers when validating image files because you can't trigger the Django code to do this by saving to the model directly, but for everything else it's often more readable just to serialize and deserialize by hand.


One metric that I'll measure a framework by is the likelihood of finding an answer to a query that is not articulated in the concepts and terms used by the framework. This is especially useful when starting out.

DRF scores well here. It's designed in an intuitive way. The healthy community around it is a big plus as well. Can't count the number of times I've come across a SO article that had updated answers for the latest versions.

I only wish there was a way to make one time donations. Currently you have to sign up for a recurring plan.


> One metric that I'll measure a framework by is the likelihood of finding an answer to a query that is not articulated in the concepts and terms used by the framework.

It's also important to measure the likelihood to have to find an answer in the first place. There are vibrant communities around many frameworks, but it doesn't make them all good.

Speaking as someone who went from DRF -> Rails -> back to DRF, I can say that DRF is sufficiently confusing to understand and get started with. The problem partially exists within Django itself, but DRF doesn't exactly help. It can feel like pulling teeth to create a simple API with DRF. And, as the another HN comment explains, DRF does a ton of "opt-in" work that can end up doing more than you intended.

My biggest gripe with DRF is how coupled it is to the Django ORM. All of the nice ViewSets are only useful if you have cookie-cutter Django models, but we all end up changing them.

I tend to enjoy working with Ruby Grape APIs:

https://github.com/ruby-grape/grape#basic-usage

No need to deal with 100 types of ViewSets, Serializers, Renderers, Parsers, and so on. You just need to understand that data is being passed back and forth. If you need something more complicated, just add it yourself.

I wish Python had something similar. Something that's between Django & Flask in terms of complexity.



Falcon maybe?



Other than requiring MongoDB, I really liked Eves approach.


When I started flirting with Ruby and Rails for building a web app backed by a JSON API, DRF is what convinced me to stick with Django. It has a ridiculous amount of built-in functionality, but without making it hard to customize your API. If you haven't used DRF, you really owe it to yourself to give it a try.

I can't wait to see support for real-time views. Is that in the cards for DRF 3.6?


I think that for API building pyramid is the way to go - it has a lot of built in goodies to support api building + there are things like cornice by mozilla or pyramid_swagger.


drf and ruby on rails are apples to oranges. you should probably compare django and rails.

drf is usually compared to sinatra.


If you're looking at Django alone, Rails has more functionality for building APIs. DRF is the package that makes Django on par with (in my opinion, better than) Rails.

I see Sinatra as more similar to Flask than DRF.


I use Django + DRF along with Ember, and love the combination.

All the new schema generation functionality is interesting. It's probably just a matter of time before someone builds a tool that reads the schema generated by Django, and syncs the Ember models with it. That's currently one of the drawbacks of using separate frameworks (and languages) for the client and server.


I'm using that stack for two fairly large projects and loving it... I use the ember-django-adapter to translate data on the client side (previously had used drf json-api).. so far it's not too much hassle to build the ember models as needed but I see what you're saying..


Why did you switch away from DRF JSON API? We used it for one project, then realized how much of a hassle it was to get nested representations of data (last time I checked, it didn't just work out of the box). But going back and changing to Ember Django Adapter is a lot of work, since we have some custom AJAX calls.

For a new project where we were starting from scratch, we stuck with Ember Django Adapter.


I always miss DJRF when using languages other than Python


This. I've recently been working with a large project using Node. I find myself constantly thinking about how I'd build it if I were using DRF.


> This. I've recently been working with a large project using Node. I find myself constantly thinking about how I'd build it if I were using DRF.

You wouldn't need to think about promises or callbacks at first place, which would make things way easier. That's the main reason I gave up NodeJS for Go when working with APIs. Async programming is noise. CSP is a better paradigm.


Scala, Akka, and Play say hi!


Don't you still need Futures for async stuff in order to not block the thread, or is each request handled by a lightweight 'fiber' (erlang process/goroutine)?


That's correct, blocking operations within an actor need to be wrapped in a Future[1]. But Akka itself can be extremely performant if the bulk of your processing is non-blocking. Any non-blocking or long-running operations should be executed in a separate thread pool (if there are many), or just a separate thread.

[1]: http://doc.akka.io/docs/akka/2.4/general/actor-systems.html#...


isnt DRF built into rails basically (never used rails)


Last time I checked, in Rails there's no Controller class that has all the built-in functionality of a DRF ViewSet. For example, you still have to perform the DB queries for every action yourself, rather than just define a queryset and serializer for the entire class and let the framework handle the rest (no pun intended).


i was under the impression that you can add :json to your controllers and they return "serialized" data.


Someone please correct me if I'm wrong, but my understanding is in Rails you still need to define every action in the controller. With DRF, you just inherit from a ModelViewSet, declare the queryset and serializer on the class (or have methods return them if you need custom behavior), and you're good to go. It makes prototyping so much easier, and adding filters and permissions is very straightforward.


You are correct.

Maybe the DRF for Ruby is grape https://github.com/ruby-grape/grape/blob/master/README.md but I never used it. I just fill in the standard scaffolded REST methods in the controllers with queries and write json views (Rails and Django have different terms and concepts, MVC vs MVT.)


I can only say nice things about Django REST framework, super simple to use and comes with lot of extras. Very interesting the shift towards schemas and RAML; I am quite curious to see how usable that is.


For people who are unfamiliar, there is also Tastypie.

I find it's Model centric approach a whole lot nicer to work with then Django-Rest .


Having tried both, I found DRF far more consistent with Django (making it a lot easier to work with as a result). ModelSerializers are similar to ModelForms and the class based views are almost the same.


Strongly disagree. DRF can be used in a model centric way, has much easier to read source and drastically better documentation. The community is much more developed as well.


Did not use Tastypie since a couple years ago and I remember it being very hard to use due to be so heavily coupled to Django models. I find DRF support for Django ORM and yet the ease of use when not doing ORM stuff one the main selling points.


Ditto with everyone else. Tastypie is unpleasant to build upon, except for the simple examples of their tutorial, and has rightfully been subsumed by DRF.


Which is basically stupid by itself, as you simply expose your internal data structures without control or thought.


I'm guessing you haven't tried it. TastyPie gives you complete control and customization for all parts of your api.


care to explain?


Data structures used internally for processing are something totally different than data structures used for communication with outside world. Usually you don't want to expose internals with public API, and even when you do, you want to be very selective about what is shown and how.

When you publish internals, you only cement your implementation so you can't change that easily later (e.g. when you realize how crappy it was at first), and you even need to pay for that drawback with ease of use of your API (API's user would need to understand the system he talks with). It's a lose-lose deal.


I agree, I find doing this with DRF very easy and had the opposite with TastyPie doing stuff I did not want or need. Having some ORM integration is nice; there are a number of situations where it's easy to use your ORM safely and get stuff done very quickly (eg. basic CRUD stuff for instance)


"Basic CRUD" is basic only in most trivial situations, which by themselves are rare. Much more often you need to create a set of related objects. With this "basic CRUD" you have many points where network can break, and network programming has one very important principle: network always breaks, so the program has to survive in such case.


Anyone been using the new(ish) schema generation features? Sounds useful to be able to generate client libraries from the API spec (e.g. DRF => swagger => JS library), but I haven't felt compelled to do so. Any other use-cases that are paying dividends?


I was thinking about using it to auto-generate documentation, but I found writing some ad-hoc tooling turned out to be more straightforward and flexible.


Yeah, I've been using django-rest-swagger for docs, which has sufficed. Newer versions of that package use the schema-gen stuff from DRF.

(A slight annoyance I've found here: the CoreAPI schema spec doesn't seem to have a place to attach a top-level summary of the API, which is useful as a 'man page' for the rest of the API calls. Swagger does allow for that.)


DRF is super nice to work with. It can be a bit slow when you start piling on the serializers and such but dev time wise it gives you a significant boost in productivity.


If you avoid nested serializers it isn't bad performance wise.


there's a meetup in SF on DRF on wednesday (10/24/16), if you're interested in learning more about DRF. https://www.meetup.com/The-San-Francisco-Django-Meetup-Group...


DRF with django its deadly combination.


I have a question about http://www.django-rest-framework.org/tutorial/2-requests-and...

Is it a good practice to handle all verbs in the function dealing with the particular request as shown in the example?

I think for a real world scenario that would be a mess to read, but for a less experienced developer this could hint that such approach is alright and result in a less readable code base in the future.


If you proceed with the tutorial it is going to show you what I consider is the cleanest way to go for views in django rest framework (ViewSets, coupled with the routers, part 6 of the tutorial).

Basically, you will 1. split verbs to different methods of one class and 2. you can not implement verbs you are not going to allow (you can of course do that also with the functional style you see in the link you posted)


Having maintained a DRF-based API before, +1 to using ViewSets.


The intro tutorial tends to show you the low-level/more-code-but-infinitely-customizable way a thing really works, and then once you understand that, introduce the convenient abstractions on top of it that make common cases simpler/less code. So keep reading :)


For a typical setup, you can just use the built in Routers. It's a much cleaner way to handle all the verbs. You can always override functions if you need it to do something special.

http://www.django-rest-framework.org/api-guide/routers/


There’s no need for a framework since you can do:

values = User.objects.all().values('id', 'username')

results = json.dumps(values)

…or use the builtin JSON serializer. You can also use Paginator to paginate the results.


Why use a website - just have your users call you and ask you to do things.


Assuming you don't want to transform data, provide your own custom serializers, provide pluggable auth modules and authentication methods, CRUD viewsets, accepting and receiving multiple response types, then yeah.


That's a small chunk of the functionality most APIs need. Why write all of your API views from scratch when there's an excellent framework that handles it for you?


Your comment is being downvoted because DRF clearly does a whole lot more than just serialising the response dictionary or adding pagination, you should really have a look at the documentation.

However, I still think that Django should have something like the "JSONResponse mixin example"[1] built-in by default; sometimes you are building a product which is not an API but you still need the occasional RESTful endpoint and, in those cases, something like DRF would be overkill.

[1] https://docs.djangoproject.com/en/1.10/topics/class-based-vi...


You could always import DRF's serializers and parsers/generators without committing to the entire framework.

Django does plan on bringing DRF's content negotiation into the main framework:

https://www.djangoproject.com/weblog/2015/dec/11/django-awar...


Thanks, that would be a reasonably light-weight alternative.


I just stopped from the js community to the Python one cause of js fatigue and the first thing I learned is Django restful APIs and now this happens....


Now what happens? A well documented and almost entirely backwards compatible release of one of Django's leading 3rd party additions?




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: