Created
March 18, 2014 00:35
-
-
Save PirosB3/9611350 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from bisect import bisect | |
from django.utils import six | |
from django.db.models import signals | |
from django.db import models | |
from django.db.models.manager import * | |
from django.db.models.fields import FieldDoesNotExist | |
from django.apps import apps | |
from pymongo import MongoClient | |
class MongoQuerySet(object): | |
def __init__(self, model=None, query=None, using=None, hints=None): | |
self.model = model | |
self.using = using | |
self.table = self.model._meta.db_table | |
def count(self): | |
return self.using[self.table].count() | |
class MongoManager(Manager): | |
client = MongoClient()['ducks'] | |
def get_queryset(self): | |
return MongoQuerySet(self.model, using=self.client) | |
class DuckOptions(object): | |
@property | |
def fields(self): | |
return [f for f in self.local_fields] | |
@property | |
def concrete_fields(self): | |
return [f for f in self.fields if f.column is not None] | |
def get_field_by_name(self, name): | |
for f, model in self.get_fields_with_model(): | |
if name in [f.name, f.attname]: | |
f, model, True, False | |
def get_concrete_fields_with_model(self): | |
return [(f, None) for f in self.concrete_fields] | |
def get_fields_with_model(self): | |
return [(f, None) for f in self.local_fields] | |
def get_field(self, name, m2m=True): | |
to_search = self.local_fields | |
for f in to_search: | |
if f.name == name: | |
return f | |
raise FieldDoesNotExist('%s has no field named %r' % (self.object_name, name)) | |
def setup_pk(self, field): | |
if not self.pk and field.primary_key: | |
self.pk = field | |
field.serialize = False | |
def add_field(self, field): | |
self.local_fields.insert(bisect(self.local_fields, field), field) | |
self.setup_pk(field) | |
def _prepare(self, model): | |
auto = models.AutoField(verbose_name='ID', primary_key=True, | |
auto_created=True) | |
model.add_to_class('id', auto) | |
if not self.db_table: | |
self.db_table = "%s_%s" % (self.app_label, self.model_name) | |
db_table = None | |
concrete_managers = [] | |
local_fields = [] | |
abstract = False | |
app_label = "duck" | |
pk = None | |
ordering = [] | |
verbose_name_plural = "Ducks" | |
model_name = "ducks" | |
swapped = False | |
has_auto_field = False | |
object_name = "duck" | |
apps = apps | |
# ModelBase | |
class DuckMeta(type): | |
def __new__(cls, name, bases, attrs): | |
cls._meta = DuckOptions() | |
for name, field in [('name', models.CharField(max_length=250)), | |
('objects', MongoManager()), | |
('age', models.PositiveIntegerField())]: | |
field.contribute_to_class(cls, name) | |
cls._meta._prepare(cls) | |
signals.class_prepared.send(sender=cls) | |
return cls | |
@classmethod | |
def add_to_class(cls, name, value): | |
if hasattr(value, 'contribute_to_class'): | |
value.contribute_to_class(cls, name) | |
else: | |
setattr(cls, name, value) | |
# Model | |
class DuckBase(six.with_metaclass(DuckMeta, object)): | |
pass | |
# MY MODEL! | |
class Duck(DuckBase): | |
pass |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment