Is it dangerous to define __contains__ on a metaclass? - python-2.7

I'm writing a custom EnumMeta class in Python 2.7 that will collect enum keys and values from some class and augment that class with some additional fields.
class EnumMeta(type):
def __init__(cls, name, bases, props):
cls.__all_values__ = [...] # collect all interesting properties
def __contains__(cls, value):
return value in cls.__all_values__
class TheFellowshipOfTheRing(object):
__metaclass__ = EnumMeta
FRODO = 'Frodo Baggins'
SAM = 'Samwise "Sam" Gamgee'
MERRY = 'Meriadoc "Merry" Brandybuck'
PIPPIN = 'Peregrin "Pippin" Took'
GANDALF = 'Gandalf the Grey'
ARAGORN = 'Aragorn (Strider)'
LEGOLAS = 'Legolas'
GIMLI = 'Gimli'
BOROMIR = 'Boromir'
print 'Gandalf the Grey' in TheFellowshipOfTheRing
# True
print 'Saruman' in TheFellowshipOfTheRing
# False
I'm wondering if implementing container-specific functions, such as __contains__, on a metaclass is a dangerous thing to do, and if so, why?

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?

How to modify the form filed data?

I have a model:
class PastStudy(Model):
grade_average = FloatField(null=True)
I have a modelform as below:
class PastStudyForm(ModelForm):
class Meta:
model = PastStudy
fields = ('grade_average', )
What I have in view:
...
if request.POST:
past_study_form = PastStudyForm(request.POST)
if past_study_form.is_valid():
return HttpResponse(past_study_form.cleaned_data['grade_average'])
else:
profile_filter_past_study_form = ProfileFilterPastStudyForm()
...
What I need is that I want to write a clean method for PastStudyForm so that in case I entered 90 as grade average, HttpResponse converts it two 0-20 grading scheme and returns 18.
I tried this and I was still getting 90 not 18
class PastStudyForm(ModelForm):
class Meta:
model = PastStudy
fields = ('grade_average', )
def clean(self):
cleaned_data = super().clean()
grade_average = self.cleaned_data['grade_average']
self.cleaned_data['grade_average'] = grade_average/5
return cleaned_data
and This:
class PastStudyForm(ModelForm):
class Meta:
model = PastStudy
fields = ('grade_average', )
def clean_grade_average(self):
grade_average = self.cleaned_data['grade_average']
data = grade_average/5
return data
However, I still get 90. I also have tried a few other methods but I still was getting 90 in HttpResponse
Maybe using clean method be wrong and I should do something else!
The real code is huge and I have summarized it in here and other aspects of the problem are not explained in here. That is why I prefer and expect to get a response in which I am advised how to it in the form definition, not other methods such as converting it in the view.
in your clean method, you assign the result of your calculation method into self.cleaned_data,
while you are returning cleaned_data not self.cleaned_data.
it is different variable.
try this instead:
self.cleaned_data = super().clean()
grade_average = self.cleaned_data['grade_average']
self.cleaned_data['grade_average'] = grade_average/5
return self.cleaned_data

How to execute a function when a variable's value is changed?

In Odoo 10, I want to change the value of a variable when the forecasted quantity of a product is changed. I tried using the #api.onchange decorator, but it doesn't work. The forecasted quantity change, but the variable keeps the same value. I have this:
class MyProduct(models.Model):
_inherit = 'product.product'
was_changed = fields.Boolean(default = False)
#api.onchange('virtual_available')
def qtychanged(self):
self.was_changed = True
_logger.info('Product_Qty_Cahnged: %s',str(self.virtual_available))
In this code, if the forecasted quantity of a product would change, the variable was_changed should be set to True, but nothing happens.
After that, I tried to overwrite the write method for my custom class, like this:
class MyProduct(models.Model):
_inherit = 'product.product'
was_changed = fields.Boolean(default=False)
#api.multi
def write(self, values):
if values['virtual_available']:
values['was_changed'] = True
# THE FOLLOWING LINES WERE IN THE ORIGINAL WRITE METHOD
res = super(MyProduct, self).write(values)
if 'standard_price' in values:
self._set_standard_price(values['standard_price'])
return res
But still, I have the same result. I can't seem to get that flag to change. So, any ideas?
Try this:
class MyProduct(models.Model):
_inherit = 'product.product'
was_changed = fields.Boolean(default = False)
#api.onchange('virtual_available')
def qtychanged(self):
self.write({'was_changed': True})
_logger.info('Product_Qty_Cahnged: %s',str(self.virtual_available))

