Skip to content

Commit

Permalink
Merge with original repo master
Browse files Browse the repository at this point in the history
  • Loading branch information
fbuccioni committed Jul 31, 2018
2 parents 0739a9b + b03d758 commit 4bd8adc
Show file tree
Hide file tree
Showing 15 changed files with 145 additions and 110 deletions.
12 changes: 9 additions & 3 deletions .travis.yml
Expand Up @@ -6,11 +6,17 @@ python:
- "3.5"
- "pypy"
env:
- DJANGO_VERSION=1.8.18
- DJANGO_VERSION=1.11.10
- DJANGO="Django>=1.11,<2.0"
- DJANGO="Django>=2.0,<2.2"
matrix:
exclude:
- python: "2.7"
env: DJANGO="Django>=2.0,<2.2"
- python: "pypy"
env: DJANGO="Django>=2.0,<2.2"
# command to install dependencies
install:
- pip install -r requirements.txt
- pip install -q Django==$DJANGO_VERSION
- pip install -q $DJANGO
# command to run tests
script: python setup.py -q nosetests
13 changes: 10 additions & 3 deletions README.rst
Expand Up @@ -8,10 +8,17 @@ Django-MongoEngine

THIS IS UNSTABLE PROJECT, IF YOU WANT TO USE IT - FIX WHAT YOU NEED

Right now we're targeting to get things working on Django 1.9
Right now we're targeting to get things working on Django 1.11;
2.0 support added, but not tested in production.

Working / Django 1.9
--------------------
WARNING:
--------
Maybe there is better option for mongo support, take a look at https://nesdis.github.io/djongo/;
It's python3 only and i have not tried it yet, but looks promising.


Working / Django 1.11
---------------------

* [ok] sessions
* [ok] models/fields, fields needs testing
Expand Down
8 changes: 6 additions & 2 deletions django_mongoengine/document.py
Expand Up @@ -38,7 +38,8 @@ class DjangoFlavor(object):
_get_pk_val = Model.__dict__["_get_pk_val"]

def __init__(self, *args, **kwargs):
self._state = ModelState(self._meta.get("db_alias", me.DEFAULT_CONNECTION_NAME))
self._state = ModelState()
self._state.db = self._meta.get("db_alias", me.DEFAULT_CONNECTION_NAME)
super(DjangoFlavor, self).__init__(*args, **kwargs)

def _get_unique_checks(self, exclude=None):
Expand All @@ -52,14 +53,17 @@ class Document(django_meta(mtc.TopLevelDocumentMetaclass,
DjangoFlavor, me.Document)):
swap_base = True


class DynamicDocument(django_meta(mtc.TopLevelDocumentMetaclass,
DjangoFlavor, me.DynamicDocument)):
swap_base = True


class EmbeddedDocument(django_meta(mtc.DocumentMetaclass,
DjangoFlavor, me.EmbeddedDocument)):
swap_base = True


class DynamicEmbeddedDocument(django_meta(mtc.DocumentMetaclass,
DjangoFlavor, me.DynamicEmbeddedDocument)):
DjangoFlavor, me.DynamicEmbeddedDocument)):
swap_base = True
3 changes: 3 additions & 0 deletions django_mongoengine/fields/__init__.py
Expand Up @@ -34,6 +34,9 @@ def patch_mongoengine_field(field_name):
for k in ["__eq__", "__lt__", "__hash__", "attname"]:
if k not in field.__dict__:
setattr(field, k, djangoflavor.DjangoField.__dict__[k])
# set auto_created False for check in django db model when delete
if field_name == "ObjectIdField":
setattr(field, "auto_created", False)


for f in ["StringField", "ObjectIdField"]:
Expand Down
2 changes: 2 additions & 0 deletions django_mongoengine/fields/djangoflavor.py
Expand Up @@ -28,6 +28,8 @@ def __init__(self, *args, **kwargs):
if "required" in kwargs:
raise ImproperlyConfigured("`required` option is not supported. Use Django-style `blank` instead.")
kwargs["required"] = not kwargs["blank"]
if hasattr(self, "auto_created"):
kwargs.pop("auto_created")
self.verbose_name = kwargs.pop("verbose_name", None)
super(DjangoField, self).__init__(*args, **kwargs)
self.remote_field = None
Expand Down
53 changes: 15 additions & 38 deletions django_mongoengine/mongo_admin/options.py
Expand Up @@ -3,7 +3,7 @@

from django import forms
from django.forms.formsets import all_valid
from django.core.urlresolvers import reverse
from django.urls import reverse
from django.contrib.admin.exceptions import DisallowedModelAdminToField
from django.contrib.admin import widgets, helpers
from django.contrib.admin.utils import (
Expand Down Expand Up @@ -54,15 +54,14 @@ def get_content_type_for_model(obj):
get_content_type_for_model=get_content_type_for_model,
)

