<commit_before>from extdirect.django.store import ExtDirectStore

class ExtDirectCRUD(object):
    
    model = None
    
    #CREATE
    def pre_create(self, request):
        return request.extdirect_post_data[0]        
        
    def post_create(self, obj):
        pass
    
    def _single_create(self, data):
        #id='ext-record-#'
        data.pop("id")

        #convert: u'key' --> 'key'
        values = dict(map(lambda x: (str(x[0]), x[1]), data.items()))

        c = self.model(**values)
        c.save(force_insert=True)
        
        self.post_create(c)
        
        return c.id
    
    def create(self, request):
        extdirect_data = self.pre_create(request)
        ids = []
        if isinstance(extdirect_data, list):
            for data in extdirect_data:
                id = self._single_create(data)
                ids.append(id)
        else:
            id = self._single_create(extdirect_data)
            ids.append(id)
            
            
        ds = self.direct_store()        
        return ds.query(self.model.objects.filter(pk__in=ids))[ds.root]        
        
    #READ
    def pre_read(self, request):
        return request.extdirect_post_data[0]
    
    def direct_store(self):
        return ExtDirectStore(self.model)
        
    def read(self, request):
        extdirect_data = self.pre_read(request)
        return self.direct_store().query(**extdirect_data)
    
    #UPDATE
    def pre_update(self, request):
        return request.extdirect_post_data
        
    def post_update(self, ids):
        pass
    
    def post_single_update(self, obj):
        pass
    
    def _single_update(self, data):
        id = data.pop("id")
        obj = self.model.objects.get(pk=id)
        
        fields = data.keys()
        for field in obj._meta.fields:
            if field.name in fields:
                value = data.pop(field.name)
                obj.__setattr__(field.name, value)

        obj.save()
        
        self.post_single_update(obj)
    
    def update(self, request):
        extdirect_data = self.pre_update(request)
        
        ids = extdirect_data[0]
        records = extdirect_data[1]
        
        if isinstance(records, list):
            #batch update
            for data in records:
                self._single_update(data)
        
        elif isinstance(records, dict):
            #single update
            self._single_update(records)
        
        else:
            raise AttributeError, "Bad parameter"
        
        self.post_update(ids)
        ds = self.direct_store()
        if isinstance(ids, list):
            return ds.query(self.model.objects.filter(pk__in=ids))[ds.root]
        else:
            return ds.query(self.model.objects.filter(pk=ids))[ds.root]
    
    #DESTROY    
    def pre_destroy(self, request):
        return request.extdirect_post_data[0]
        
    def post_destroy(self, id):
        pass
    
    def destroy(self, request):
        id = self.pre_destroy(request)
        
        c = self.model.objects.get(pk=id)
        c.delete()
        
        self.post_destroy(id)
        
        return dict(success=True, message="Object deleted")<commit_msg>Refactoring of all CRUD actions, trying to get a more realistic implementation (still under development).<commit_after>from extdirect.django.store import ExtDirectStore
from django.forms.models import modelform_factory
from django.db import transaction
from django.core.serializers import serialize

ACTIONS = ('CREATE', 'READ', 'UPDATE', 'DESTROY')

class BaseExtDirectCRUD(object):
    """
    Base class for CRUD actions.
    
    Implements all the methods that you may want to
    re-implement in your own class.
    """
    model = None
    form = None    
    
    def __init__(self):
        self.store = self.direct_store()
        
        if not self.form:
            self.form = modelform_factory(self.model)
    
    def direct_store(self):
        return ExtDirectStore(self.model)
    
    def extract_data(self, request, action):
        if action not in ACTIONS:
            raise AttributeError, "action must be one of: %s" % str(ACTIONS)
        
        if action in ('CREATE', 'READ', 'DESTROY'):
            return request.extdirect_post_data[0]
        
        else:
            return request.extdirect_post_data
    
    def pre_create(self, data):
        return True, ""
        
    def post_create(self, ids):
        pass
    
    def post_single_create(self, obj):
        pass

    def _single_create(self, data):
        #id='ext-record-#'
        data.pop("id")        
            
        c = None
        form = self.form(data=data)
        if form.is_valid():
            c = form.save()                
            self.post_single_create(c)
            return c.id        
        else:
            return 0
        
    def pre_read(self, data):
        return True, ""

    def pre_update(self, data):
        return True, ""
        
    def post_update(self, ids):
        pass
    
    def post_single_update(self, obj):
        pass
    
    def _single_update(self, data):
        id = data.pop("id")
        obj = self.model.objects.get(pk=id)        
    
        all_fields = serialize('python', [obj])[0]['fields']
        all_fields.update(data)

        form = self.form(all_fields, instance=obj)
        if form.is_valid():
            obj = form.save()        
            self.post_single_update(obj)
            return obj.id
        else:
            return 0

    def pre_destroy(self, data):
        return True, ""
        
    def post_destroy(self, id):
        pass
    
    def failure(self, msg):
        return {self.store.success: False, self.store.root: [], self.store.total: 0, 'message': msg}
            
