URL: / client /[client_id]/ log / operator
Method: POST
Data:
{
"access_token": "TOKEN",
"limit": 100,
"sort": "asc",
"start_date": "2018-01-01T00: 00: 00Z"
}
OR
{
"access_token": "TOKEN",
"limit": 100,
"sort": "asc",
"offset": "500"
}
Success Response:
{
"result": "ok",
"logs": [
{
"date": "2018-01-01T00: 00: 00Z",
"text": "Log entry"
},
...
]
}
Log entry in the format: "message. User: name the name of the operator."
I need to create a request to receive logs of operator activity. Which returns a formatted log of all user actions.
I have an activity application in which there is an OperatorLog model.
from django.db import models
from users.models import User
from .constants import ACTIVITY_ACTIONS
class OperatorLogManager(models.Manager):
"""Manager for operator logs"""
def active(self):
"""Mark object as active"""
return self.filter(is_delete=False)
def get_by_user_id(self, id):
return self.active().filter(pk=id)
def get_by_client_id(self, client_uid):
return self.active().filter(client_uid=client_uid)
class OperatorLog(models.Model):
"""Model for logs"""
user = models.ForeignKey(User, on_delete=models.CASCADE)
created = models.DateTimeField(auto_now_add=True)
is_deleted = models.BooleanField(default=False)
action_type = models.CharField(max_length=32,
сhoices=ACTIVITY_ACTIONS)
message = models.TextField(max_length=2048)
client_uid = models.CharField(max_length=50)
bitrix_id = models.PositiveIntegerField()
# Operator Manager
objects = OperatorLogManager()
def delete(self, **kwargs):
self.is_deleted = True
self.save()
You need a public api (activity / api.py) to register events in other applications,
There is also a file with a list of activity types (constants.py), it should be available in other applications via the import of api.py, you need to output the logs using the serializer (DRF).
constants.py (Sample version)
from model_utils import Choices
ACTIVITY_ACTIONS = Choices (
('ACTION_REQ_PHONE_VERIFY', 'Request phone verification'),
('VALIDATE_PHONE', 'Request phone validation'),
('VALIDATE_EMAIL', 'Email validation'),
('SET_INTERNAL_VERIFY', 'Set result of Internal verification'),
('SET_BANK_VERIFY', 'Set result of Bank verification'),
('GET_CLIENT_DATA', 'Request client data'),
('GET_SENSITIVE_INFO', 'Request sensitive info'),
)
Try the logging library, where you can access various type of log messages
like-
Error, Debug, Warning or just Information.
You can read more about here:
https://docs.python.org/3/library/logging.html
Related
I have set my multiple user model in Django rest framework and I am using dj_rest_auth, allauth and djangosimplejwt for my user Authentication and Authorisation workflow
my serialisers.py look like this
class LoginSerializer(Serializer):
email = EmailField(required=False, allow_blank=True)
password = CharField(style={'input_type': 'password'})
class Meta:
model = Users
fields = ['email', 'password']
extra_kwargs = {
'password': {'write_only': True},
'style': {'input_type': 'password'},
}
def authenticate(self, **kwargs):
return authenticate(self.context['request'], **kwargs)
def _validate_email(self, email, password):
if email and password:
user = self.authenticate(email=email, password=password)
else:
msg = {'error': _('Did you forget to include an email or password?')}
raise ValidationError(msg)
return user
def get_auth_user_using_allauth(self, email, password):
from allauth.account import app_settings
# Authentication through email
if (
app_settings.AUTHENTICATION_METHOD
== app_settings.AuthenticationMethod.EMAIL
):
return self._validate_email(email, password)
def get_auth_user(self, email, password):
"""
Retrieve the auth user from given POST payload by using
either `allauth` auth scheme or bare Django auth scheme.
Returns the authenticated user instance if credentials are correct,
else `None` will be returned
"""
if 'allauth' in settings.INSTALLED_APPS:
# When `is_active` of a user is set to False, allauth tries to return template html
# which does not exist. This is the solution for it. See issue #264.
try:
return self.get_auth_user_using_allauth(email, password)
except url_exceptions.NoReverseMatch:
msg = {'error': _('Unable to log in with provided credentials.')}
# msg = 'Unable to log in with provided credentials.'
raise exceptions.ValidationError(msg)
return self.get_auth_user_using_orm(email, password)
#staticmethod
def validate_auth_user_status(user):
if not user.is_active:
msg = _('User account is disabled.')
raise exceptions.ValidationError(msg)
#staticmethod
def validate_email_verification_status(user):
from allauth.account import app_settings
if (
app_settings.EMAIL_VERIFICATION
== app_settings.EmailVerificationMethod.MANDATORY
):
email_address = user.emailaddress_set.get(email=user.email)
if not email_address.verified:
raise exceptions.ValidationError(
{'error': _('E-mail is not verified.')}
)
def validate(self, data):
email = data.get('email')
password = data.get('password')
user = self.get_auth_user(email, password)
if not user:
msg = {'error': _('Unable to log in with provided credentials.')}
raise exceptions.ValidationError(msg)
# Did we get back an active user?
self.validate_auth_user_status(user)
# If required, is the email verified?
if 'dj_rest_auth.registration' in settings.INSTALLED_APPS:
self.validate_email_verification_status(user)
data['user'] = user
return data
and my views.py looks like this
class Login(LoginView):
"""
Check the credentials and return the REST Token
if the credentials are valid and authenticated.
Calls Django Auth login method to register User ID
in Django session framework
Accept the following POST parameters: username, password
Return the REST Framework Token Object's key.
"""
serializer_class = LoginSerializer
def post(self, request, *args, **kwargs):
self.request = request
self.serializer = self.get_serializer(data=self.request.data)
self.serializer.is_valid(raise_exception=True)
self.login()
return self.get_response()
def get_all_clients(self):
"""
Using related objects, get all clients of the business
"""
business = self.request.user
business_client = ClientProfile.objects.filter(business=business)
client_list = business_client.values(
'client__id',
'client__email',
'client__fullname',
'logo',
)
# rename the keys in clean_names
for client in client_list:
client['id'] = client.pop('client__id')
client['email'] = client.pop('client__email')
client['fullname'] = client.pop('client__fullname')
client['logo'] = (
f"{self.request.META['HTTP_HOST']}{business.profile_image.url}"
if client['logo']
else None
)
return client_list
# display user profile information based on type of user
def get_response(self):
response = super().get_response()
user = self.request.user
if user.type.name == "Business":
profile = {
'profile': {
'business_logo': f"{self.request.META['HTTP_HOST']}{user.businessprofile.logo.url}"
if user.businessprofile.logo
else None,
'business_name': user.businessprofile.business_name,
'user_type': user.type.name,
'client_list': self.get_all_clients(),
}
}
response.data.update(profile)
return response
elif user.type.name == 'Client':
profile = {
'profile': {
'logo': (
f"{self.request.META['HTTP_HOST']}{user.clientprofile.logo.url}"
)
if user.clientprofile.logo
else None,
'name': user.clientprofile.client_business_name,
'type': user.type.name,
'full_name': user.fullname,
'country': user.country.name,
}
}
response.data.update(profile)
return response
first thing I notice is when a user has an inactive account i.e user.is_active I want to write a more meaningful message to make it easy for the frontend but when I use the browsable api I get
{
"error": [
"Unable to log in with provided credentials."
]
}
and when I use postman I get a 401 error dictionary
{
"detail": "User is inactive",
"code": "user_inactive"
}
the above error comes when I use the dj_rest_auth documentation that says I should add
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'dj_rest_auth.jwt_auth.JWTCookieAuthentication',
),
}
But if I follow Django simplejwt documentation it says
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
)
}
I only get this both on postman and browsable api endpoint
{
"error": [
"Unable to log in with provided credentials."
]
}
I will appreciate if I can get a valid way to get the proper error message that I want and a little explanation on why there are different error codes and documentation for using this
I am trying to open a websocket connection from my angular 2+ app with my Django backend using Django Channels.
I went through this tutorial: https://www.youtube.com/watch?v=RVH05S1qab8
and managed to get everything working with the javascript portion written inline in a Django html template. But I am having issues simply opening a websocket connection when I migrated the front-end chat form to a separate angular 2 app.
Both font-end and backends are hosted locally.
Front End - Chat Form Template
<div *ngFor="let message of thread.messages">
<div>{{message.message}}</div>
</div>
<form #formData [formGroup]="form">
<div class="form-group">
<input formControlName="messageInput" #msgInput type="text" class="form-control" id="newMessage" placeholder="Type a message">
</div>
<button (click)="onSubmit($event)" type="submit" class="btn btn-primary">Send</button>
</form>
</div>
Front End - Chat Form Component
otherUser: User;
me: User;
threadId: number;
thread: Thread;
endpoint: string;
socket: WebSocket;
form = new FormGroup({
messageInput: new FormControl("")
});
get messageInput() {
return this.form.get('messageInput');
}
getThreadById(id: number) {
this._chatService.getThreadById(id).subscribe(thread => {
console.log("response: thread found", thread);
this.thread = thread;
},
error => {
console.log("error", error);
});
}
getEndpoint() {
let loc = window.location
let wsStart = "ws://"
if (loc.protocol == "https:") {
wsStart = 'wss://'
}
this.endpoint = wsStart + loc.host + loc.pathname;
return this.endpoint;
}
constructor(private _activatedRoute: ActivatedRoute) {
}
ngOnInit() {
this._activatedRoute.params.subscribe(params => { this.threadId = params['id']; });
if (this.threadId) {
this.getThreadById(this.threadId);
}
this.getEndpoint();
this.createSocket();
}
createSocket() {
this.socket = new WebSocket(this.endpoint);
console.log("endpoint ", this.endpoint);
this.socket.onopen = (e) => {
console.log("open", e);
}
this.socket.onmessage = (e) => {
console.log("message", e);
let chatDataMsg = JSON.parse(e.data);
this.thread.messages.push(chatDataMsg.message);
}
this.socket.onerror = (e) => {
console.log("error", e);
}
this.socket.onclose = (e) => {
console.log("close", e);
}
}
onSubmit($event) {
let msgText = this.messageInput.value;
let finalData = {
'message': msgText
};
let chatMessage: ChatMessage = new ChatMessage(this.thread, this.me, new Date(), msgText);
this.socket.send(JSON.stringify(finalData))
this.form.reset();
}
Django Backend Project Settings
ASGI_APPLICATION = "joole.routing.application"
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
"hosts": [("localhost", 6379)],
#"hosts": [os.environ.get('REDIS_URL', 'redis://localhost:6379')]
},
},
}
ALLOWED_HOSTS = ['joole-api.herokuapp.com', '.herokuapp.com', '127.0.0.1']
Django Websocket Routing
from channels.routing import ProtocolTypeRouter, URLRouter
from django.conf.urls import url
from channels.auth import AuthMiddlewareStack
from channels.security.websocket import AllowedHostsOriginValidator, OriginValidator
from chat.consumers import ChatConsumer
application = ProtocolTypeRouter({
'websocket': AllowedHostsOriginValidator(
AuthMiddlewareStack(
URLRouter(
[
url(r"^messages/(?P<id>[\w.#+-]+)/$", ChatConsumer)
]
)
)
)
})
Django Project Urls
from django.urls import path, include
from django.conf import settings
urlpatterns = [
path('messages/', include('chat.urls')),
]
Django WebSocket Consumer
import asyncio
import json
from users.models import CustomUser, Employee
from channels.consumer import AsyncConsumer
from channels.db import database_sync_to_async
from .models import Thread, ChatMessage
class ChatConsumer(AsyncConsumer):
async def websocket_connect(self, event):
print("CONNECTED", event)
thread_id = self.scope['url_route']['kwargs']['id']
thread_obj = await self.get_thread(thread_id)
self.thread_obj = thread_obj
chat_room = f"thread_{thread_obj.id}"
self.chat_room = chat_room
await self.channel_layer.group_add(
chat_room,
self.channel_name
)
await self.send({
"type": 'websocket.accept'
})
async def websocket_receive(self, event):
print("receive", event)
front_text = event.get('text', None)
if front_text is not None:
loaded_dict_data = json.loads(front_text)
msg = loaded_dict_data.get('message')
user = self.scope['user']
username = 'default'
if user.is_authenticated:
username = user.email
myResponse = {
'message': msg,
'username': user.email
}
await self.create_chat_message(user, msg)
# broadcasts the message event to be sent
await self.channel_layer.group_send(
self.chat_room,
{
"type": "chat_message",
"text": json.dumps(myResponse)
}
)
async def chat_message(self, event):
# send the actual message event
print("message", event)
await self.send({
"type": "websocket.send",
"text": event["text"]
})
async def websocket_disconnect(self, event):
print("disconnected", event)
#database_sync_to_async
def get_thread(self, id):
return Thread.objects.get(id=id)
#database_sync_to_async
def create_chat_message(self, me, msg):
thread_obj = self.thread_obj
return ChatMessage.objects.create(thread=thread_obj, user=me, message=msg)
Django Chat Models
class Thread(models.Model):
first = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='chat_thread_first')
second = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='chat_thread_second')
updated = models.DateTimeField(auto_now=True)
timestamp = models.DateTimeField(auto_now_add=True)
#property
def room_group_name(self):
return f'chat_{self.id}'
def broadcast(self, msg=None):
if msg is not None:
broadcast_msg_to_chat(msg, group_name=self.room_group_name, user='admin')
return True
return False
class ChatMessage(models.Model):
thread = models.ForeignKey(Thread, null=True, blank=True, on_delete=models.SET_NULL, related_name="messages")
user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='sender', on_delete=models.CASCADE)
message = models.TextField()
timestamp = models.DateTimeField(auto_now_add=True)
Django Chat Urls
from django.urls import include, path
from rest_framework import routers
from .views import ThreadViewSet, ChatMessageViewSet
router = routers.DefaultRouter()
router.register('thread', ThreadViewSet)
router.register('chatMessage', ChatMessageViewSet)
urlpatterns = [
path('', include(router.urls)),
]
Expected Output
I was expecting the "CONNECTED" message with the event information printed on the console according to the websocket_connect method in the consumers class. Similarly a "open" message with the event fired in my browser's console from the Angular 2+ chat.component.ts.
Actual Output
I immediately get this warning message on the browser console:
WebSocket connection to 'ws://localhost:4200/sockjs-node/344/ux0z32ma/websocket' failed: WebSocket is closed before the connection is established.
After about 2 minutes of waiting...
Attached image shows what is automatically output on the console.
I may have missed something, because I cannot see the Django configuration, but as far as I understood, you wrote that you're running the frontend and backend server separately. You can see that the frontend is trying to establish the connection to localhost:4200. I belive that is the angular server which doesn't make sense, you should point your WebSocket to the Django app, so in my opinion you should modify the method below:
SERVER_URL = "localhost:8000"
getEndpoint() {
let wsStart = "ws://"
if (window.location.protocol == "https:") {
wsStart = 'wss://'
}
this.endpoint = wsStart + SERVER_URL + window.location.pathname;
return this.endpoint;
}
But if you're hosting both apps on Django and exposing that on port 4200 that doesn't apply, though I'm quite sure that's not your case.
I'm pretty new to Django restframework, what i'm trying now is to return object with foreignkey.
class User(models.Model):
name = models.CharField(max_length=255,blank=True)
date_created = models.DateTimeField(auto_now_add=True)
date_modiefied = models.DateTimeField(auto_now=True)
area = models.CharField(max_length=255,blank=True)
uuid = models.CharField(max_length=255)
home = models.CharField(max_length=255,blank=True)
work = models.CharField(max_length=255,blank=True)
mobileNo = models.CharField(max_length=255,blank=True)
email = models.CharField(max_length=255,blank=True)
appVersionCode = models.CharField(max_length=255,blank=True)
photoUrl = models.CharField(max_length=255,blank=True)
serverTime = models.CharField(max_length=255,blank=True)
fcmTokenId = models.CharField(max_length=255,blank=True)
def __str__(self):
return self.name
class LocationData(models.Model):
user = models.ForeignKey(
User, related_name='user', on_delete=models.DO_NOTHING)
source_id = models.CharField(max_length=255)
latitude = models.CharField(max_length=255)
longitude = models.CharField(max_length=255)
speed = models.CharField(max_length=255)
kms = models.CharField(max_length=255)
date_created = models.DateTimeField(auto_now=True)
date_modiefied = models.DateTimeField(auto
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'
class LocationDataSerializer(serializers.ModelSerializer):
class Meta:
model = LocationData
fields = '__all__'
depth = 1
I'm using def get_queryset(self):
class SyncIndexLastDataViewSet(viewsets.ModelViewSet):
serializer_class = LocationDataSerializer
def get_queryset(self):
userid = self.request.query_params.get('user_id', None)
userExist = User.objects.filter(id=userid)
if userExist.exists():
# call the original 'list' to get the original response
queryset = LocationData.objects.values('source_id').filter(user__id=userid).order_by('-source_id')[:1]
lastSourceId = queryset[0]['source_id']
response = {"collection": {"data": lastSourceId,"statusCode": status.HTTP_200_OK,"version":"1.0"}}
json = JSONRenderer().render(response)
# customize the response data
if response is not None:
return json
else:
# return response with this custom representation
response = {"collection": {"data": "","statusCode":status.HTTP_404_NOT_FOUND,"version":"1.0","error":"Not found"}}
return response
Right now the result is inside the response is below and immediately it throws this error
But i want that queryset to return as below one, Hence i can read those key-pair values in android
{ "collection": {
"data": {
"id": 31,
"source_id": "55",
"latitude": "24654",
"longitude": "454654",
"date_created": "2019-02-08T17:10:09.318644Z",
"date_modiefied": "2019-02-08T17:10:09.318714Z",
"area": "54546",
"user": {
"id": 1,
"name": "Dormy",
"date_created": "1992-01-18T03:29:53.388000Z",
"date_modiefied": "2018-02-19T05:17:00.164000Z",
"serverTime": "",
"fcmTokenId": ""
}
},
"statusCode": 200,
"version": "1.0"
}
Now the error throws
AttributeError: Got AttributeError when attempting to get a value for field source_id on serializer LocationDataSerializer.
The serializer field might be named incorrectly and not match any attribute or key on the int instance.
Original exception text was: 'int' object has no attribute 'source_id'.
Thanks!
The answer to this depends on what type of view you are using but the bottom line is you don't do this in get_queryset you do this in the method for the type of reguest.
For example if you are using a RetrieveAPIView you should override the retrieve method from the RetrieveModelMixin like so:
class MyAPIView(RetrieveAPIView):
queryset = MyModel.objects.all()
serializer_class = MySerializer
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance)
data = {
"collection": {
"data": serializer.data
},
"statusCode": 200,
"version": "1.0"
}
return Response(data)
If you are using something else like a ListAPIView then you want to see what is used by that in the relevant method and override that to wrap your data.
The main thing to realise here is that it has nothing to do with getting the queryset - which is just about getting data from the database. This is about transforming the data into the correct format when sending back a response. As a result the work should be done at the point the response is made.
There are couple of solution possible for this problem. NDevox already mention how we can overwrite our retrive function and get our expected response. But If we want this will be done with every response for every api end-point and if we go this way we need to overwrite every function then its quite burden and its DRY we should avoid this as possible. One of the possible way to introduce a middleware or overwrite Response so that we can get our generic response for every-api end-point without explicitly overwrite every functionality.
Possible Solution One
As we are using DRF here we can add our own return responses with various media types, say for application/json.
First We need to add in our settings.py
REST_FRAMEWORK = {
...
'DEFAULT_RENDERER_CLASSES': (
'app_name.renderers.ApiRenderer', # our own render middleware
),
...
}
And in our custom render middleware
from rest_framework.renderers import BaseRenderer
from rest_framework.utils import json
class ApiRenderer(BaseRenderer):
def render(self, data, accepted_media_type=None, renderer_context=None):
our_response_dict = {
'version': '1.0'
'data': {},
'message': '',
}
if data.get('data'):
our_response_dict['data'] = data.get('data')
if data.get('status'):
our_response_dict['statusCode'] = data.get('status')
if data.get('message'):
our_response_dict['message'] = data.get('message')
data = our_response_dict
return json.dumps(data)
Reference Link
Possible Solution Two
If we are using ModelViewset then there is another way we can achievement that. Say Our Views.py are like following
class A(serializer.ModelSerializer):
........
class B(serializer.ModelSerializer):
........
class C(serializer.ModelSerializer):
........
Our goal is to overwrite ModelViewset's to_representation function and return our custom result. This will like as following
from collections import OrderedDict
class OurParentViewset(serializer.ModelSerializer):
......
def to_representation(self, instance):
data = super(serializers.ModelSerializer, self).to_representation(instance)
result = OrderedDict()
result['data'] = data
result['version'] = '1.0'
result['statusCode'] = '2xx' # i am not fully sure how to customize this
return result
class A(OurParentViewset):
........
class B(OurParentViewset):
........
class C(OurParentViewset):
........
Implementing a custom renderer here seems to be a ways to go.
You can have requests from your android client include in the Accept header a way to identify the client to the renderer. 1 e.g.
Accept: application/json; android=true
Then compose a renderer using the JSONRenderer class to provide the format for your Android client.
# ./formatters/android_format.py
from rest_framework.renderers import JSONRenderer, BaseRenderer
from django.http.multipartparser import parse_header
class AndroidV1FormatRenderer(BaseRenderer):
media_type = 'application/json'
format = 'json'
json_renderer = JSONRenderer()
def android(self, accepted_media_type):
base_media_type, params = parse_header(accepted_media_type.encode('ascii'))
return 'android' in params
def render(self, data, accepted_media_type=None, renderer_context=None):
response = renderer_context['response']
android = self.android(accepted_media_type)
if android:
data = {
"collection": {"data": data},
"statusCode": response.status_code,
"version": "1.0"
}
return json_renderer.render(
wrapped_data, accepted_media_type, renderer_context)
This can then be used where you require response formatted that way using renderer_classes attribute of your APIView. 2
Since get_queryset won't allow you to customize the response data. I decide to take the query value that's important to me.
http://localhost/api/users/?user_id=1 --> changed into ...api/users/1
def retrieve(self, request, *args, **kwargs):
""" userid = self.request.query_params.get('user_id', None) """
userid = kwargs.get('pk')
userExist = User.objects.filter(id=userid)
if userExist.exists():
# call the original 'list' to get the original response
queryset = LocationData.objects.values('source_id').filter(user__id=userid).order_by('-source_id')[:1]
lastSourceId = queryset[0]['source_id']
response = {"collection": {"data": lastSourceId,"statusCode": status.HTTP_200_OK,"version":"1.0"}}
# customize the response data
if response is not None:
return Response(response)
else:
# return response with this custom representation
response = {"collection": {"data": "","statusCode":status.HTTP_404_NOT_FOUND,"version":"1.0","error":"Not found"}}
return response
I'm looking for a way/function/method to make it impossible to save two identical names on my JSON, for example, I got this JSON with repeated names:
[
[
{
"id": "59a5c80dc75969297837c51e",
"name": "uza",
"password": "3648726"
},
{}
],
[
{
"id": "59a5c811c75969297837c51f",
"name": "kuza",
"password": "3648726"
},
{}
],
[
{
"id": "59a5c83ec75969297837c520",
"name": "kuza",
"password": "3648726"
},
{}
]
]
My code that creates an user is this one:
#api.route('/', methods=['POST'])
def create():
# Grabs the data from the requisition
user_json = request.get_json(silent=True)
if not user_json:
return "FAIL"
# creates an entity JSON
user, errors = schema.load(user_json)
if bool(errors):
return jsonify(errors)
user.save()
return "SUCCESS"
Again, I'm using mongoengine, anybody knows how to do it?
Edited to add my model.py
rom mongoengine import Document
from mongoengine import StringField, ReferenceField
import marshmallow_mongoengine as ma
from marshmallow import Schema, fields
from .service import ImageService
class User(Document):
name = StringField(unique=True)
password = StringField(unique=True)
class Face(Document):
user = ReferenceField(User)
image = StringField()
embedding = StringField()
def get_embedding(self):
return ImageService().from_base64_flat(self.embedding.encode())
def get_image(self):
return ImageService().from_base64(self.image.encode())
class UserSchema(ma.ModelSchema):
class Meta:
model = User
class FaceSchema(ma.ModelSchema):
class Meta:
model = Face
image = ma.fields.Method(deserialize="img_to_base64", serialize="img_to_base64")
embedding = ma.fields.Method(deserialize="to_base64", serialize="to_base64")
def img_to_base64(self, data):
return ImageService().to_base64(data)
def to_base64(self, data):
return ImageService().np_to_base64(data)
In the class User i changed it from required to unique, now i can't add one with the same name but in exchange it returns an INTERNAL SERVER ERROR on Insomnia, and as you can see i put another unique on the password for test and it didn't worked it saves even if there is another user with the same password.
Try this
class User(Document):
name = StringField(unique=True)
password = StringField(unique=True)
meta = {
'indexes': [{'fields': ['name'], 'unique': True}]
}
I am using endpoints_proto_datastore library by dhermes in my project based on google-endpoints.
Here is my code
class Log(EndpointsModel):
_message_fields_schema = ('id', 'createdOn', 'author', 'lastUpdatedBy')
createdOn = ndb.DateTimeProperty(auto_now_add=True)
author = ndb.UserProperty(auto_current_user_add=True)
lastUpdatedBy = ndb.UserProperty(auto_current_user=True)
#endpoints.api(name="logs", version="v1", description="Logs API")
class LogsApi(remote.Service):
#Log.method(user_required=True, path="log/create", name="create")
def addLog(self, log):
log.put()
return log
when I call the API, I get the following response
{
"createdOn": "2017-07-30T01:08:42.018641",
"id": "6296903092273152"
}
Why are auto_current_user_add and auto_current_user property not working? What am I doing wrong?