Overload get_FIELD_display() function - django

Is there a way to overload Django's get_FIELD_display() function properly? When I call the function from inside itself, the result is a recursion. But I can't call it using super() either, as it's not a parent class' method but a method created by the metaclass...
The goal is to have a common interface for getting a displayable version of a CHOICE field (which is given by get_FIELD_display), but with the possibility to customize it in some specific cases.
Example:
# This does not work because it results in recursion
def get_opposition_state_display(self):
"""Overloading of default function."""
value = self.get_opposition_state_display()
if self.opposition_state == 4:
return '%s %s' % (value, self.opposition_date.strftime('%d.%m.%Y'))
return value

updated
field = self._meta.get_field('opposition_state')
value = self._get_FIELD_display(field)

To override get_FOO_display you need something like this:
field_name = models.PositiveSmallIntegerField('Field', choices=some_choices)
def _get_FIELD_display(self, field):
f_name = field.name
if f_name == 'field_name':
return 'what_you_need'
return super(YourModelName, self)._get_FIELD_display(field=field)

Related

Python - Overriding a parent variable with a getter/setter

So I have a parent class BaseAdd that I'm trying to subclass. The BaseAdd uses self.left and self.right, I want to use self.nodes to make it easier to access both left and right at once:
class BaseAdd():
def __init__(self, leftright):
self.left = leftright[0]
self.right = leftright[1]
class Add(BaseAdd):
def __init__(self, leftright):
self.nodes = leftright
#property
def left(self):
return self.nodes[0]
#left.setter
def left(self, value):
self.nodes[0] = value
foo = Add(('L', 'R'))
foo.left = "new"
print(foo.left, foo.nodes[0])
>>> ('new', 'L')
The problem is that the setter is never getting called, my hunch is that it's using the BaseAdd.left somehow instead. How can I make the setter properly set the list element?

Compare Django child classes of abstract model in Django

I have two classes as childs of abstract class (example below).
How to check if queryset model is one or other of these classes?
class Parent(models.Model)
field_a = models.CharField(primary_key = True, max_length = 24)
field_b = models.CharField(primary_key = True, max_length = 24)
class Meta:
abstract = True
class A(Parent)
pass
class B(Parent)
pass
I have tired something like this but it's not working:
if type(queryset.model) == type(A):
do something...
elif type(queryset.model) == type(B):
do something else...
because when I check the type(queryset.model) it's returns type(Parent),
even the queryset.model is the A or B class.
To be more precise issubclass is not working.
isinstance method is not working too because the object which I check is not instance.
my problem is for example when i have queryset of one of child models, and when I don't know exactly which one how do I check this?
for example:
queryset = A.objects.all()
# or
queryset = B.objects.all()
if I don't ktow the queryset (dynamic method) this check like this it returns false for boths conditions:
if type(queryset.model) == type(A):
do something...
elif type(queryset.model) == type(B):
do something else...
because true is:
type(queryset.model) == type(Parent)
my solution is to use __name__ but I don't know if there is a better way?
if queryset.model.__name__ == A.__name__:
do something...
elif queryset.model.__name__ == B.__name__:
do something else...
You should compare queryset.model directly with the class.
Something like this should work:
if queryset.model == A:
# do your stuff

Using dict like C switch

class checkevent:
def __init__(self,fromuser):
self.fromuser = fromuser
def openid_check(self):# use sqlalchemy
exist_user = User.query.filter_by(openid = self.fromuser).first()
if exist_user is None:
text = u'请绑定后在使用'
return text
def grade(self):
openid_check()
exist_user = User.query.filter_by(openid = self.fromuser).first()
geturp = urp(exist_user.username, exist_user.password_urp) #the function
return geturp #return the grades as text
def key_check(self,x): # use dict like switch
{'grade': self.grade
}
contents = checkevent('ozvT4jlLObJWzz2JQ9EFsWSkdM9U').key_check('grade')
print contents
It's always return None,I want to get a value
and it's the right way to use dict?
There's no return statement in key_check, so naturally it doesn't return anything. You're basically missing the last bit of the implementation: once you look up the appropriate function by name, you need to call that function and return the result.
def key_check(self, key): # "x" is a meaningless name; use something meaningful
lookup = {
'grade': self.grade
}
func = lookup[key] # Look up the correct method
return func() # Call that method and return its result
Technically you could in-line all that into one statement if you really wanted to, but unless performance is at a premium I wouldn't recommend it as the readability suffers.