class ExtDirectCRUD(BaseExtDirectCRUD):
    """
    ExtDirectCRUD main class.
    
    Implements the main CRUD actions.
    
    You shouldn't re-implement these methods, see 
    BaseExtDirectCRUD if you need custom behavior.
    """
    
    #CREATE            
    @transaction.commit_manually
    def create(self, request):
        extdirect_data = self.extract_data(request, 'CREATE')
        
        ok, msg = self.pre_create(extdirect_data)
        if not ok:
            return self.failure(msg)
                    
        ids = []
        success = True
        sid = transaction.savepoint()
        
        if isinstance(extdirect_data, list):
            for data in extdirect_data:
                id = self._single_create(data)
                if id:
                    ids.append(id)
                else:            
                    success = False
                    break
        else:
            id = self._single_create(extdirect_data)
            if id:
                ids.append(id)
            else:
                success = False
            
        if success:
            transaction.commit()    
            self.post_create(ids)
            res = self.store.query(self.model.objects.filter(pk__in=ids))            
            res['message'] = 'Records created'
            return res
        else:
            transaction.savepoint_rollback(sid)
            return self.failure("There was an error while trying to save some of the records.")
        
    #READ        
    def read(self, request):
        extdirect_data = self.extract_data(request, 'READ')
        ok, msg = self.pre_read(extdirect_data)
        if ok:           
            return self.store.query(**extdirect_data)
        else:
            return self.failure(msg)
    
    #UPDATE    
    @transaction.commit_manually
    def update(self, request):
        extdirect_data = self.extract_data(request, 'UPDATE')
        
        ok, msg = self.pre_update(extdirect_data)
        if not ok:
            return self.failure(msg)
        
        ids = []
        success = True
        records = extdirect_data[1]
        sid = transaction.savepoint()
        
        if isinstance(records, list):
            #batch update
            for data in records:
                id = self._single_update(data)
                if id:
                    ids.append(id)
                else:
                    success = False
                    break

        else:
            #single update
            id = self._single_update(records)
            if id:
                ids.append(id)
            else:
                success = False

        if success:
            transaction.commit()    
            self.post_update(ids)
            res = self.store.query(self.model.objects.filter(pk__in=ids))
            res['message'] = "Records updated"
            return res
        else:
            transaction.savepoint_rollback(sid)
            return self.failure("There was an error while trying to save some of the records.")
    
    #DESTROY        
    def destroy(self, request):
        ids = self.extract_data(request, 'DESTROY')
        
        ok, msg = self.pre_destroy(ids)
        if not ok:
            return self.failure(msg)
        
        if isinstance(ids, list):
            cs = self.model.objects.filter(pk__in=ids)
        else:            
            cs = [self.model.objects.get(pk=ids)]
        
        for c in cs:
            i = c.id
            c.delete()        
            self.post_destroy(i)
        
        return {self.store.success:True, 'message':"Objects deleted"}
    
{'fraction_non_alphanumeric': 0.09217225286380992, 'fraction_numerical': 0.0013788714467543488, 'mean_word_length': 1.5539003250270855, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 4, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5182816', 'n_tokens_mistral': 2671, 'n_tokens_neox': 2623, 'n_words': 599}