Why is Django reverse() failing with unicode? - python

Here is a django models file that is not working as I would expect.
I would expect the to_url method to do the reverse lookup in the urls.py file, and get a url that would correspond to calling that view with arguments supplied by the Arguments model.
from django.db import models
class Element(models.Model):
viewname = models.CharField(max_length = 200)
arguments = models.ManyToManyField('Argument', null = True, blank = True )
#models.permalink
def to_url(self):
d = dict( self.arguments.values_list('key', 'value') )
return (self.viewname, (), d)
class Argument(models.Model):
key = models.CharField(max_length=200)
value = models.CharField(max_length=200)
The value d ends up as a dictionary from a unicode string to another unicode string, which I believe, should work fine with the reverse() method that would be called by the permalink decorator, however, it results in:
TypeError: reverse() keywords must be strings

In your to_url method, you need to make sure the keys in the d dict are not Unicode strings. This isn't peculiar to Django, it's just how keyword arguments to functions work in Python. Here's a simple example:
>>> def f(**kwargs): print kwargs
...
>>> d1 = { u'foo': u'bar' }
>>> d2 = { 'foo': u'bar' }
>>> f(**d1)
TypeError: f() keywords must be strings
>>> f(**d2)
{'foo': u'bar'}
Changing your
d = dict( self.arguments.values_list('key', 'value') )
into something like
d = dict((str(k), v) for k, v in self.arguments.values_list('key', 'value').iteritems())
should do the trick.

Related

json.dumps generates a string and returning it as dict is making a string inside another string, how to avoid it and get just a single string

class_object = ModelClass(title=entity_object['title'],
entities_definition_key=entity_object['entities_definition_key'],
orderId=entity_object['orderId'],uid = json.dumps( uuid.uuid4(),
cls=UUIDEncoder))
ModelClass is mongoengine model class
json_output = class_object.serializing_method()
final_list.append(json_output)
another_class_object = AnotherModelClass(workflowId=body['workflowId'],entities_list=final_list)
another_class_object.save()
save() to mongodb
final_dict={}
final_dict['entities_list'] = another_class_object.entities_list
return HttpResponse(json.dumps({'entity_definition_dict':entity_definition_dict}))
output-{'uid': "\"74b1900ccfbd44234563805ac0279d\""}
I don't know why you need to call json.dumps() on the UUID. It causes all your problems and I can't imagine a problem it would fix.
class_object = ModelClass(
...,
uid = uuid.uuid4().hex,
)

How to Call django model field name from a list?

django models.py
class mymodel(models.Model):
date_check = models.DateField()
item_1 = models.NullBooleanField()
item_2 = mod`enter code here`els.NullBooleanField()
item_3 = models.NullBooleanField()
item_4 = models.NullBooleanField()
item_5 = models.NullBooleanField()
Task:
>>> from .models import mymodel
>>>
>>> a_list = ['item_1', 'item_2', 'item_3', 'item_4', 'item_5', 'item_5', ]
>>> a_year = 2018
>>> param1 = {}
>>> param2 = {}
>>> param3 = {}
>>> for item in a_list :
>>> param1[item] = mymodel.objects.filter(date_check__year = a_year, item=True).count()
>>> param2[item] = mymodel.objects.filter(date_check__year = a_year, item=False).count()
>>> param3[item] = mymodel.objects.filter(date_check__year = a_year, item=None).count()
.....error here
how do we call field name from list?
Here item is interpreted as an identifier, so the name of the parameter is item. The fact that there is a variable with the same name and a certain value, is not relevant.
We can however fix this by constructing a dictionary that maps item (so here it will be replaced with the corresponding value) to True, False, and None. We the can use this dictionary as the named parameters dictionary* by using two consecutive asterisks as prefix:
for item in a_list :
param1[item] = mymodel.objects.filter(date_check__year=a_year, **{item: True}).count()
param2[item] = mymodel.objects.filter(date_check__year=a_year, **{item: False}).count()
param3[item] = mymodel.objects.filter(date_check__year=a_year, **{item: None}).count()
Note that this will hoever result in multiple queries. We can reduce the amount of querying by for example aggregating over a selection, like:
qs = mymodel.objects.filter(date_check__year=a_year)
for item in a_list :
data = qs.aggregate(
p1=Count('pk', filter=Q(**{item: True}))
p2=Count('pk', filter=Q(**{item: False}))
p3=Count('pk', filter=Q(**{item: None}))
)
param1[item] = data['p1'] or 0
param2[item] = data['p2'] or 0
param3[item] = data['p3'] or 0
Here we thus count three things per query: the number of Trues, Falses and Nones. We can actually extend this logic, and even count everything in a single query, which is typically more efficient (this is not per se true, but making a query typically results in some overhead to construct a query, interpret the query at the database side, serializing results, etc.).