class BaseDocumentAdmin(djmod.BaseModelAdmin):
class BaseDocumentAdmin(djmod.ModelAdmin):
"""Functionality common to both ModelAdmin and InlineAdmin."""
form = DocumentForm

def formfield_for_dbfield(self, db_field, **kwargs):
"""
Hook for specifying the form Field instance for a given database Field
instance.
If kwargs are given, they're passed to the form Field's constructor.
"""
request = kwargs.pop("request", None)
Expand Down Expand Up @@ -162,10 +161,11 @@ def __init__(self, model, admin_site):
self.model = model
self.opts = model._meta
self.admin_site = admin_site
super(DocumentAdmin, self).__init__()
super(DocumentAdmin, self).__init__(model, admin_site)
self.log = not settings.DATABASES.get('default', {}).get(
'ENGINE', 'django.db.backends.dummy'
).endswith('dummy')
self.change_list_template = 'admin/change_document_list.html'

# XXX: add inline init somewhere
def _get_inline_instances(self):
Expand Down Expand Up @@ -231,11 +231,17 @@ def get_changelist_formset(self, request, **kwargs):
fields=self.list_editable, **defaults
)

def get_changelist(self, request, **kwargs):
"""
Returns the ChangeList class for use on the changelist page.
"""
from django_mongoengine.mongo_admin.views import DocumentChangeList
return DocumentChangeList


def log_addition(self, request, object, message):
"""
Log that an object has been successfully added.
The default implementation creates an admin LogEntry object.
"""
if not self.log:
Expand All @@ -245,7 +251,6 @@ def log_addition(self, request, object, message):
def log_change(self, request, object, message):
"""
Log that an object has been successfully changed.
The default implementation creates an admin LogEntry object.
"""
if not self.log:
Expand All @@ -256,13 +261,16 @@ def log_deletion(self, request, object, object_repr):
"""
Log that an object will be deleted. Note that this method is called
before the deletion.
The default implementation creates an admin LogEntry object.
"""
if not self.log:
return
super(DocumentAdmin, self).log_deletion(request, object, object_repr)

@property
def media(self):
return djmod.ModelAdmin.media.fget(self)

@csrf_protect_m
def changeform_view(self, request, object_id=None, form_url='', extra_context=None):

Expand Down Expand Up @@ -471,41 +479,10 @@ def history_view(self, request, object_id, extra_context=None):
"admin/object_history.html"
], context)

def get_search_results(self, request, queryset, search_term):
"""
Returns a tuple containing a queryset to implement the search,
and a boolean indicating if the results may contain duplicates.
"""
# Apply keyword searches.
def construct_search(field_name):
if field_name.startswith('^'):
return "%s__istartswith" % field_name[1:]
elif field_name.startswith('='):
return "%s__iexact" % field_name[1:]
elif field_name.startswith('@'):
return "%s__search" % field_name[1:]
else:
return "%s__icontains" % field_name

use_distinct = False
search_fields = self.get_search_fields(request)
if search_fields and search_term:
orm_lookups = [construct_search(str(search_field))
for search_field in search_fields]
for bit in search_term.split():
or_queries = [Q(**{orm_lookup: bit})
for orm_lookup in orm_lookups]
queryset = queryset.filter(reduce(operator.or_, or_queries))

return queryset, use_distinct

media = djmod.ModelAdmin.media


class InlineDocumentAdmin(BaseDocumentAdmin):
"""
Options for inline editing of ``model`` instances.
Provide ``name`` to specify the attribute name of the ``ForeignKey`` from
``model`` to its parent. This is required if ``model`` has more than one
``ForeignKey`` to its parent.
Expand Down
51 changes: 29 additions & 22 deletions django_mongoengine/mongo_admin/views.py
Expand Up @@ -9,27 +9,26 @@
from django.utils.encoding import smart_str

from mongoengine import Q
from functools import reduce


class DocumentChangeList(ChangeList):
def __init__(self, request, model, list_display, list_display_links,
list_filter, date_hierarchy, search_fields, list_select_related,
list_per_page, list_max_show_all, list_editable, model_admin):
try:
super(DocumentChangeList, self).__init__(
request, model, list_display, list_display_links, list_filter,
date_hierarchy, search_fields, list_select_related,
list_per_page, list_max_show_all, list_editable, model_admin)
except TypeError:
self.list_max_show_all = list_max_show_all
# The init for django <= 1.3 takes one parameter less
super(DocumentChangeList, self).__init__(
request, model, list_display, list_display_links, list_filter,
date_hierarchy, search_fields, list_select_related,
list_per_page, list_editable, model_admin)
def __init__(self, *args, **kwargs):
super(DocumentChangeList, self).__init__(*args, **kwargs)
self.pk_attname = self.lookup_opts.pk_name

def get_results(self, request):
# query_set has been changed to queryset
try:
self.query_set
except:
self.query_set = self.queryset
# root_query_set has been changed to root_queryset
try:
self.root_query_set
except:
self.root_query_set = self.root_queryset

paginator = self.model_admin.get_paginator(request, self.query_set,
self.list_per_page)
# Get the number of objects, with admin filters applied.
Expand Down Expand Up @@ -84,7 +83,7 @@ def get_ordering(self, request=None, queryset=None):
ordering field.
"""
if queryset is None:
# with Django < 1.4 get_ordering works without fixes for mongoengine
# with Django < 1.4 get_ordering works without fixes for mongoengine
return super(DocumentChangeList, self).get_ordering()

