Django: Not able to save to DB - python

I have the following view code:
def control_activation(request, device_id, variable_name, activated):
time_now = int(datetime.utcnow().strftime('%s'))
variable_qs = Variables.objects.filter(device_id=device_id, name=variable_name)
variable = variable_qs[0]
variable.activation = activated
variable.updated_at = time_now
variable.save()
coco_qs = GlobalUpdateTable.objects.all()
coco = coco_qs[0]
coco.variable_udated = time_now
coco.save
return HttpResponse()
For some reason I cannot understand the first save (variable.save) does what is intended but the second one (coco.save) does not.
If I use the following code, on the second part instead of the one above, I am able to save the value to the DB:
GlobalUpdateTable.objects.all().update(variable_updated=time_now)
Both codes should be able to update the column (variable_updated). The table GlobalUpdateTable only has one row, can that constitute a problem in any way?
For reference I indicate the models:
class Variables(models.Model):
name = models.CharField(max_length=20)
device_id = models.ForeignKey(Devices, to_field='id')
device_addr = models.CharField(max_length=6)
device_type = models.CharField(max_length=20)
response_tag = models.CharField(max_length=10)
command = models.CharField(max_length=6)
config_parameter = models.CharField(max_length=6)
unit = models.CharField(max_length=4)
direction = models.CharField(max_length=6)
period = models.IntegerField(null=True, blank=True, default=900)
activation = models.BooleanField(default=False)
formula = models.TextField(null=True, blank=True)
variable_uuid = models.CharField(max_length=36, primary_key=True)
mapping = models.TextField(null=True, blank=True)
updated_at = models.BigIntegerField(default=int(datetime.utcnow().strftime('%s')))
created_at = models.BigIntegerField(default=int(datetime.utcnow().strftime('%s')))
def __unicode__(self):
return unicode(self.device_id) + '_' + unicode(self.name)
class GlobalUpdateTable(models.Model):
device_updated = models.BigIntegerField(default=int(datetime.utcnow().strftime('%s')))
variable_updated = models.BigIntegerField(default=int(datetime.utcnow().strftime('%s')))

It seems you do coco.save instead of coco.save(). No error raised because you don't do anything wrong, but save method hasn't been called.

Related

Displaying sum of time by project by user using Django

I am a student new to programming. I am working on a project to create a timekeeping function. I want to be able to display the total time a user worked on a project. I have been able to display the total time for a user, and the total time for a project.
class User(models.Model):
class Project(models.Model):
title = models.CharField(max_length=255)
start_date = models.DateField()
end_date = models.DateField()
done = models.BooleanField(default=False)
created_by = models.ForeignKey(User, related_name ='made_by', on_delete=models.CASCADE)
projects_working_on = models.ManyToManyField(User, related_name = "projects_assigned_to")
class Timekeeper(models.Model):
clock_in = models.DateTimeField(null=True)
clock_out = models.DateTimeField(null=True)
total_time = models.DurationField(null=True, blank=True)
entire_time = models.FloatField(null=True)
is_working = models.BooleanField(default=False)
users_time = models.ForeignKey(User, related_name="time_of_user", on_delete=models.CASCADE)
proj_time = models.ForeignKey(Project, related_name = 'time_of_project', on_delete=models.CASCADE)
Here is is clockout function:
def clockout(request, proj_id):
user = User.objects.get(id=request.session['userid'])
now = datetime.now(timezone.utc)
this_proj = Project.objects.get(id = proj_id)
this_time = user.time_of_user.last()
time = this_time.users_time
this_time.clock_out = now
this_time.is_working = False
newtime = user.time_of_user.filter(proj_time=proj_id).aggregate(Sum('total_time'))
# this_time.total_time_two = newtime
this_time.save()
Timekeeper.objects.update(total_time=F('clock_out') - F('clock_in'))
Timekeeper.objects.update(entire_time=F('total_time'))
Timekeeper.objects.update(total_time_two=newtime)
# Timekeeper.objects.update(entire_time=user.time_of_user.filter(proj_time=proj_id).aggregate(Sum"(F('total_time')")
return redirect('/dashboard/view/'+str(proj_id))
The entire_time field exists solely for another function to iterate through and find the time of all of the fields for a particular user, or project. I can't seem to get a sum of the total_times (or entire_times) of 1 user for a particular project. Any help is greatly appreciated.
Responding to my own post, I found a workable solution: Not the most elegant though.
class Timekeeper(models.Model):
clock_in = models.TimeField(null=True)
clock_out = models.TimeField(null=True)
total_time = models.FloatField(null=True, blank=True)
entire_time = models.FloatField(null=True)
user_total_time = models.FloatField(null=True, blank=True)
user_project_total_time = models.FloatField(null=True, blank=True)
is_working = models.BooleanField(default=False)
users_time = models.ForeignKey(User, related_name="time_of_user", on_delete=models.CASCADE)
proj_time = models.ForeignKey(Project, related_name = 'time_of_project', on_delete=models.CASCADE)
In views.py
def clockout(request, proj_id):
user = User.objects.get(id=request.session['userid'])
this_time = user.time_of_user.last()
total_time_of_user = 0
total_time_of_user_project = 0
for i in user.time_of_user.all():
total_time_of_user += i.total_time
this_time.user_total_time = total_time_of_user
this_time.save()
for x in user.time_of_user.filter(proj_time=proj_id).all():
total_time_of_user_project += x.total_time
this_time.user_project_total_time = total_time_of_user_project
this_time.save()
This creates 2 new attributes to the Timekeeper model.

