Django query update - the field is determined by a string - django

I want to update a record, but the field is determined by string. Is it possible to do so?
This is my model:
class Wallet(models.Model):
user_id = models.IntegerField(blank=True, null=True)
wallet1 = models.DecimalField(max_digits=15, decimal_places=2, blank=True, null=True)
wallet2 = models.DecimalField(max_digits=15, decimal_places=2, blank=True, null=True)
This is my code:
amount = 200
transfer_from = 'wallet1'
transfer_to = 'wallet2'
obj = Wallet.objects.get(user_id=1)
obj.transfer_from = obj.transfer_from - amount
obj.transfer_to = obj.transfer_to + amount
obj.save()
Django only recognize the field when i write this:
obj.wallet1 = obj.wallet1 - amount
but it doesn't recognize this:
transfer_from = 'wallet1'
obj.transfer_from = obj.transfer_from - amount
Is said 'Wallet' object has no attribute 'transfer_from'. Thank you.

This is not tested but should work.
amount = 200
transfer_from = 'wallet1'
transfer_to = 'wallet2'
obj = Wallet.objects.get(user_id=1)
transfer_from_field_val = getattr(obj,transfer_from)
transfer_to_field_val = getattr(obj,transfer_to)
transfer_from_field_val = transfer_from_field_val - amount
transfer_to_field_val = transfer_to_field_val + amount
setattr(obj , transfer_from, transfer_from_field_val)
setattr(obj , transfer_to, transfer_to_field_val)
obj.save()

Actually this is a Python question.
Please refer to this: What is getattr() exactly and how do I use it?
Using getattr, here is what you could do:
transfer_from_label = 'wallet1'
transfer_from = getattr(obj, transfer_from_label)
transfer_from = transfer_from - amount

setattr(obj, transfer_form, getattr(obj, transfer_form) - amount)
getattr, setattr.

Related

How to calculate numbers of days between two dates and subtract weekends DJANGO MODELS

hope you're all fine!
I have a model called Vacation and I'm struggling with one field: days_requested, this field is the number days from vacation_start and vacation_end, it works and gives me an integer as result. The problem I'm facing now is that I need to subtract the weekends (or not count them).
What I have:
vacation_start = '2022-05-20'
vacation_end = '2022-05-24'
days_requested = 5
What I'm trying to have:
vacation_start = '2022-05-20'
vacation_end = '2022-05-24'
days_requested = 3
#21/05 and 22/05 are weekends
Vacation Models:
class Vacation(models.Model):
department = models.ForeignKey(
'departments.Department', on_delete=models.SET_NULL, null=True)
responsible = models.ForeignKey(
User, on_delete=models.SET_NULL, null=True, related_name='responsible_vacation')
status = models.CharField(
max_length=20, choices=STATUS_CHOICES_VACATIONS, default='open')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
created_by = models.ForeignKey(
User, on_delete=models.SET_NULL, null=True, related_name='created_by_vacation')
vacation_start = models.DateField(blank=False)
vacation_end = models.DateField(blank=False)
days_requested = property(
lambda self: (self.vacation_end - self.vacation_start).days + 1
)
def __str__(self):
return str(self.created_by.first_name + ' ' + self.created_by.last_name)
I have tried:
days_requested = property(
lambda self: [(self.vacation_start + datetime.timedelta(days=i)).date()
for i in range(0, (self.vacation_end - self.vacation_start)) if (self.vacation_start + datetime.timedelta(days=i)).weekday() not in [5, 6].days()])
But I get the following error:
'datetime.timedelta' object cannot be interpreted as an integer
And as I perform operations with the amount of days asked I need to be able to get an integer.
Thank you all in advance.
UPDATE
class Model:
days_requested = models.IntegerField(blank=True,null=True)
def save(self, *args, **kwargs):
excluded = (6, 7)
days = 0
start_date =self.vacation_start
while start_date < self.vacation_end:
if start_date.isoweekday() not in excluded: #if you want to get only weekdays
days += 1
start_date+= timedelta(days=1)
self.days_requested=days
super(YourModel, self).save(*args, **kwargs)
After Elvin's answer I moved the hole logic to my view and set the logic inside form_valid function:
start = form.instance.vacation_start
end = form.instance.vacation_end
delta = end - start
excluded = (6, 7)
days = 0
for i in range(delta.days + 1):
day = start + datetime.timedelta(days=i)
if day.isoweekday() not in excluded:
days += 1
form.instance.days_requested = days
Thank you all.