params = self.params
Expand All @@ -106,9 +105,12 @@ def get_ordering(self, request=None, queryset=None):
continue # Invalid ordering specified, skip it.

# Add the given query's ordering fields, if any.
sign = lambda t: t[1] > 0 and '+' or '-'
qs_ordering = [sign(t) + t[0] for t in queryset._ordering]
ordering.extend(qs_ordering)
try:
sign = lambda t: t[1] > 0 and '+' or '-'
qs_ordering = [sign(t) + t[0] for t in queryset._ordering]
ordering.extend(qs_ordering)
except:
pass

# Ensure that the primary key is systematically present in the list of
# ordering fields so we can guarantee a deterministic order across all
Expand Down Expand Up @@ -152,7 +154,12 @@ def _lookup_param_1_3(self):
)
return lookup_params

def get_query_set(self, request=None):
def get_queryset(self, request=None):
# root_query_set has been changed to root_queryset
try:
self.root_query_set
except:
self.root_query_set = self.root_queryset
# First, we collect all the declared list filters.
qs = self.root_query_set.clone()

Expand All @@ -174,7 +181,7 @@ def get_query_set(self, request=None):
# string (i.e. those that haven't already been processed by the
# filters).
qs = qs.filter(**remaining_lookup_params)
# TODO: This should probably be mongoengine exceptions
# TODO: This should probably be mongoengine exceptions
except (SuspiciousOperation, ImproperlyConfigured):
# Allow certain types of errors to be re-raised as-is so that the
# caller can treat them in a special way.
Expand All @@ -184,7 +191,7 @@ def get_query_set(self, request=None):
# have any other way of validating lookup parameters. They might be
# invalid if the keyword arguments are incorrect, or if the values
# are not in the correct type, so we might get FieldError,
# ValueError, ValidationError, or ?.
# ValueError, ValidationError, or ?.
raise IncorrectLookupParameters(e)

# Set ordering.
Expand Down
25 changes: 21 additions & 4 deletions django_mongoengine/mongo_auth/models.py
Expand Up @@ -15,8 +15,24 @@

from django_mongoengine import document
from django_mongoengine import fields
from django_mongoengine.queryset import QuerySetManager
from .managers import MongoUserManager


def ct_init(self, *args, **kwargs):
super(QuerySetManager, self).__init__(*args, **kwargs)
self._cache = {}


ContentTypeManager = type(
"ContentTypeManager",
(QuerySetManager,),
dict(
ContentTypeManager.__dict__,
__init__=ct_init,
),
)

try:
from django.contrib.auth.hashers import check_password, make_password
except ImportError:
Expand Down Expand Up @@ -88,7 +104,7 @@ class SiteProfileNotAvailable(Exception):
pass


class PermissionManager(models.Manager):
class PermissionManager(QuerySetManager):
def get_by_natural_key(self, codename, app_label, model):
return self.get(
codename=codename,
Expand Down Expand Up @@ -134,9 +150,10 @@ class Meta:

def __unicode__(self):
return u"%s | %s | %s" % (
unicode(self.content_type.app_label),
unicode(self.content_type),
unicode(self.name))
self.content_type.app_label,
self.content_type,
self.name,
)

def natural_key(self):
return (self.codename,) + self.content_type.natural_key()
Expand Down
2 changes: 2 additions & 0 deletions django_mongoengine/views/edit.py
Expand Up @@ -20,6 +20,7 @@
# django 1.10
FormMixin = djmod.FormMixin


class WrapDocumentForm(WrapDocument, FormMixin):
pass

Expand All @@ -41,6 +42,7 @@ def get_success_url(self):
" a get_absolute_url method on the Model.")
return url


@copy_class(djmod.CreateView)
class CreateView(six.with_metaclass(
WrapDocumentForm,
Expand Down

0 comments on commit 4bd8adc

Please sign in to comment.