how to convert json to model in python3

i am trying convert json string to model
then it is easy to get value with .
i have checked another question
but different, my json sting looks like,
{
"id":"123",
"name":"name",
"key":{
"id":"345",
"des":"des"
},
}
i prefer to use 2 class like,
class A:
id = ''
name = ''
key = new B()
class B:
id = ''
des = ''
There are few libraries that might help:
marshmallow is nice
colander from Pylons
schematics
For easier cases you can also use something from standard library like
named tuples and one from collections which is available also in py2
SimpleNamespace
In order to do that you should provide your custom callback as an object_hook argument to the json.loads function.
object_hook is an optional function that will be called with the
result of any object literal decode (a dict). The return value of
object_hook will be used instead of the dict. This feature
can be used to implement custom decoders (e.g. JSON-RPC class hinting).
Consider using collections.namestuple subclasses:
json_str = '''
{
"id":"123",
"name":"name",
"key":{
"id":"345",
"des":"des"
}
}'''
B = collections.namedtuple('B', 'id des')
A = collections.namedtuple('A', 'id name key')
def make_models(o):
if 'key' in o:
return A(o['id'], o['name'], B(id=o['key']['id'], des=o['key']['des']))
else:
return o
result = json.loads(json_str, object_hook=make_models)
print(type(result)) # outputs: <class '__main__.A'>
print(result.id) # outputs: 123
print(result.key.id) # outputs: 345

Set Django model field by choice text name

Consider the following example model:
class MyModel(models.Model):
TYPE_ONE = 1
TYPE_TWO = 2
TYPE_CHOICES = (
(TYPE_ONE, "One"),
(TYPE_TWO, "Two"),
)
type = models.SmallIntegerField(choices=TYPE_CHOICES)
# ... other fields
This works well internally, as I now have a 'constant' which I can reuse throughout my code to refer to each type.
However, when this model gets serialized and sent to the client as JSON through a custom API Controller implementation, it turns the type into it's textual representation. It might look like this:
{
'id': 1,
'type': 'One'
}
This is fine, however I'd like to be able to set the field value based on this text version (the consumer of my API wants to be able to pass friendly strings, not ints).
When constructing a model instance, how can I set type to One, and have it automatically convert it into the relevant int?
Something like:
m = MyModel()
m.type = "One"
m.save() # throws a ValueError
Thanks
You can use this workaround:
m.type = dict((key,value) for (value,key) in MyModel.TYPE_CHOICES)['One']
You should make one property for it. So you can use whenever you want.
class MyModel(object):
TYPE_CHOICES = ((1, "One"), (2, "Two"))
type = models.SmallIntegerField(choices=TYPE_CHOICES)
def getx(self):
return self.type
def setx(self, val):
ch = filter(lambda y: y if y[1] == val else None, self.TYPE_CHOICES)
self.type = ch[0][0]
type_val = property(getx, setx)
then save like this.
m = MyModel()
m.type_val = "One"
m.save()
it will save into type.
Hopefully, it will work for you. :)

Is it possible getting all parameters of a field

What I need is returning all the parameters from field :
Example :
Class MyClass(models.Model):
field = models.Charfield(blank = True, null = True)
I want to return all the parameters of "field" from "MyClass".
Here, it should be the parameters blank and null.
For a model MyModel
class MyModel(models.Model):
my_field = models.Charfield(max_length=100)
You can get the field using the Meta api.
>>> field = MyModel._meta.get_field('my_field')
You can then use the deconstruct method to get the kwargs that were passed to the field when it was instantiated.
>>> name, path, args, kwargs = field.deconstruct()
>>> print(kwargs)
{u'max_length': 100}
I did not really get the purpose of getting the parameters, but I think you can use 'vars'. It's kind of wrap for '__dict__'.
As django model fields have '__dict__' attribute, 'vars' will give you access to the field's parameters as follow:
def has_parameter(field_name, parameter_name):
parameter_dict = vars(field_name)
return not parameter_dict.get(parameter_name) == None
if equal to None means it's not set yet otherwise it's set or has a default value.
in you case: >>> has_parameter(field_name,'through')

Categories

Resources