Django form Data - django

Please I gotta a model I created with three fields input1,input2,total. So I generated a model form so that if I input the values of input 1 and input2 it will automatically multiply the the inputted values. Then on calling the save method it will save the inputted values and computed value to the database

Try this:
class Multiply(models.Model):
input1 = models.IntegerField()
input2 = models.IntegerField()
result = models.IntegerField(null=True, blank=True)
def __str__(self):
return str(self.input1) + " * " + str(self.input2) + " = " + str(self.result)
def save(self, *args, **kwargs):
self.result = self.input1 * self.input2
super().save(*args, **kwargs)

Related

Set initial values in form passing parameters (kwargs) with view

I want to prefill a form with values taken in a table.
First I pass the PK relative to the line where I wan't to get values and build the kwargs list:
views.py
def NavetteToFicheCreateView(request, pk):
navette = Navette.objects.get(id=pk)
ref = navette.id
attribute_set = navette.famille.pk
cost = navette.cost
qty = navette.qty
etat = navette.etat
etat_ebay = navette.etat.etat_ebay
ean = get_last_ean()
form = NavetteToFicheForm(
request.POST,
ref=ref,
attribute_set=attribute_set,
cost=cost,
qty=qty,
etat=etat,
etat_ebay=etat_ebay,
ean=ean,
)
[...]
then I retrieve the kwargs in the form.py and setup my initial values
class NavetteToFicheForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.ref = kwargs.pop('ref', 'noref')
self.attribute_set = kwargs.pop('attribute_set', 9999)
self.cost = kwargs.pop('cost', 0)
self.qty = kwargs.pop('qty', 0)
self.etat = kwargs.pop('etat', 0)
self.etat_ebay = kwargs.pop('etat_ebay', 9999)
self.ean = kwargs.pop('ean', 9999)
super(NavetteToFicheForm, self).__init__(*args, **kwargs)
self.fields['ref'].initial = self.ref
self.fields['attribute_set'].initial = self.attribute_set
self.fields['cost'].initial = self.cost
self.fields['qty'].initial = self.qty
self.fields['etat'].initial = self.etat
self.fields['etat_ebay'].initial = self.etat_ebay
self.fields['ean'].initial = self.ean
[...]
My problem : some fields like "ref" or "attribute_set" are foreignKeys and are not transmitted when i display the form.
For checking my values :
print(self.ref)
print(self.attribute_set)
output
34
2
noref
9999
questions :
Why does the "print" displays 2 couples of values ? This looks like as if the "noref" and "999" are taken in account.
Why if i set manually 34 and 2 values, it works ?
self.fields['ref'].initial = 34
self.fields['attribute_set'].initial = 2
There's maybe a better way of doing this but I don't know it yet .

How do I use data stored in django model in a calculation and then store the result of a calculation in a django model field?

I'm working on my first Django app, and I need to take the data inputted by a user in my models fields, insert it into a function that makes a calculation using that data, and then returns the value of that calculation to my model where it is then stored.
It is not essential that the result be stored in my database, however I will need to use the resulting figure later on to allow the app to determine which data to present to the user.
I have my model class in models.py:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
age = models.IntegerField(default=18)
gender = models.CharField(max_length=6, choices=gend, default='')
weight = models.IntegerField(default=0)
height = models.IntegerField(default=0)
and my function in a services.py file:
def caloriefunction():
weight = Profile.weight
height = Profile.height
age = Profile.age
isMale = Profile.gender
if isMale == "Male":
isMale = True
elif isMale == "Female":
isMale = False
else:
print("Error")
quit()
if isMale:
bmr = 66.5 + (13.75 * weight) + (5 * height) - (6.755 * age)
else:
bmr = 655.1 + (9.6 * weight) + (1.8 * height) - (4.7 * age)
bmr = round(bmr)
return bmr
How would I get the resulting value and then store it in my database or keep it to use in another piece of logic?
Would I be better off using the function in the class as a method?
Sorry if the question isn't being asked very well i'm quite a newbie.
Any help if appreciated!
Yes, you can add that as a method of Profile. And/or if you want to keep the result handy you could add another field to the profile model, and override the save method so it is recalculated whenever an instance is saved. Something like this:
def save(self, *args, **kwargs):
self.update_bmr()
super().save(*args, **kwargs)
def update_bmr(self):
if self.gender == "Male":
self.bmr = (
66.5
+ (13.75 * self.weight)
+ (5 * self.height)
- (6.755 * self.age)
)
elif self.gender == "Female":
self.bmr = (
655.1
+ (9.6 * self.weight)
+ (1.8 * self.height)
- (4.7 * self.age)
)
else:
self.bmr = None
You may need to guard against missing data.

