Preparing a request body without headers throws a TypeError

I have a usecase where I need to generate the body of a `PreparedRequest` without anything else known about the request. If I run `PreparedRequest.prepare_body` without any headers, it fails, citing the headers are `None`. It seems like `prepare_body` is attempting to set the `Content-Length` header. It likely shouldn't, if there are no headers. One possible solution is to create the `headers` object as needed. It would also probably work to skip this step when headers aren't present, and then when `prepare_headers` is called, analyze the `body` to insert a content length, using `prepare_content_length`. 

## Expected Result

I should be able to generate the body of a request on its own, without preparing headers. 

## Actual Result

When running the below snippet, I get
```
$ python3 main.py
Traceback (most recent call last):
  File "main.py", line 5, in <module>
    req.prepare_body(data="hello world!", files=None)
  File "/Users/nkrichevsky/.local/lib/python3.6/site-packages/requests/models.py", line 514, in prepare_body
    self.prepare_content_length(body)
  File "/Users/nkrichevsky/.local/lib/python3.6/site-packages/requests/models.py", line 529, in prepare_content_length
    self.headers['Content-Length'] = builtin_str(length)
TypeError: 'NoneType' object does not support item assignment
```

I can work around this by doing `req.prepare_headers(None)` before preparing the body, but this isn't documented as being required in the API reference.

## Reproduction Steps

```python
import requests

if __name__ == "__main__":
    req = requests.PreparedRequest()
    req.prepare_body(data="hello world!", files=None)
    print(req.body)
```

## System Information

    $ python -m requests.help

```
{
  "chardet": {
    "version": "3.0.4"
  },
  "cryptography": {
    "version": ""
  },
  "idna": {
    "version": "2.9"
  },
  "implementation": {
    "name": "CPython",
    "version": "3.6.5"
  },
  "platform": {
    "release": "19.5.0",
    "system": "Darwin"
  },
  "pyOpenSSL": {
    "openssl_version": "",
    "version": null
  },
  "requests": {
    "version": "2.24.0"
  },
  "system_ssl": {
    "version": "1010107f"
  },
  "urllib3": {
    "version": "1.25.9"
  },
  "using_pyopenssl": false
}

```


Hi @ollien,

We typically try to keep usage questions to StackOverflow. We have a whole [section in the docs](https://requests.readthedocs.io/en/master/user/advanced/#prepared-requests) covering how to use PreparedRequests and the basic flow for making modifications to the body/headers. That has the info you need to make the changes you're attempting.

As for the prepare_* methods. These are technically available to the end user, but they have expectations that you've already constructed a reasonable request. When you start partially instantiating objects there are a number of edge cases that start to crop up. I don't think we have an intention to add edge case handling for any possible mocking situation right now.

Is there any intent to have those expectations documented? I'm not really intending to ask a question with this issue; it's more that the the public API has undocumented behavior that I found surprising. In fact, the docs say you can construct `PreparedRequest`s manually, but makes no mention of the order in which those methods must be called.

The page you linked mentions how to use `PreparedRequest`s, but it doesn't mention the `PreparedRequest.prepare_*`.

Right, you're expected to create a `Request` and then call `prepare` on that to get your own PreparedRequest. You really shouldn't be creating `PreparedRequests`. I always objected to it being exposed but nothing's private in Python and even if we tried to use a "private" module in Python, folks would use it.

>  You really shouldn't be creating PreparedRequests

Gotcha. The [API docs for it](https://requests.readthedocs.io/en/master/api/#requests.PreparedRequest) say manual creation is allowed, so if that's not the case, the docs should reflect that, IMO.

That's a fair point. I'm sure Nate or Seth would merge a PR if you removed that language

Yep, I think that's completely reasonable. Partial initialization has a number of failure points so we shouldn't be recommending it. 

Done :) Thanks so much for working through this with me