Is there a converter between django.forms.Form and rest_framework.serializers?

I already have plenty of forms defined in my django 1.9 project. Now I need to export them as REST (DRF 3.5.3) as well.
With just a bit of hacking, I was able to provide GET and PUT methods. But I also need to provide the OPTIONS method and I can't seem to find anything that would help me do that.
So, is there something that would convert an instanced form to DRF Serializer / ViewSet?
No but you can do the other way around as explained in http://www.django-rest-framework.org/topics/html-and-forms/#rendering-forms.
drf-braces can do this.
from django import forms
from drf_braces.serializers.form_serializer import FormSerializer
class MyForm(forms.Form):
foo = forms.CharField(max_length=32)
bar = forms.DateTimeField()
class MySerializer(FormSerializer):
class Meta(object):
form = MyForm
https://github.com/dealertrack/django-rest-framework-braces/blob/master/docs/overview.rst
I didn't want to mess with all of my custom logic in the forms, so I just added an as_options method:
class APIViewForm(Form):
def as_dict(self):
return {fld.auto_id: self.initial.get(fld.name, None) for fld in self}
def as_options(self):
flds = {}
for fld in self:
flds[fld.name] = f = {}
fld = fld.field
f.update(dict(
required=fld.required,
read_only=fld.disabled,
label=fld.label,
))
if isinstance(fld, (CharField, URLField)):
f['type'] = 'field'
if fld.max_length:
f['max_length'] = fld.max_length
if fld.min_length:
f['min_length'] = fld.min_length
elif isinstance(fld, IntegerField):
f['type'] = 'integer'
if fld.max_value:
f['max_value'] = fld.max_value
if fld.min_value:
f['min_value'] = fld.min_value
elif isinstance(fld, ChoiceField):
f['type'] = 'choice'
f['choices'] = [dict(value=c[0], display_name=c[1]) for c in fld.choices]
elif isinstance(fld, DateTimeField):
f['type'] = 'datetime'
return dict(
name=self.__class__.__qualname__,
description='',
renders=['application/json'],
parses=['application/json'],
actions=dict(PUT=flds)
)
It seems to do the trick

Django Model inheritance and access children based on category

I want to get the parent class values with each child values? How can I identify child objects to fetch?
I have the Django model structure like this.
class Category(models.Model):
name = models.CharField(max_length=80)
class Place(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)
category = models.ForeignKey('Category')
class PizzaRestaurant(Place):
serves_hot_dogs = models.BooleanField(default=False)
serves_pizza = models.BooleanField(default=False)
class PastaRestaurant(Place):
extra = models.CharField(max_length=80)
When we do operation we may save the object like below. And it saved into the db as i expected. two entry in the Place table and each entry in each child object table.
a = Category()
a.name = "pasta"
b = Category()
b.name = "pizza"
a.save()
b.save()
x = PastaRestaurant()
x.address = "Pasta Address"
x.name = "Pastamonia"
x.extra = "some extra"
x.category = a
y = PizzaRestaurant()
y.address = "Pizza Address"
y.name = "Dominos"
y.serves_hot_dogs = 1
y.serves_pizza = 0
y.category = b
x.save()
y.save()
Now I need to access the like this
p = Place.objects.get(id=1)
How can I know, which objects/attributes belongs to the place objects?
So when I fetch the place with common attributes and should be able get the corresponding child objects values also.
Or any other model design work for my need?
If you want to access the child model's attributes you need to fetch it as that model, i e PizzaRestaurant or PastaRestaurant, otherwise you will only get a Place object.
If you need to get all Places regardless of subclass take a look at InheritanceManager from django-model-utils. Using this you can implement overloaded operations to perform subclass-specific actions.
django-polymorphic does this beautifully, improving the abilities to work with model inheritance like so:
from polymorphic.models import PolymorphicModel
class Place(PolymorphicModel):
...
class PizzaRestaurant(Place):
...
class PastaRestaurant(Place:
...
>>> some_place = Place.objects.create(name="Walmart")
>>> some_pizza_place = PizzaRestaurant.objects.create(name="Slice King", address="101 Main St., Bismarck, ND", category = Category.objects.first(),serves_pizza=True)
>>> some_pizza_place.instance_of(PizzaPlace)
True
>>> PizzaRestaurant.objects.all()
queryset<['Slice King',]>
>>> Place.objects.all()
queryset<['Walmart', 'Slice King',]>