get value in table manytomany django

hi I am trying to get the same value in a many to many tables but I don't know how can I achieve that
here is my model:
class Raza(models.Model):
Nombre = models.CharField(max_length=50)
Origen = models.CharField(max_length=45)
Altura = models.CharField(max_length=10)
Peso = models.CharField(max_length=10)
Esperanza_vida = models.CharField(max_length=10)
Actividad_fisica = models.CharField(max_length=45)
Recomendaciones = models.CharField(max_length=500)
Clasificacion_FCI = models.ForeignKey(Clasificacion_FCI,null=True,blank=True,on_delete=models.CASCADE)
Tipo_pelo = models.ManyToManyField(Tipo_pelo,blank=True)
Caracteristicas_fisicas = models.ManyToManyField(Caracteristicas_fisicas,blank=True)
Caracter = models.ManyToManyField(Caracter,blank=True)
Ideal = models.ManyToManyField(Ideal,blank=True)
Tamanio = models.ForeignKey(Tamanio,null=True,blank=True,on_delete=models.CASCADE)
User = models.ManyToManyField(User,blank=True)
I am using the User model that's provided by Django
I have no idea how can I do that
I want do something like that
table user
id_usuario = 1
name = "Juan"
table raza
id_raza = 1
name = "pitbull"
table user_raza
id_user_raza = 1
id_user = 1
id_raza = 1
Please write class attributes with small letters in python.
to your question:
raza = Raza.objects.get(id=1)
tipo_pelos = raza.tipo_pelo.all()
for tp in tipo_pelos:
print(tp.id)
...
...
Django has wonderful documentation for this. Have fun.

Django Update Multiple Object error

i found some problem when i try to update multiple object in my models. here is my models:
class NumberSequence(models.Model):
code = models.CharField(max_length=12)
name = models.CharField(max_length=60)
prefix = models.CharField(max_length=3)
length = models.IntegerField()
last = models.IntegerField(verbose_name='Last Number Used')
def getNumberSequence():
ns = NumberSequence.objects.filter(code='REQ')
letter = ns[0].prefix
lastNumber = ns[0].last+1
l = '{0}-{1:0'+str(ns[0].length)+'d}'
for num in ns:
num.last = lastNumber
num.save()
return l.format(letter,lastNumber+1)
class Requisitions(models.Model):
number = models.CharField(max_length=20, default=getNumberSequence())
transDate = models.DateField(verbose_name='Date')
businessUnit = models.ForeignKey(BusinessUnit, verbose_name='Unit')
division = models.ForeignKey(Division, verbose_name='Division')
remarks = models.TextField
status = models.IntegerField(verbose_name='Status')
when i create new record in Requisition, the table Number Sequence does not update. but if i restart the service, the number sequence table updated automatically.
what's happened with my code?
any suggestion, please..
You should not call the default function in your field definition, but pass the callable only without parentheses.
number = models.CharField(max_length=20, default=getNumberSequence)

Django queryset search on multiple models, return the same object