How to make a copy of a table before delete ( django pre_delete )

I'm new to Django so I guess my Question is basic but I need your help.
I have a table called Answer.
class Answer(models.Model):
id = models.AutoField(auto_created=True,primary_key=True)
sku = models.CharField(max_length=128, default=secrets.token_urlsafe(16), editable=False)
user = models.ForeignKey(User,on_delete=models.SET_NULL, null= True)
topic = models.ForeignKey(Topic,on_delete=models.SET_NULL, null=True)
content = models.TextField()
created = models.DateTimeField(auto_now_add = True)
updated = models.DateTimeField(auto_now = True)
it's for a forum.
Before a user deletes his/her answer, I want to make a copy of the answer. I want to make a new table that has the values of this table, for example, a table named DeletedAnswer that has all the values in Answer table.
thanks
Update :
I did it with pre_delete, here is what I did :
created a new model named DeleteAnswer:
class DeleteAnswer(models.Model):
id = models.AutoField(auto_created=True,primary_key=True)
sku = models.CharField(max_length=128, default=secrets.token_urlsafe(16), editable=False)
user = models.ForeignKey(User,on_delete=models.CASCADE)
topic = models.ForeignKey(Topic,on_delete=models.SET_NULL,null=True)
content = models.TextField()
delete_date = models.DateTimeField(auto_now_add=True)
created = models.DateTimeField()
and then I did it with signals and pre_delete :
#receiver(pre_delete,sender=Answer)
def delete_answer(sender, instance, **kwargs):
d = DeleteAnswer()
d.sku = instance.sku
d.content = instance.content
d.topic = instance.topic
d.user = instance.user
d.created = instance.created
d.delete_date = datetime.datetime.now()
d.save()

Using getattrs() to access Foregin Key values

