[Mayan EDMS: 1604] Advanced modding - Adding 'current user' to DocumentMetadata model's Save method

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

[Mayan EDMS: 1604] Advanced modding - Adding 'current user' to DocumentMetadata model's Save method

MacRobb Simpson
This one's a tricky one, and I hope someone has some ideas:

I'm trying to rig up a 'metadata changed' event. I got it to work!
...At least, everything except for accessing via the API(directly via the app works).

The problem is that I can't figure out how to get access to the current user within the scope of class DocumentMetadata, function Save(). (this is in apps/metadata/models.py)

Here's my traceback:

(...)
  File "/Data/Projects/mayan/local/lib/python2.7/site-packages/mayan/apps/metadata/api_views.py", line 206, in put
    return super(APIDocumentMetadataView, self).put(user=self.request.user,*args,**kwargs)
  File "/Data/Projects/mayan/local/lib/python2.7/site-packages/rest_framework/generics.py", line 289, in put
    return self.update(request, *args, **kwargs)
  File "/Data/Projects/mayan/local/lib/python2.7/site-packages/rest_framework/mixins.py", line 70, in update
    self.perform_update(serializer)
  File "/Data/Projects/mayan/local/lib/python2.7/site-packages/rest_framework/mixins.py", line 74, in perform_update
    serializer.save()
  File "/Data/Projects/mayan/local/lib/python2.7/site-packages/rest_framework/serializers.py", line 186, in save
    self.instance = self.update(self.instance, validated_data)
  File "/Data/Projects/mayan/local/lib/python2.7/site-packages/rest_framework/serializers.py", line 880, in update
    instance.save()
  File "/Data/Projects/mayan/local/lib/python2.7/site-packages/mayan/apps/metadata/models.py", line 181, in save
    traceback.print_stack(file=sys.stdout)

I can access request.user on line 206 in api_views.py, but then it goes through several calls in the rest_framework library.
I just can't figure out how to pass that variable through to where I need it, in models.py, not without modifying the rest_framework library(which would mean having to keep a special copy of this around).

Any thoughts?

-Rob

--

---
You received this message because you are subscribed to the Google Groups "Mayan EDMS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

[Mayan EDMS: 1635] Re: Advanced modding - Adding 'current user' to DocumentMetadata model's Save method

rosarior
Administrator
I'm not sure if this is what you need but to have the user for some event commits, the optional _user parameter is passed to some overrided save methods.

Example: https://gitlab.com/mayan-edms/mayan-edms/blob/master/mayan/apps/documents/models.py#L222

To pass the user from the API's request you can use the get_serializer_context() method from the API view: https://gitlab.com/mayan-edms/mayan-edms/blob/development/mayan/apps/documents/api_views.py#L220
This way you insert the views, the request's or the user's instance in the context of the serializer which does the actual interface with the model.
Finally override the serializer's save() and/or update() method to insert the user from the context that the API view provided: https://gitlab.com/mayan-edms/mayan-edms/blob/development/mayan/apps/documents/serializers.py#L288

I wouldn't recommend it but you can take a shortcut and just can call the model's save() method from the API view itself if you are in a tight deadline and then improve the implementation.

On Tuesday, April 18, 2017 at 5:24:33 PM UTC-4, MacRobb Simpson wrote:
This one's a tricky one, and I hope someone has some ideas:

I'm trying to rig up a 'metadata changed' event. I got it to work!
...At least, everything except for accessing via the API(directly via the app works).

The problem is that I can't figure out how to get access to the current user within the scope of class DocumentMetadata, function Save(). (this is in apps/metadata/models.py)

Here's my traceback:

(...)
  File "/Data/Projects/mayan/local/lib/python2.7/site-packages/mayan/apps/metadata/api_views.py", line 206, in put
    return super(APIDocumentMetadataView, self).put(user=self.request.user,*args,**kwargs)
  File "/Data/Projects/mayan/local/lib/python2.7/site-packages/rest_framework/generics.py", line 289, in put
    return self.update(request, *args, **kwargs)
  File "/Data/Projects/mayan/local/lib/python2.7/site-packages/rest_framework/mixins.py", line 70, in update
    self.perform_update(serializer)
  File "/Data/Projects/mayan/local/lib/python2.7/site-packages/rest_framework/mixins.py", line 74, in perform_update
    serializer.save()
  File "/Data/Projects/mayan/local/lib/python2.7/site-packages/rest_framework/serializers.py", line 186, in save
    self.instance = self.update(self.instance, validated_data)
  File "/Data/Projects/mayan/local/lib/python2.7/site-packages/rest_framework/serializers.py", line 880, in update
    instance.save()
  File "/Data/Projects/mayan/local/lib/python2.7/site-packages/mayan/apps/metadata/models.py", line 181, in save
    traceback.print_stack(file=sys.stdout)

I can access request.user on line 206 in api_views.py, but then it goes through several calls in the rest_framework library.
I just can't figure out how to pass that variable through to where I need it, in models.py, not without modifying the rest_framework library(which would mean having to keep a special copy of this around).

Any thoughts?

-Rob

--

---
You received this message because you are subscribed to the Google Groups "Mayan EDMS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

[Mayan EDMS: 1639] Re: Advanced modding - Adding 'current user' to DocumentMetadata model's Save method

MacRobb Simpson
I'm going to look into this, but what I ended up doing between posting this question and now is editing api_views.py's APIDocumentMetadataView class and change the 'put' function to:

def put(self, *args, **kwargs):
        """
        Edit the selected document metadata type and value.
        """
        try:
            partial = kwargs.pop('partial', False)
            instance = self.get_object()
            serializer = self.get_serializer(instance, data=self.request.data, partial=partial)
            serializer.is_valid(raise_exception=True)
            instance.user = self.request.user
            serializer.save()
            return Response(serializer.data)
        except Exception as exception:
            return Response(
                status=status.HTTP_400_BAD_REQUEST, data={
                    'non_fields_errors': unicode(exception)
                }
            )

This gave me a user variable available in class DocumentMetadata to use in the save method:
    def save(self, *args, **kwargs):
        if self.metadata_type.pk not in self.document.document_type.metadata.values_list('metadata_type', flat=True):
            raise ValidationError(
                _('Metadata type is not valid for this document type.')
            )

        #compare metadata values; if different, log the change
       
        valueList = self.document.metadata.filter(id=self.id).values()
        if len(valueList) > 0:
            old_metadata_value = valueList[0]['value']
            if old_metadata_value != self.value:
                event_metadata_properties_edit.commit(
                    actor=self.user,
                    target=self._document_cache,
                    description='Changed value from "'+str(old_metadata_value or '')+'" to "'+str(self.value or '')+'"',
                    action_object=self._metadata_type_cache
                )
           
        return super(DocumentMetadata, self).save(*args, **kwargs)

This is what I've used internally for my implementation.
I'm still getting up to speed on the whole 'django-mvc-layers-on-layers' thing; This is my first project using python in a web environment, using classes in python, and very near to my first time implementing classes myself... so forgive me if things aren't 'good enough' or 'pythonic enough' code wise.

--

---
You received this message because you are subscribed to the Google Groups "Mayan EDMS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.