I'm trying to create an advanced search on my website, you are looking at various models related to each one, always returning a list of profiles that meet some parameters
Here are my Models:
class Profile(models.Model):
first_name=models.CharField(max_length=60, blank=False)
last_name=models.CharField(max_length=60, blank=False)
residence=models.CharField(max_length=60, null=True, blank=True)
birthdate=models.DateField(null=True, blank=True)
telephone=models.CharField(max_length=60, null=True, blank=True)
email=models.EmailField(null=True, blank=True)
linkedin=models.URLField(null=True, blank=True)
starred=models.BooleanField(default=False)
created_from = models.ForeignKey(EmployeeUser, related_name='profile_author')
created_on = models.DateField(default=tznow)
internal_id = models.CharField(max_length=5, blank=True)
class Education(models.Model):
almalaurea_id = models.CharField(max_length=60, null=True, blank=True)
profile = models.ForeignKey(Profile, related_name='education_profile')
education_type = models.ForeignKey(Education_type, related_name='education_type')
class Education_type(models.Model):
VALUES = (
(0, 'Altro'),
(1, 'Licenza media'),
(2, 'Diploma'),
(3, 'Laurea Triennale'),
(4, 'Laurea Magistrale'),
)
title = models.CharField(max_length=60)
value = models.IntegerField(choices=VALUES)
I want to search the profiles that meet various results, such as birthdate, residence, starred, education (based on education_type)
This is an example scenario, my research includes other models
These are the research in my view, I thought that having found the results of the two queries, I could extract the profile id and compare them, then run another query by selecting profiles that match, but I think it's not a great idea, the real scenario includes other various models.
filters_profile = []
filters_education = []
year = form.cleaned_data["year"]
residence = form.cleaned_data["residence"]
starred = form.cleaned_data["starred"]
education_type = form.cleaned_data["education_type"]
if year:
filters_profile.append(Q(birthdate__year=year))
if residence:
filters_profile.append(Q(residence__icontains=residence))
if starred:
filters_profile.append(Q(starred=starred))
result_profile = Profile.objects.filter(reduce(lambda q1, q2: q1 & q2, filters_profile)).order_by('first_name')
result_education = None
if education_type:
e = Education_type.objects.filter(title=education_type)
result_education = Education.objects.filter(education_type=e).prefetch_related('profile','education_type')
Any idea?
Many thanks in advance :)
EDIT :
About the solution of #Geo Jacob
Here is the third models:
if valutation:
result_valutation = Status.objects.filter(valutation=valutation).values_list('profile_id', flat=True)
key['id__in'] = result_valutation
Adding this code for my scenario, this solution don't work, as i written in the comments :)
"in practice, the content of key['id__in'] is overwritten when the other model query (this) is executed"
Try this:
key = {}
year = form.cleaned_data["year"]
residence = form.cleaned_data["residence"]
starred = form.cleaned_data["starred"]
education_type = form.cleaned_data["education_type"]
if year:
key['birthdate__year'] = year
if residence:
key['residence__icontains'] = residence
if starred:
key['starred'] = starred
if education_type:
e = Education_type.objects.filter(title=education_type)
result_education = Education.objects.filter(education_type=e).values_list('profile_id', flat=True)
key['id__in'] = result_education
result_profile = Profile.objects.filter(**key).order_by('first_name')
My solution working on more than 2 models, based on #Geo Jacob solution, thank you
I make a check and put in key['id__in'] only matched id from the previous query, so as to intersect the results
key = {}
statokey = 0
year = form.cleaned_data["year"]
residence = form.cleaned_data["residence"]
starred = form.cleaned_data["starred"]
education_type = form.cleaned_data["education_type"]
valutation = form.cleaned_data["valutation"]
if year:
key['birthdate__year'] = year
if residence:
key['residence__icontains'] = residence
if starred:
key['starred'] = starred
if education_type:
e = Education_type.objects.filter(title=education_type)
result_education = Education.objects.filter(education_type=e).values_list('profile_id', flat=True)
if statokey > 0:
for r in result_education:
for k in key['id__in']:
if r == k:
key['id__in'] = str(r)
else:
key['id__in'] = result_education
statokey += 1
if valutation:
result_valutation = Status.objects.filter(valutation=valutation).values_list('profile_id', flat=True)
if statokey > 0:
for r in result_valutation:
for k in key['id__in']:
if r == k:
key['id__in'] = str(r)
else:
key['id__in'] = result_valutation
statokey += 1
result_profile = Profile.objects.filter(**key).order_by('first_name')

Django model field relating to a few models

Imagine a 5x5 grid (map), every field of it represents a certain object (it can be a monster, a tree etc.)
So, here we have:
class Field(Model):
x = y = PositiveIntegerField()
content = ...(?)
Here the problem arises. Here is the alternative, but I think this way is too messy, especially if I have many different content ids.
class Field(Model):
x = y = PositiveIntegerField()
content = PositiveIntegerField()
monster_rel = ForeignKey(Monster, null=True, blank=True)
building_rel = ForeignKey(Monster, null=True, blank=True)
nature_obj_rel = ForeignKey(Monster, null=True, blank=True)
and then in a view:
f = Field.objects.get(pk=1)
if f.content == 1:
print "Monster %s of level %d" % (f.monster_rel.name, f.monster_rel.level)
elif f.content == 2:
print "This is a %s" % f.building_rel.type
...
Is there a better solution for this?
EDIT
I would like fields like:
content_id = IntegerField()
content_rel = FieldRelatedToModelByContentId()
Well, sounds like generic relations is exactly what you're looking for.