I am using a basic form in Django to collect a users choices which will be used to create a filter of objects and then output to csv. I would like to use the values from the form to access data in the different models.
My form looks like this..
class CustomReportForm(forms.Form):
CHOICES=[('Asset Labels','Asset Labels'),
('Asset List','Asset List')]
REPORT_FIELDS = [('id','ID'),
('name','Name'),
('location','Location'),
('status','Status'),
]
type = forms.ChoiceField(choices=CHOICES)
col_choices = forms.MultipleChoiceField(choices=REPORT_FIELDS, widget=forms.CheckboxSelectMultiple)
location = forms.ModelChoiceField(AssetLocation.objects.all(), required=False)
status = forms.ModelChoiceField(AssetStatus.objects.all(), required=False)
I have 2 models included in the form 'AssetLocation' and 'AssetStatus'.
class AssetLocation(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
company = models.ForeignKey(Company, on_delete=models.CASCADE)
location = models.CharField(max_length=20)
location_code = models.CharField(max_length=10, blank=True)
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
def __str__(self):
return str(self.company) + " - " + self.location
class AssetStatus(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
company = models.ForeignKey(Company, on_delete=models.CASCADE)
status = models.CharField(max_length=20)
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
def __str__(self):
return str(self.company) + " - " + self.status
I also have an Asset model
class Asset(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
company = models.ForeignKey(Company, on_delete=models.CASCADE)
location = models.ForeignKey(AssetLocation, on_delete=models.CASCADE)
status = models.ForeignKey(AssetStatus, on_delete=models.CASCADE)
name = models.CharField(max_length=40)
def __str__(self):
return str(self.company) + " - " + self.name
And I have a view which accesses the POST data and tries to use that to get data.
def AssetList(request):
assets = Asset.objects.all()
cols = request.POST.getlist('col_choices')
for a in assets:
data = []
for i in cols:
data.append(getattr(a,i))
print(data)
This works as expected. I am getting the location and status of each asset but its returning the def str of AssetLocation and AssetStatus.
I would like to access AssetLocation.location and AssetStatus.status.
I have tried to modify the form choices to this but it generates a 'Asset' object has no attribute 'location.location' error
REPORT_FIELDS = [('id','ID'),
('name','Name'),
('location.location','Location'),
('status.status','Status'),
]
How can I access foreign key values with the getattr() function?
thanks
James
You'll have to be cleverer in your view code. You could try splitting on '.':
for a in assets:
data = []
for i in cols:
if '.' in col:
fk, field = col.split('.')
val = getattr(getattr(a, fk), field)
else:
val = getattr(a,i)
data.append(val)
Of course, this will break if you have more than one level of relationship.

How to check the details of foreignkey before creating object in the form?

In the Django project I'm working on there is model called Course and it contains many Assignment objects.
This is a part of models.py:
class Assignment(models.Model):
course = models.ForeignKey(Course, related_name='get_assignments')
name = models.CharField(max_length=200)
ipaddress = models.CharField(null=True, max_length=500)
publish_type = models.CharField(max_length=50, default="Scheduled")
type_of_lab = models.CharField(max_length=50, default="Lab")
timeduration = models.DurationField(default=timedelta(seconds=0), null=True)
late_duration = models.DurationField(default=timedelta(seconds=0), null=True)
exam_group_id = models.CharField(max_length=50, null=True)
serial_number = models.IntegerField()
program_language = models.CharField(max_length=32)
duration = models.DurationField(default=timedelta(seconds=0), null=True)
freezing_duration = models.DurationField(default=timedelta(seconds=0), null=True)
deadline = models.DateTimeField(null=True)
freezing_deadline = models.DateTimeField(null=True)
publish_on = models.DateTimeField(null='true')
bulk_add = models.FileField(max_length = 800,upload_to=assignment_bulk_upload_path, null=True)
When creating an assignment through form, the form is validated using some functions. This is part of forms.py:
class AssignmentForm(forms.Form):
assignment_type = forms.BooleanField(required=False, widget=forms.HiddenInput())
name = forms.CharField(label="Assignment Name", widget=forms.TextInput(attrs={'placeholder':'Assignment Name (200 Characters or fewer)','maxlength':200}))
Typeof = (('Lab', 'Lab'), ('Exam', 'Exam'))
publishtype = (('Scheduled', 'Scheduled'), ('On Demand', 'On Demand'))
publish_type = forms.ChoiceField(
choices=publishtype,
label="Choose type of Publish (Default : Scheduled)"
)
duration = forms.DurationField(
label="Assignment Duration",
required=False,
help_text="Assignment Duration, input format is HH:MM:SS "
)
freezing_duration = forms.DurationField(
label="Freezing extra time",
required=False,
help_text="Extra time for students to freeze submission, input format is HH:MM:SS "
)
bulk_add = forms.FileField(
error_messages={'invalid': 'File was not a valid tar file.'},
required=False,
label="Add sections and/or test cases in bulk",
)
#
#
# some more code
#
#
def clean_bulk_add(self):
assig1 = self.cleaned_data['name']
course1 = self.this_course
user1 = course1.owner
tot1 = 30 + len(str(user1)) + len(str(course1.title)) + len(str(assig1)) + len(str(self.cleaned_data['bulk_add']))
if tot1 > 700 :
raise forms.ValidationError("Assignment or Course name is too long: "+str(tot1))
return self.cleaned_data['bulk_add']
def clean_name(self):
if not hasattr(self, 'this_course'):
return self.cleaned_data['name']
try:
_ =Assignment.objects.filter(trash=False).get(name=self.cleaned_data['name'], course=self.this_course)
raise forms.ValidationError('This assignment already exists in this course.')
except Assignment.DoesNotExist:
pass
return self.cleaned_data['name']
As you can see while validating AssignmentForm I want to use the name of course in which it is created. So in function clean_bulk_add, I've written course1 = self.this_course.
Then it is showing AttributeError 'AssignmentForm' object has no attribute 'this_course'. So, how to get the name of course in which it the Assignment is going to be created?

how to select columns from multiple models in django?

models.py
class Custom_user_model(User):
daily_target = models.IntegerField()
monthly_target = models.IntegerField()
yearly_target = models.IntegerField()
weekly_target = models.IntegerField()
call_target = models.IntegerField()
email_target = models.IntegerField()
meeting_target = models.IntegerField()
added_under = models.IntegerField()
profile_pic = models.TextField()
doj = models.DateTimeField(default='')
location_id = models.IntegerField()
locked = models.BooleanField()
default_currency = models.IntegerField()
date_change_permission = models.BooleanField()
deal_back_log = models.BooleanField()
created_date=models.DateTimeField(auto_now_add=True)
role_id=models.ForeignKey('user_Roles')
profile_pic = models.FileField(upload_to='.')
objects = UserManager()
class Deal(models.Model):
a_choices = ((0,'yes'),(1,'no'))
approved = models.IntegerField(choices=a_choices,default=1)
user_id = models.ForeignKey('Custom_user_model')
company_id = models.IntegerField()
contact_id = models.IntegerField()
deal_title=models.CharField(max_length=200)
deal_value = models.CharField(max_length=20)
currency_id = models.IntegerField()
process_id = models.IntegerField()
expected_close_date = models.DateField(default='')
closed_date = models.DateField()
deal_milestone=models.IntegerField()
created=models.DateTimeField(auto_now_add=True)
last_modified=models.DateTimeField(auto_now_add=True)
s_choices = ((0,'active'),(1,'won'),(2,'junk'),(3,'lost'))
status = models.IntegerField(choices=a_choices,default=0)
type = models.CharField(max_length=50, default='deal')
class user_Roles(models.Model):
code = models.CharField(max_length=20)
description = models.CharField(max_length=30)
permitted_menus = models.CharField(max_length=200)
created = models.DateTimeField(auto_now_add=True)
views.py
Here, i wrote the code to get columns from three models. But
Deal.objects.filter(user_id__role_id_id=1).select_related() returned nothing and Deal.objects.filter(user_id__role_id_id=1).select_related().values() returned the fields from deal model only. It shows 'no fields error', when specifying relationship as values('Custom_user_model__doj').How can i select fields from multiple models?
def get_all_normal_users(request,start_date=None,end_date=None):
query = Deal.objects.filter(user_id__role_id_id=1).select_related().values()
start_date_range = (
# The start_date with the minimum possible time
datetime.datetime.combine(start_date, datetime.time.min),
# The start_date with the maximum possible time
datetime.datetime.combine(end_date, datetime.time.max)
)
query = query.filter(created__range=start_date_range).values()
data_dict = ValuesQuerySetToDict(query)
data_json = json.dumps(data_dict)
return json_response({'status':data_json})
If you want to select related values you have to specify all parameters you want in values(). Otherwise you will get only the foreignkey to your user model. Try adding the values you want from your user model with __:
query = query.filter(created__range=start_date_range).values('approved', ..., 'user_id__daily_target', 'user_id__username')
Btw if you are creating an API you should have a look at django-rest-framework
try this,
Deal.objects.filter(user_id__role_id_id=1, created__range=start_date_range).select_related('user_id').values()
or specify required fields as parameters to values().

Categories

Resources