Skip to content

Commit

Permalink
Merge branch 'release/v1.10.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
paulloz committed Oct 8, 2014
2 parents 1e2ee1f + b1bf7db commit eca6375
Show file tree
Hide file tree
Showing 53 changed files with 1,722 additions and 490 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ test:
mv lib/neo4j/data/graph.db lib/neo4j/data/graph.db.backup || true
# Start a brand new database
make startdb
./manage.py syncdb -v 0 --noinput --traceback --pythonpath=. --settings=app.settings_tests
-python manage.py syncdb -v 0 --noinput --traceback --pythonpath=. --settings=app.settings_tests
# Launch test with coverage
-python -W ignore::DeprecationWarning manage.py test $(TEST) --pythonpath=. --settings=app.settings_tests --traceback
# Stop database in order to restore it
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
[License](https://github.com/jplusplus/detective.io/blob/master/LICENSE)
[Test coverage](https://coveralls.io/r/jplusplus/detective.io)
[Documentation](http://docs.detective.io/en/latest/)
*Version 1.9.0 Baboon*
*Version 1.10.0 Caribou*

## Installation

Expand Down
24 changes: 23 additions & 1 deletion app/detective/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from app.detective.models import QuoteRequest
from app.detective.models import Topic
from app.detective.models import TopicSkeleton
from app.detective.models import TopicDataSet
from app.detective.models import TopicToken
from app.detective.models import SearchTerm
from app.detective.models import Article
Expand Down Expand Up @@ -76,7 +77,7 @@ def formfield_for_choice_field(self, db_field, request, **kwargs):
model_name = getattr(model._meta, "verbose_name").title()
subset = []
# Retreive every relationship field for this model
for field in utils.get_model_fields(model):
for field in utils.iterate_model_fields(model):
if field["type"] != 'AutoField':
choice = [ field["name"], field["verbose_name"].title(), ]
# Add ... at the end ot the relationship field
Expand Down Expand Up @@ -180,6 +181,27 @@ class TopicSkeletonAdmin(admin.ModelAdmin):

admin.site.register(TopicSkeleton, TopicSkeletonAdmin)

class TopicDataSetForm(forms.ModelForm):
target_plans = forms.MultipleChoiceField(choices=PLANS_CHOICES)

def __init__(self, *args, **kwargs):
super(TopicDataSetForm, self).__init__(*args, **kwargs)
instance = kwargs.get('instance', None)
if instance:
self.initial['target_plans'] = instance.selected_plans()

class TopicDataSetAdmin(admin.ModelAdmin):
form = TopicDataSetForm
list_display = ("title", "description_stripped", "_plans", "_skeletons")

def _skeletons(self, instance):
return ', '.join(instance.selected_skeletons())

def _plans(self, instance):
return ', '.join(instance.selected_plans())

admin.site.register(TopicDataSet, TopicDataSetAdmin)

class ArticleAdmin(admin.ModelAdmin):
save_on_top = True
prepopulated_fields = {'slug': ('title',)}
Expand Down
51 changes: 39 additions & 12 deletions app/detective/individual.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
# -*- coding: utf-8 -*-
from app.detective import register, graph
from app.detective.neomatch import Neomatch
from app.detective.utils import import_class, to_underscores, get_model_topic, get_leafs_and_edges, get_topic_from_request, get_model_fields
from app.detective.utils import get_model_fields as utils_get_model_fields
from app.detective.utils import import_class, to_underscores, get_model_topic, get_leafs_and_edges, get_topic_from_request, iterate_model_fields, topic_cache
from app.detective.topics.common.models import FieldSource
from app.detective.topics.common.user import UserResource
from app.detective.models import Topic
from django.conf.urls import url
from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.core.paginator import Paginator, InvalidPage
from django.core.urlresolvers import reverse
Expand Down Expand Up @@ -83,9 +84,6 @@ def delete_detail(self, object_list, bundle):

def delete_list(self, object_list, bundle):
return False
# if not self.check_contribution_permission(object_list, bundle, 'delete'):
# raise Unauthorized("Sorry, only staff or contributors can delete resource.")
# return True

class IndividualMeta:
list_allowed_methods = ['get', 'post', 'put']
Expand Down Expand Up @@ -134,6 +132,7 @@ def prepend_urls(self):
url(r"^(?P<resource_name>%s)/search%s$" % params, self.wrap_view('get_search'), name="api_get_search"),
url(r"^(?P<resource_name>%s)/mine%s$" % params, self.wrap_view('get_mine'), name="api_get_mine"),
url(r"^(?P<resource_name>%s)/(?P<pk>\w[\w/-]*)/patch%s$" % params, self.wrap_view('get_patch'), name="api_get_patch"),
url(r"^(?P<resource_name>%s)/(?P<pk>\w[\w/-]*)/authors%s$" % params, self.wrap_view('get_authors'), name="api_get_authors"),
url(r"^(?P<resource_name>%s)/bulk_upload%s$" % params, self.wrap_view('bulk_upload'), name="api_bulk_upload"),
url(r"^(?P<resource_name>%s)/(?P<pk>\w[\w/-]*)/graph%s$" % params, self.wrap_view('get_graph'), name="api_get_graph"),
url(r"^(?P<resource_name>%s)/(?P<pk>\w[\w/-]*)/relationships%s$" % params, self.wrap_view('get_relationships'), name="api_get_relationships"),
Expand Down Expand Up @@ -300,6 +299,8 @@ def obj_create(self, bundle, **kwargs):
# Create an object to build the bundle
obj = node.properties
obj["id"] = node.id
# update the cache
topic_cache.incr_version(request.current_topic)
# Return a new bundle
return self.build_bundle(obj=model._neo4j_instance(node), data=obj, request=request)

Expand Down Expand Up @@ -334,13 +335,12 @@ def alter_detail_data_to_serialize(self, request, bundle, nested=False):
# If the nested parameter is True, this set
node_to_retreive = set()
# Resolve relationships manualy
model_fields = get_model_fields(model)
for field in fields:
# Get relationships for this fields
field_rels = [ rel for rel in node_rels[:] if rel.type == field._type]
# Filter relationships to keep only the well oriented relationships
# get the related field informations
related_field = [f for f in model_fields if "rel_type" in f and f["rel_type"] == field._type and "name" in f and f["name"] == field._BoundRelationship__attname]
related_field = [f for f in iterate_model_fields(model) if "rel_type" in f and f["rel_type"] == field._type and "name" in f and f["name"] == field._BoundRelationship__attname]
if related_field:
# Note (edouard): check some assertions in case I forgot something
assert len(related_field) == 1, related_field
Expand Down Expand Up @@ -584,10 +584,6 @@ def get_patch(self, request, **kwargs):
bundle = self.build_bundle(request=request)
# User allowed to update this model
self.authorized_update_detail(self.get_object_list(bundle.request), bundle)
# Current model
model = self.get_model()
# Fields
fields = { x['name'] : x for x in utils_get_model_fields(model) }
# Get the node's data using the rest API
try: node = connection.nodes.get(pk)
# Node not found
Expand Down Expand Up @@ -678,6 +674,10 @@ def get_patch(self, request, **kwargs):
# We simply update the node property
# (the value is already validated)
else:
# Current model
model = self.get_model()
# Fields
fields = { x['name'] : x for x in iterate_model_fields(model) }
if field_name in fields:
if 'is_rich' in fields[field_name]['rules'] and fields[field_name]['rules']['is_rich']:
data[field_name] = field_value = bleach.clean(field_value,
Expand All @@ -688,10 +688,37 @@ def get_patch(self, request, **kwargs):
'a': ("href", "target")
})
node.set(field_name, field_value)

# update the cache
topic_cache.incr_version(request.current_topic)
# And returns cleaned data
return self.create_response(request, data)


def get_authors(self, request, **kwargs):
pk = kwargs["pk"]
# This should be a POST request
self.method_check(request, allowed=['get'])
self.throttle_check(request)
# User must be authentication
self.is_authenticated(request)
bundle = self.build_bundle(request=request)
# User allowed to update this model
self.authorized_read_detail(self.get_object_list(bundle.request), bundle)
# Get the node's data using the rest API
try: node = connection.nodes.get(pk)
# Node not found
except client.NotFoundError: raise Http404("Not found.")
# Get the authors ids
authors_ids = node.properties.get("_author", [])
# Find them in the database
authors = User.objects.filter(id__in=authors_ids).select_related("profile")
resource = UserResource()
# Create a bundle with each resources
bundles = [resource.build_bundle(obj=a, request=request) for a in authors]
data = [resource.full_dehydrate(bundle) for bundle in bundles]
# We ask for relationship properties
return resource.create_response(request, data)

def get_relationships(self, request, **kwargs):
# Extract node id from given node uri
def node_id(uri) : return re.search(r'(\d+)$', uri).group(1)
Expand Down
3 changes: 1 addition & 2 deletions app/detective/management/commands/orphans.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ def handle(self, *args, **options):
try:
for Model in topic.get_models():
try:
fields = utils.get_model_fields(Model)
for field in fields:
for field in utils.iterate_model_fields(Model):
if field["rel_type"] and field["direction"] == "out" and "through" in field["rules"]:
ids= []
for entity in Model.objects.all():
Expand Down
Loading

0 comments on commit eca6375

Please sign in to comment.