Grails Criteria not working in JUnit Test

I'm trying to test search method in my grails app but I'm having a null pointer exception. I mocked the domain in my test as follows:
#TestFor(AuditController)
#Mock(Audit)
class AuditControllerTests {
void testSearch() {
populateValidParams(params)
def audit=new Audit(params)
audit.save(failOnError: true)
//Search existing customer
def model = controller.search()
assert model.auditInstanceList.size() == 1
assert model.auditInstanceList.size() == 1
}
}
I got NPE on model.auditInstanceList. Where it shouldn't be null. Here is the code in my controller:
def search = {
def query
def criteria = Audit.createCriteria()
def results
query = {
and{
if(params.customerName){
ilike("customerName", params.customer + '%')
}
if(params.siteName){
ilike("siteName", params.siteName + '%')
}
max:params.max
offset:params.offset
}
}
results = criteria.list(params, query)
render(view:'list', model:[ auditInstanceList: results,auditInstanceTotal:results.totalCount ])
}
What is going on with this?
Return model at the end of search. As in,
def search = {
...
render(view:'list', model:[ auditInstanceList: results, auditInstanceTotal:results.totalCount ])
[auditInstanceList: results, auditInstanceTotal:results.totalCount]
}
When testing a controller action that calls render(), model and view variables are automatically created and populated in your test. By doing def model = controller.search(), you are replacing the magic model with your own, assigning it to the return value of search(). The correct way to do your assertions is:
controller.search()
assert model.auditInstanceList.size() == 1
assert view == '/audit/list'
I don't know why but sometimes you need to remove model as a return value from controller's action. I use both version alternatively in case one of them fails:
// sometimes this one works
def model = controller.search()
assert model
// sometimes this one works
controller.search()
assert model
Edit: I think of two new possibilities why your action doesn't work:
try to change your action from closure and make it a method.
make sure you have no after filter. I've found this bug: http://jira.grails.org/browse/GRAILS-6825

How do I access the id of a Django Widget from the widget definition?

I am creating a custom widget for a datetime field:
class MySplitDateTimeWidget(forms.SplitDateTimeWidget):
def format_output(self, rendered_widgets):
mytimeid = self.widgets[1].attrs['id'] #####NEED HELP HERE
temp = "javascript:$('%s').val(new Date().getHours());" % mytimeid
temp1 = 'Now' % temp
return mark_safe(u'%s %s<br />%s %s %s' % \
(_('Date:'), rendered_widgets[0], _('Time:'), rendered_widgets[1],
temp1
))
I need the "id" attribute of the widget, however self.widgets doesn't include the "id" attribute in attrs. It includes every other attribute though. I'm not sure where this attribute comes from?
I was just grappling with the exact same thing; hopefully this is useful for other people. The "id" attr is set via:
Form is asked to render itself
Form iterates through its fields
For each field, the form calls its custom __getitem__() which wraps the field as a BoundField
The BoundField, in the as_widget() method, is what actually sets the "id" attribute (see also the auto_id() method)
The MultiWidget then performs its render() method, which renders each of its child widgets and then joins them with format_output()
So, to answer your question, you want to get the ID in the render() method and not the format_output() method:
class MySplitDateTimeWidget(forms.SplitDateTimeWidget):
def render(self, name, value, attrs=None):
widgets_html = super(MySplitDateTimeWidget, self).render(name, value, attrs)
# attrs['id'] is the ID of the entire widget, append the prefix to chose the sub-widget
mytimeid = attrs['id'] + '_0'
temp = "javascript:$('%s').val(new Date().getHours());" % mytimeid
temp1 = 'Now' % temp
return mark_safe(widgets_html + ' ' + temp1)
def format_output(self, rendered_widgets):
return mark_safe(u'%s %s<br />%s %s' % (_('Date:'), rendered_widgets[0], _('Time:'), rendered_widgets[1]))
Unless you've overwritten it, the ID should be:
id_[name]
So try:
mytimeid = 'id_'+self.widgets[1].attrs['name']