Save only dirty fields
I can see how that code appears confusing. The `only` parameter accepts a list of fields, and `model_instance.dirty_fields` returns a list of fields that have been modified. Using the two together, you can accomplish "save only the fields that changed":

``` python
project.save(only=project.dirty_fields)
```
 Please let me know if this does not address your concern.
 Yes, It solves the problem. I just thought the presence of a composite primary key were not a good criteria to save all fields or just the dirt ones.
 Looking at d53415fb, I think that code is there to replace previous logic that popped the PK off the field dict when updating a model.

I don't use the `Model.save()` method in some of my models to avoid race conditions.

Actually I overwrite it for these specific models to have a default value to the `only` argument that makes sense.

Example:

```
In [1]: p1 = Project.get(id=21)

In [2]: Project.get(id=21).used_credit_count
Out[2]: 4669

In [3]: # Now, lets simulate another thread

In [4]: Project.update(used_credit_count=Project.used_credit_count + 1).where(Project.id == 21).execute()
Out[4]: 1L

In [5]: Project.get(id=21).used_credit_count
Out[5]: 4670

In [6]: p1.save()
Out[6]: 1L

In [7]: Project.get(id=21).used_credit_count
Out[7]: 4669
```

The release 2.2 introduced saving only dirty (modified) fields, what would be very useful in my application (and others, I hope). But when I took a look at the code, I noticed that the dirty fields only takes place when using CompositeKey:

``` python

    def save(self, force_insert=False, only=None):
        field_dict = dict(self._data)
        pk_field = self._meta.primary_key
        if only:
            field_dict = self._prune_fields(field_dict, only)
        if self._get_pk_value() is not None and not force_insert:

          # Here is #
           if not isinstance(pk_field, CompositeKey):
                field_dict.pop(pk_field.name, None)
            else:
                field_dict = self._prune_fields(field_dict, self.dirty_fields)
            rows = self.update(**field_dict).where(self._pk_expr()).execute()
        else:
            pk = self._get_pk_value()
            pk_from_cursor = self.insert(**field_dict).execute()
            if pk_from_cursor is not None:
                pk = pk_from_cursor
            self._set_pk_value(pk)  # Do not overwrite current ID with None.
            rows = 1
        self._dirty.clear()
        return rows

```

It seemed that its been used only to remove the fields that are part of the composite primary key, but IMHO its very useful on many scenarios.

Sorry if my English is not clear. Please don't hesitate to ask for clarifications.
