I can pass context to another class of models.Model but in models.AbstractModel it return none.
Here is my code.
class PrintWizard(models.TransientModel):
_name = 'print.report.wizard'
start_date = fields.Date()
end_date = fields.Date()
#api.multi
def print_report(self):
ctx = self.env.context.copy()
ctx.update({'start': self.start_date, 'end': self.end_date})
return self.env['report'].with_context(ctx).get_action('erp.report_id')
class ReportClass(models.AbstractModel):
_name = 'report.erp.report_id'
#api.multi
def render_html(self, data):
report_obj = self.env['report']
report = report_obj._get_report_from_name('erp.report_id')
start = self.env.context.get('start')
end = self.env.context.get('end')
docs = self.env['erp.account'].search([('start_date','>=',start),('end_date', '<=', end)])
docargs = {
'doc_model': report.model,
'docs': docs
}
return report_obj.render('erp.report_id', docargs)
i tried to print the start and end, it return none i think i am passing the context to absractmodel in a improper way.
Try this as an alternative to context (but it pretty well is context)
#api.multi
def print_report(self):
return {
'type':'ir.actions.report.xml',
'report_name': 'erp.report_id',
'datas': 'start': self.start_date, 'end': self.end_date}
}
#api.multi
def render_html(self, data):
report_obj = self.env['report']
report = report_obj._get_report_from_name('erp.report_id')
start = data.get('start')
end = data.get('end')
docs = self.env['erp.account'].search([('start_date','>=',start),('end_date', '<=', end)])
docargs = {
'doc_model': report.model,
'docs': docs
}
return report_obj.render('erp.report_id', docargs)
Related
I'm learning to create a blockchain system and cannot understand how this line fits into this code.
Why and how last_block() is used with 'index'?
class Blockchain(object):
def init(self):
self.chain = []
self.current_transactions = []
def new_block(self):
pass
def new_transaction(self):
pass
#staticmethod
def hash(block):
pass
#property
def last_block(self):
pass
block = {
'index': 1,
'timestamp': 1506057125.900785,
'transactions': [
{
'sender': "8527147fe1f5426f9dd545de4b27ee00",
'recipient': "a77f5cdfa2934df3954a5c7c7da5df1f",
'amount': 5,
}
],
'proof': 324984774000,
'previous_hash': "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
}
def new_transaction(self,sender,recipient,amount):
self.current_transactions.append({
'sender' : sender,
'recipient':recipient,
'amount':amount
})
return self.last_block['index']+1
If you're referring to
https://hackernoon.com/learn-blockchains-by-building-one-117428612f46 to implement the blockchain, view the full source code at https://github.com/dvf/blockchain/blob/master/blockchain.py.
On line 142 and 143 you see the following lines of code
def last_block(self):
return self.chain[-1]
Which clearly indicate how
return self.last_block['index']+1
works
Here is my django model
class Data(models.Model):
created = models.DateTimeField(null=True, blank=True, editable=False)
modified = models.DateTimeField(null=True, blank=True)
raw = models.TextField(null=True, blank=True)
uuid = models.CharField(blank=True, null=True, max_length=48,unique=True)
used = models.BooleanField(default=False,null=True)
name = models.CharField(blank=True, null=True, max_length=200)
geohash = models.CharField(blank=True, null=True, max_length=200)
def __str__(self):
return str(self.created) + ":" + str(self.raw)
def __unicode__(self):
return str(self.created) + ":" + str(self.raw)
def save(self, *args, **kwargs):
""" On save, update timestamps """
if not self.uuid :
self.uuid = str(uuid.uuid4().hex) +str(random.randint(1000,9999) )
if not self.id:
self.created = timezone.now()
self.modified = timezone.now()
# if not self.geoHash and (self.gpsLat and self.gpsLong):
# Geohash.encode(self.gpsLat, self.gpsLong)
return super(DataLbc, self).save(*args, **kwargs)
def toJson(self):
ret = {}
ret["Created"] = str(self.created)
ret["Modified"] = str(self.modified)
ret["Used"] = self.used
ret["Raw"] = self.raw
return ret
Here is the way that i send it to my golang server :
from RawOffer.models import Data
while True:
try :
for data in Data.objects.all()[:10]:
requests.post("http://127.0.0.1:8087/convert/",json=data.toJson())
except Exception as e:
print(e)
time.sleep(5)
Now my golang server :
package main
import (
"database/sql"
"encoding/json"
"fmt"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
"github.com/jmoiron/sqlx"
"github.com/lib/pq"
"strings"
"gopkg.in/guregu/null.v3"
)
type RawOffer struct {
RawOfferData string `json:"Raw"`
Modified null.Time `json:"Modified"`
Created null.Time `json:"Created"`
}
func convertLbc(c *gin.Context) {
var rawOffer RawOffer
c.BindJSON(&rawOffer)
fmt.Println(rawOffer.Created)
var err error
s := strings.Split(rawOffer.RawOfferData, `"ads": `)
s2 := `{ "ads": ` + s[1]
result := strings.Replace(s2, `, "status": "ready"}]`, ``, -1)
//fmt.Println(result)
var rawOfferLbc RawOfferLbc
if err = json.Unmarshal([]byte(result), &rawOfferLbc); err != nil {
fmt.Println(result)
panic(err)
}
}
var db *sqlx.DB
func main() {
var err error
fmt.Println("begin")
r := gin.Default()
r.Use(cors.Default())
r.POST("/convert/",convert)
r.Run((":8087"))
}
but for Created and modified when i try to receive it i have {0001-01-01 00:00:00 +0000 UTC false}
How to serialize a django datetime to send it in json and how to get it in golang?
My main goal so is to send an object with the date from the django app to a microservice in golang. So I need to serialize the django date and I need to write a lot of text because stackoverflow won't let me post my program if i don't write enough text ...
Regards
Here is a working example related to the question that could be helpful to someone in the future.
server.go
package main
import (
"fmt"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
"github.com/jmoiron/sqlx"
"gopkg.in/guregu/null.v3"
"strconv"
)
type RawOffer struct {
Used_f bool `json:"Used_f"`
Used_t bool `json:"Used_t"`
RawOfferData string `json:"Raw"`
Modified null.Time `json:"Modified"`
Created null.Time `json:"Created"`
}
func convert(c *gin.Context) {
var rawOffer RawOffer
c.BindJSON(&rawOffer)
fmt.Println(`Used_f = ` + strconv.FormatBool(rawOffer.Used_f))
fmt.Println(`Used_t = ` + strconv.FormatBool(rawOffer.Used_t))
fmt.Println(`RawOfferData = `, rawOffer.RawOfferData)
fmt.Println(`Modified = `, rawOffer.Modified)
fmt.Println(`Created = `, rawOffer.Created)
}
var db *sqlx.DB
func main() {
fmt.Println("begin")
r := gin.Default()
r.Use(cors.Default())
r.POST("/convert/", convert)
r.Run((":8087"))
}
test.py
import requests
import json
import datetime
def default(o):
if isinstance(o, (datetime.date, datetime.datetime)):
return o.isoformat() + 'Z'
try :
data = dict(
Created = datetime.datetime.utcnow(),
Modified = datetime.datetime.utcnow(),
Used_f = False,
Used_t = True,
Raw = 'some raw data here',
)
datastr = json.dumps(data, default=default)
print(datastr)
requests.post("http://127.0.0.1:8087/convert/", datastr)
except Exception as e:
print(e)
Log on test.py:
$ python test.py
{"Created": "2019-06-09T15:48:38.978230Z", "Modified": "2019-06-09T15:48:38.978689Z", "Used_f": false, "Used_t": true, "Raw": "some raw data here"}
Log on Server:
begin
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
[GIN-debug] POST /convert/ --> main.convert (4 handlers)
[GIN-debug] Listening and serving HTTP on :8087
Used_f = false
Used_t = true
RawOfferData = some raw data here
Modified = {2019-06-09 15:48:38.978689 +0000 UTC true}
Created = {2019-06-09 15:48:38.97823 +0000 UTC true}
[GIN] 2019/06/09 - 11:48:39 |[97;42m 200 [0m| 16.979399ms | 127.0.0.1 |[97;46m POST [0m /convert/
by default django datetime field had timezone support. you need think other way . or you can use django-extentions . this third party package comes with a created and modified datetime field which is don't record timezone, use those two field you will get output like {0001-01-01 00:00:00 }
I've used a dirty trick to serialize the date :
def toJson(self):
ret = {}
date_handler = lambda obj: (
obj.isoformat()
if isinstance(obj, (datetime.datetime, datetime.date))
else None
)
ret["Created"] = str(json.dumps(self.created, default=date_handler)).replace("\"","")
ret["Modified"] = str(json.dumps(self.modified, default=date_handler)).replace("\"","")
ret["Used"] = self.used
ret["Raw"] = self.raw
return ret
I hope someone will find a better solution
I have been pulling my hair due to this for quite some time. ModelField seems like a good option in my case, but I can't seem to get it to work. I am working on a search-engine for a project.
serializers.py
class FullSearchSerializer(serializers.Serializer):
profiles = serializers.ModelField(model_field=Profiles())
cv = serializers.ModelField(model_field=CV())
I get this little fantastic error:
'Profiles' object has no attribute '_get_val_from_obj'
The reason I'm doing this is because I fetch, lists and paginates several models before I serialize it. As such: (views.py)
result_list = []
for target in targets:
result = targets[target]['model'].objects.select_related().filter(reduce(operator.or_, targets[target]['query_list']) & targets[target]['extra_query'])
if result:
result_list.append(result)
print result_list
results = list(
sorted(
chain(*result_list),
key = lambda objects: objects.id,
)
)
print results
page = request.QUERY_PARAMS.get('page')
paginated_result = paginate(results, page)
serializer_context = {'request': request}
serialized = PaginatedSearchSerializer(paginated_result, context=serializer_context)
print serialized.data
return JSONResponse(serialized.data, status=status.HTTP_200_OK)
return JSONResponse({'message': 'No results'})
"targets[target]['model']" and so on comes from a dictionary which i loops though, getting the right model, serializers and so on. Since I am making a function where you are able to search though all, without specifying targets and I need a serializer that can handle that.
The complete search-class:
class Search(APIView):
#method_decorator(req_login)
#transaction.non_atomic_requests
def get(self, request, *args, **kwargs):
""" Defining variables """
count_result = 0
result = None
target = None
serialized = None
search_query = ''
result_list = {}
""" Checks so values are there. """
if 'target' in kwargs:
target = kwargs['target']
if 'q' in request.GET:
search_query = request.GET['q']
""" List of modeltions and methods for search. """
targets = {
'user': {
'model': Profiles,
'query_list': [
Q(profiledata__full_name__icontains=search_query)
],
'extra_query': Q(profiledata__role__role='applicant'),
'serializer': PaginatedProfileSerializer
},
'cv': {
'model': CV,
'query_list': [
Q(skills__icontains=search_query),
Q(education__icontains=search_query),
Q(experience__icontains=search_query),
Q(interests__icontains=search_query),
Q(languages__icontains=search_query),
Q(driverlicense__icontains=search_query)
],
'extra_query': Q(),
'serializer': CVSerializer
},
'corporation': {
'model': Corporation,
'query_list': [
Q(name__icontains=search_query),
Q(description__icontains=search_query),
Q(keywords__title__icontains=search_query)
],
'extra_query': Q(),
'serializer': PaginatedCorporationSerializer
},
'jobs': {
'model': Jobs,
'query_list': [
Q(title__icontains=search_query),
Q(description__icontains=search_query),
Q(keywords__title__icontains=search_query)
],
'extra_query': Q(),
'serializer': PaginatedJobSerializer
}
}
""" Making stuff happen and returns result """
if target:
result = targets[target]['model'].objects.select_related().filter(reduce(operator.or_, targets[target]['query_list']) & targets[target]['extra_query'])
if result:
count_result = result.count()
page = request.QUERY_PARAMS.get('page')
paginated_result = paginate(result, page)
serializer_context = {'request': request}
serialized = targets[target]['serializer'](paginated_result, context=serializer_context, many=True)
return JSONResponse({'query': serialized.data, 'count': count_result}, status=status.HTTP_200_OK)
else:
result_list = []
for target in targets:
result = targets[target]['model'].objects.select_related().filter(reduce(operator.or_, targets[target]['query_list']) & targets[target]['extra_query'])
if result:
result_list.append(result)
print result_list
results = list(
sorted(
chain(*result_list),
key = lambda objects: objects.id,
)
)
print results
page = request.QUERY_PARAMS.get('page')
paginated_result = paginate(results, page)
serializer_context = {'request': request}
serialized = PaginatedSearchSerializer(paginated_result, context=serializer_context)
print serialized.data
return JSONResponse(serialized.data, status=status.HTTP_200_OK)
return JSONResponse({'message': 'No results'})
Here is my class:
class WorkflowsCloudant(cloudant.Account):
def __init__(self, account_id):
super(WorkflowsCloudant, self).__init__(settings.COUCH_DB_ACCOUNT_NAME,
auth=(settings.COUCH_PUBLIC_KEY, settings.COUCH_PRIVATE_KEY))
self.db = self.database(settings.COUCH_DB_NAME)
self.account_id = account_id
def get_by_id(self, key, design='by_workflow_id', view='by_workflow_id', limit=None):
params = dict(key=key, include_docs=True, limit=limit)
docs = self.db.design(design).view(view, params=params)
if limit is 1:
doc = [doc['doc'] for doc in docs]
if doc:
workflow = doc[0]
if workflow.get("account_id") != self.account_id:
raise InvalidAccount("Invalid Account")
return workflow
else:
raise NotFound("Autoresponder Cannot Be Found")
return docs
Here is my test:
def test_get_by_id_single_invalid_account(self):
self.klass.account_id = 200
self.klass.db = mock.MagicMock()
self.klass.db.design.return_value.view.return_value = [{
'doc': test_workflow()
}]
# wc.get_by_id = mock.MagicMock(side_effect=InvalidAccount("Invalid Account"))
with self.assertRaises(InvalidAccount("Invalid Account")) as context:
self.klass.get_by_id('workflow_id', limit=1)
self.assertEqual('Invalid Account', str(context.exception))
I'm trying to get the above test to simple raise the exception of InvalidAccount but I'm unsure how to mock out the self.db.design.view response. That's what's causing my test to fail because it's trying to make a real call out
I think this is what you want.
def test_get_by_id_single_invalid_account(self):
self.klass.account_id = 200
self.klass.db = mock.MagicMock()
self.klass.db.design = mock.MagicMock()
view_mock = mock.MagicMock()
view_mock.return_value =[{
'doc': test_workflow()
}]
self.klass.db.design.return_value.view = view_mock
# wc.get_by_id = mock.MagicMock(side_effect=InvalidAccount("Invalid Account"))
with self.assertRaises(InvalidAccount("Invalid Account")) as context:
self.klass.get_by_id('workflow_id', limit=1)
self.assertEqual('Invalid Account', str(context.exception))
I am having problem understanding how mock works and how to write unittests with mock objects. I wanted to mock an external api calls so I can write unittests for these functions and functions which use these calls.
I tried to mock check_sms_request at first and later I need to do something with it to cover check_delivery_status for an object.
How do I write test for this cases?
Function to mock
def check_sms_request(remote_id, phone):
if not can_sms(phone):
return None
client = Client(settings.SMS_API_URL)
base_kwargs = {
'phone': phone,
'remoteId': remote_id,
}
request = client.service.CheckSmsRequest(settings.SMS_API_LOGIN, settings.SMS_API_PASSWORD, base_kwargs)
return request
class SMS(models.Model):
sms_response = models.IntegerField(choices=SMS_SEND_STATUS, null=True, blank=True)
delivery_status = models.IntegerField(choices=DELIVERY_STATUS_CHOICES, null=True, blank=True)
has_final_status = models.BooleanField(default=False)
def check_delivery_status(self):
if not self.has_final_status:
response_status = check_sms_request(self.id, self.phone)
if response_status is not None:
self.history.create(fbs_status=self.sms_response, delivery_status=response_status.response)
if response_status is not None and response_status.response in FINAL_STATUSES:
self.has_final_status = True
if response_status is not None:
self.delivery_status = response_status.response
self.save()
return self.delivery_status
My test:
#override_settings(SMS_WHITELIST=['', ], SMS_ENABLE=True)
def test_soap_check_sms_request(self):
check_sms_request = Mock(return_value=True)
check_sms_request.response = SMS_SENT_AND_RECIEVED
self.assertEqual(check_sms_request.response, SMS_SENT_AND_RECIEVED)
obj = SMS.objects.create(**{
'phone': self.user.phone,
'text': u"Hello",
'user': self.user,
'site': self.site2,
})
obj.check_sms_status()
You could monkey-patch the function for the test, like so:
#override_settings(SMS_WHITELIST=['', ], SMS_ENABLE=True)
def test_soap_check_sms_request(self):
check_sms_request = Mock(return_value=True)
check_sms_request.response = SMS_SENT_AND_RECIEVED
self.assertEqual(check_sms_request.response, SMS_SENT_AND_RECIEVED)
obj = SMS.objects.create(**{
'phone': self.user.phone,
'text': u"Hello",
'user': self.user,
'site': self.site2,
})
import model
old_fn = model.check_sms_request
model.check_sms_request = check_sms_request
obj.check_sms_status()
model.check_sms_request = old_fn
test check_sms_request first
mock Client
retrive service and CheckSmsRequest mocks using return_value
call check_sms_request
check Client and CheckSmsRequest was called once with right args
check_sms_request should be method of a class, move it inside SMS model or just add method and call the function from this method
Mock this model method when testing check_delivery_status
Model:
class SMS(models.Model):
sms_response = models.IntegerField(choices=SMS_SEND_STATUS, null=True, blank=True)
delivery_status = models.IntegerField(choices=DELIVERY_STATUS_CHOICES, null=True, blank=True)
has_final_status = models.BooleanField(default=False)
def check_sms_request(remote_id, phone):
if not can_sms(phone):
return None
client = Client(settings.SMS_API_URL)
base_kwargs = {
'phone': phone,
'remoteId': remote_id,
}
request = client.service.CheckSmsRequest(settings.SMS_API_LOGIN, settings.SMS_API_PASSWORD, base_kwargs)
return request
def check_delivery_status(self):
if not self.has_final_status:
response_status = self.check_sms_request(self.id, self.phone)
if response_status is not None:
self.history.create(fbs_status=self.sms_response, delivery_status=response_status.response)
if response_status is not None and response_status.response in FINAL_STATUSES:
self.has_final_status = True
if response_status is not None:
self.delivery_status = response_status.response
self.save()
return self.delivery_status
Test:
class SMSModelTestCase(TestCase):
#patch('...Client')
def test_check_sms_request(self, ClientMock):
client_object = ClientMock.return_value
CheckSmsRequestMock = client_object.service.return_value.CheckSmsRequest
sms_model = SMS() # don't save
with self.settings(SMS_API_URL='http://example.com', SMS_API_LOGIN='kanata', SMS_API_PASSWORD='izumi'):
sms_model.check_sms_request(101, '+11111111')
ClientMock.assert_called_once_with('http://example.com')
CheckSmsRequestMock.assert_called_once_with('kanata', 'izumi', '+11111111', 101)
#patch('myproject.myapp.models.SMS.check_sms_request')
def test_check_delivery_status(self, CheckSmsRequestMock):
CheckSmsRequestMock.return_value = ...
sms_model = SMS()
...
sms_model.check_delivery_status(...)