How to perform multiplication in django model?

This is my model:
class Purchase(models.Model):
Quantity = models.PositiveIntegerField()
rate = models.DecimalField(max_digits=5,decimal_places=2)
Amount = models.DecimalField(max_digits=5,decimal_places=2)
I want to perform multiplication between Quantity and rate and store the result in Amount...
So I have done something like this:
from django.db.models import F
#receiver(pre_save, sender=Purchase)
def update_amount(sender,instance,*args,**kwargs):
totalamount = Purchase.objects.get(F('rate') * F('Quantity'))
instance.Amount = totalamount
But its giving me this error:
'CombinedExpression' object is not iterable
Do anyone have any idea how to do this???
But here you already have the instance, so the totalamount is simply:
#receiver(pre_save, sender=Purchase)
def update_amount(sender, instance, *args, **kwargs):
instance.Amount = instance.rate * instance.Quantity
That being said, if the Amount is always the rate multiplied with the Quantity, it is better to define a #property, since then you avoid data duplication, like:
class Purchase(models.Model):
Quantity = models.PositiveIntegerField()
rate = models.DecimalField(max_digits=5,decimal_places=2)
def amount(self):
return self.Quantity * self.rate

How to get currently selected choice from CharField in Django?

I'm trying to get the currently selected choice from the CharField and use it in str method like this:
class Foo(models.Model):
measurement_value = models.FloatField(max_length=200)
CHOICES = (('a', 'Alpha'), ('b', 'Beta'))
choice = models.CharField(max_length=5, choices=CHOICES, default='a')
def __str__(self):
"""String representation for the foo object."""
return str(self.measurement_value) + " " + self.choice
So for example, if I'd like to add object foo with measurement 10.5 and choice 'a' (Alpha), str would return this: "10.5 Alpha"
Currently, the code that I provided returns this: "10.5 a".
You can get the human readable choice name by using instance method get_{}_display
your example
def __str__(self):
return str(self.measurement_value) + " " + self.get_choices_display()

Django Custom Model Field with Validation...how to hook it back to ModelForm

