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.
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
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.
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.
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.
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 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.
> 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.
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.
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).
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.
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.
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.
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.
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)
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.
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.
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....
* 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.