Question: **Hello!**

With help of Yii GII I generated a controller+view:

*/Controllers/XmlWorkerController.php + /views/XmlWorker/index.php.*

There is a simplest code in /views/XmlWorker/index.php:

```
<?
echo 'Hello, world';

```

There is also a file index2.php, just after the standart index.php, in the same directory.

In some reason it is necessary to call in browser: `http://localhost/index2.php` and see just
'Hello, world!". No standard Yii header/footer at all.

There is some code in my index2.php:

```
$yii=dirname(__FILE__).'/yii/framework/yii.php';
$config=dirname(__FILE__).'/protected/config/main.php';

defined('YII_DEBUG') or define('YII_DEBUG',true);
defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL',3);

require_once($yii);
Yii::createWebApplication($config);
list($controller) = Yii::app()->createController('XmlWorker');
$controller->actionIndex();

```

But as a result I see "Hello, world!" between Yii standart header/footer. It is necessary to see this sentence in a clear white browser window.

**How can I arrive such goal?**

P.S. *Of course, task is simplified. What is the real reason to do it?
Lets say, I have two clients. First client wants to call index2.php (without any parameters) and gets some information in XML format. Second client wants to call index3.php (without any parameters) and gets some other information in HTML format. So, it is necessary to provide two different entrance points for them.*

Answer: 
Example for using DRF-extensions caching with all GET params as key hash on ReadOnlyModelViewSet.

Define your key constructor (key hash):

```
from rest_framework_extensions.key_constructor.constructors import DefaultKeyConstructor
from rest_framework_extensions.key_constructor.bits import QueryParamsKeyBit

class QueryParamsKeyConstructor(DefaultKeyConstructor):
    all_query_params = QueryParamsKeyBit('*')  # Don't change, * is default on drf-extension dev version only

```

And your view:

```
class UserViewSet(ListCacheResponseMixin, viewsets.ReadOnlyModelViewSet):
    serializer_class = UserSerializer
    list_cache_key_func = QueryParamsKeyConstructor()

```

set DRF-extensions and django caching settings in settings.py, for example:

```
CACHES = {
    "default": {
        "BACKEND": "redis_cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/0"
    }
}

REST_FRAMEWORK_EXTENSIONS = {
'DEFAULT_CACHE_RESPONSE_TIMEOUT': 20

```

}
> 
> What I would like to do is add a parameter force\_refresh to the /user/:id/products API call
> 
> 
> 

I don't think it's a good idea. What if your client made `/pay` request and then used his own routing to `/user/:id/products` ? With `force_refresh` attribute you are adding state for request and it is not idempotent anymore.

If you have high read rate and low write rate I would suggest you to look at creation of [custom key bit](http://chibisov.github.io/drf-extensions/docs/#custom-key-bit) with global cached invalidation, based on post save signals.

If you want to make cache invalidation more specific I would suggest you to denormalize your User model. For example:

```
class User(UserBaseModel):
    ...
    products_updated_date = models.DateTimeField()

```

You should update `products_updated_date` every time you make payments:

```
class UserViewSet(CacheResponseMixin, ReadOnlyModelViewSet):
    ...
    @action('pay')
    def pay(self):
        ...
        self.request.user.products_updated_date = now()
        self.request.user.save()
        ...

```

And finally you should create custom key bit with users's `products_updated_date` field usage:

```
from rest_framework_extensions.key_constructor.bits import (
    KeyBitBase
)

class UserProductsUpdatedKeyBit(KeyBitBase):
    def get_data(self, **kwargs):
        request = kwargs['request']
        if (hasattr(request, 'user') and 
            request.user and 
            request.user.is_authenticated()):
            return request.user.products_updated_date

```

You can add `UserProductsUpdatedKeyBit` to your key constructor class for `/user/:id/products` routing.