A common occurrence I have with one particular project is that it requires the user to enter dimensions (for width/depth/height) in Feet and Inches. Calculations are needed to be performed on that dimension, so I've been working on a custom field type that takes in a dimension in Feet/Inches (eg. 1'-10") and saves it to the database as a decimal number using a regex to parse the input. The field displays to the end-user as feet-inches at all times (with the eventual goal of writing a
method to be able to optionally display in metric, and interact with measure.py, and geodjango stuff). What I have so far is definitely not DRY, but aside from that, I'm having trouble with validation at the form level. The custom model field itself works properly (from what I've seen), and I've written a form field clean method which should work to validate the field. My question is how to hook that form field back into my model form to work for all the width/depth/height fields.
I'm thinking maybe an override of the init on the modelform (a la self.fields['depth']...) , but I'm not quite sure where to go from here...
DCML_PATTERN = re.compile(r'^(?P<feet>\d+)(?P<dec_inch>\.?\d*)\'?$')
FTIN_PATTERN = re.compile(r'^(?P<feet>\d+)\'?\s*-?\s*(?P<inch>[0-9]|10|11)?\"?$')
class FtInField(models.Field):
__metaclass__ = models.SubfieldBase
empty_strings_allowed = False
def db_type(self):
return 'double'
def get_internal_type(self):
return "FtInField"
def to_python(self,value):
if value is u'' or value is None:
return None
if isinstance(value, float):
m = FTDCML_PATTERN.match(str(value))
if m is None:
raise Exception('Must be an integer or decimal number')
feet = int(m.group('feet'))
dec_inch = float(m.group('dec_inch') or 0)
inch = dec_inch * 12
return "%d\'-%.0f\"" % (feet,inch)
return value
def get_db_prep_value(self,value):
if value is u'' or value is None:
return None
m = FTIN_PATTERN.match(value)
if m is None:
raise Exception('Must be in X\'-Y" Format')
feet = int(m.group('feet'))
inch = int(m.group('inch') or 0)
return (feet + (inch/float(12)))
class FtInField(forms.Field):
def clean(self,value):
super(FtInField, self).clean(value)
if value is u'' or value is None:
raise forms.ValidationError('Enter a dimension in X\'-Y" format')
m = FTIN_PATTERN.match(value)
if m is None:
raise forms.ValidationError('Must be in X\'-Y" Format')
feet = int(m.group('feet'))
inch = int(m.group('inch') or 0)
value = '%d\'-%.0f"' % (feet,inch)
return value
class ProductClass(models.Model):
productname = models.CharField('Product Name', max_length=60,blank=True)
depth = FtInField('Depth (Feet/Inches)')
width = FtInField('Width (Feet/Inches)')
height = FtInField('Height (Feet/Inches)')
class ProductClassForm(forms.ModelForm):
depth = FtInField()
width = FtInField()
height = FtInField()
class Meta:
model = ProductClass
class ProductClassAdmin(admin.ModelAdmin):
form = ProductClassForm
Thank you, thank you to both of you. This is what I came up with (based on both of your advise). I'll work on defining a data type to make it better in terms of repetition, but in the meantime, this works...(I was so close, yet so far away...) You guys are amazing. Thanks.
DCML_PATTERN = re.compile(r'^(?P<feet>\d+)(?P<dec_inch>\.?\d*)\'?$')
FTIN_PATTERN = re.compile(r'^(?P<feet>\d+)\'?\s*-?\s*(?P<inch>[0-9]|10|11)?\"?$')
class FtInFormField(forms.Field):
def clean(self,value):
super(FtInFormField, self).clean(value)
if value is u'' or value is None:
raise forms.ValidationError('Enter a dimension in X\'-Y" format')
m = FTIN_PATTERN.match(value)
if m is None:
raise forms.ValidationError('Must be in X\'-Y" Format')
feet = int(m.group('feet'))
inch = int(m.group('inch') or 0)
value = '%d\'-%.0f"' % (feet,inch)
return value
class FtInField(models.Field):
__metaclass__ = models.SubfieldBase
empty_strings_allowed = False
def db_type(self):
return 'double'
def get_internal_type(self):
return "FtInField"
def to_python(self,value):
if value is u'' or value is None:
return None
if isinstance(value, float):
m = FTDCML_PATTERN.match(str(value))
if m is None:
raise Exception('Must be an integer or decimal number')
feet = int(m.group('feet'))
dec_inch = float(m.group('dec_inch') or 0)
inch = dec_inch * 12
return "%d\'-%.0f\"" % (feet,inch)
return value
def get_db_prep_value(self,value):
if value is u'' or value is None:
return None
m = FTIN_PATTERN.match(value)
if m is None:
raise Exception('Must be in X\'-Y" Format')
feet = int(m.group('feet'))
inch = int(m.group('inch') or 0)
return (feet + (inch/float(12)))
def formfield(self, **kwargs):
defaults = {'form_class': FtInFormField}
defaults.update(kwargs)
return super(FtInField,self).formfield(**defaults)
class ProductClass(models.Model):
productname = models.CharField('Product Name', max_length=60,blank=True)
depth = FtInField('Depth (Feet/Inches)')
width = FtInField('Width (Feet/Inches)')
height = FtInField('Height (Feet/Inches)')
class ProductClassForm(forms.ModelForm):
class Meta:
model = ProductClass
class ProductClassAdmin(admin.ModelAdmin):
form = ProductClassForm
To avoid duplication you should probably implement a data type class that handles the parsing of feets and inches for you, it should greatly simplify the other code.
Then you should create a model field and form field, keeping in mind that these are two COMPLETELY SEPARATE components. (which you more or less have already done, but this is just for completeness)
Now, if I'm reading the question right, you want to set the default form field for your model field. To facilitate this you want to implement the formfield() function on your model field class. Ref: the django docs