from modeltree.query import ModelTreeQuerySet
from avocado.meta.formatters import registry

try:
    from collections import OrderedDict
except ImportError:
    from ordereddict import OrderedDict

class BaseExporter(object):
    "Base class for all exporters"

    preferred_formats = []

    def __init__(self, queryset, concepts):
        if not isinstance(queryset, ModelTreeQuerySet):
            queryset = queryset._clone(klass=ModelTreeQuerySet)

        self.queryset = queryset
        self.concepts = concepts

    def _get_raw_query(self, fields):
        return self.queryset.select(*fields, inclue_pk=False)

    def _read_row(self, row, params):
        for i, (keys, length, formatter) in enumerate(params):
            part, row = row[:length], row[length:]
            values = OrderedDict(zip(keys, part))
            yield formatter(values, self.preferred_formats)

    def _get_keys(self, fields):
        return [f.field_name for f in fields]

    def read(self, concepts=None):
        concepts = concepts or self.concepts
        params = []
        select_fields = []

        for concept in concepts:
            cfields = concept.conceptfields.select_related('field')
            fields = [c.field for c in cfields]
            select_fields.extend(f.field for f in fields)
            formatter = registry[concept.formatter](cfields)
            params.append((self._get_keys(fields), len(cfields), formatter))

        for row in iter(self._get_raw_query(select_fields)):
            yield self._read_row(row, params)

    def write(self, *args, **kwargs):
        raise NotImplemented

@@ -525,32 +525,27 @@
   def _get_r
-aw_query
+ows
 (self, field
@@ -620,20 +620,22 @@
    def _
-read
+format
 _row(sel
@@ -921,45 +921,521 @@
     
-return %5Bf.field_name for f in fields%5D
+# Best case scenario, no conflicts, return as is. Otherwise%0A        # duplicates found will be suffixed with a '_N' where N is the%0A        # occurred position.%0A        keys = %5Bf.field_name for f in fields%5D%0A%0A        if len(set(keys)) != len(fields):%0A            cnts = %7B%7D%0A            for i, key in enumerate(keys):%0A                if keys.count(key) %3E 1:%0A                    cnts.setdefault(key, 0)%0A                    keys%5Bi%5D = '%7B%7D_%7B%7D'.format(key, cnts%5Bkey%5D)%0A                    cnts%5Bkey%5D += 1%0A        return keys
 %0A%0A  
@@ -1945,16 +1945,11 @@
 et_r
-aw_query
+ows
 (sel
@@ -1986,20 +1986,22 @@
 d self._
-read
+format
 _row(row

Add better parser for non-conflicting keys Fix #10, clean up internal API