Reputation: 11493
I'm really at a loss because this makes no sense at all. I call save/create an object, and it dosn't show up in the admin site. I even checked the SQLite database with a SQLite Viewer program, which again showed that the item had not been saved.
This is the code that saves the Data
object:
data = Data(represents=field, for_entry=entry, value="This can be anything")
# field is a DataField db object and entry is a Entry db object (see model below and paragraph)
print("B4", data) #<---- Shows that Data has not been assigned an ID/pk
data.save()
print("8ER: ", data) #<--- Shows that Data has been assigned an ID/pk
As you can see from my comments, I know that the Data object is assigned an ID after the save
call, which I would think meant that it worked. No error is thrown anywhere. field
, and entry
are all both. Each one seems to be ok, as in they have the right IDs, were retrieved with [table name].objects.get(id=...)
, and I can save/edit them and their saves change.
Even strange, this exact code in a function that is called right before this one works.
This is my model.py (I took out some functions to make it shorter):
class Entry(models.Model):
parent = models.ForeignKey('Entry', blank = True, null = True, default=None) # The entry this subs. Is left blank for top level entries.
id_number = models.CharField(max_length=20)
visible = models.BooleanField()
data_field = models.ForeignKey('DataField', default=1) # The field that this entire entry falls under. REDUNDANT BUT NECISSARY
def __str__(self):
return str(self.id)+ "-" + str(self.id_number)
class DataField(models.Model):
parent = models.ForeignKey('DataField', related_name='parent field', null=True, blank=True, default=1)
order = models.IntegerField()
multiple_entries = models.BooleanField(default=True)
DATA_TYPES = (('t', 'Text'), ('d', 'Date'), ('l', 'List'), ('o', 'Option'), ('b', 'Boolean'), ('f', 'Foreign Key'), ('r', 'Root'), ('bb', 'Branch'), ('i', 'Image'), ('ff', 'File'), ('h', 'Holder'), ('bt', 'Big Text')) # A number means it is a foreign key. Should go off title.
foreign_source = models.ForeignKey('DataField', null=True, blank=True) # Points to DATA FIELD WHO'S MATCHING DATA WILL MAKE UP THE OPTIONS
data_type = models.CharField(max_length=2, choices=DATA_TYPES, default='t', null=True, blank=True)
title = models.CharField(max_length=100, null=True, blank=True)
visibility = models.BooleanField(default=False)
def __str__(self):
return str(self.id) + "-" + str(self.title)
def __eq__(self, other):
if not isinstance(other, DataField):
return False
if self.data_type == 'h':
return self.title == other.title
return self.id == other.id
class Data(models.Model):
represents = models.ForeignKey('DataField')
for_entry = models.ForeignKey('Entry', null=True)
value = models.CharField(max_length=1000000)
def __str__(self):
return self.represents.title + "-" + str(self.for_entry.id) + "-" + str(self.value) + "-" + str(self.id)
It's possible that I'm missing something obvious, or maybe you need way more information than I can provide to fix it. If there is not enough information, please comment and request more info, or just list possible issues that could be happening.
Upvotes: 10
Views: 16955
Reputation: 2106
I had the same issue. I solved it by assigned the object to a new variable, making my changes and saving the new variable:
location = self.location # self.location is set by other methods
location.is_active = True
location.save()
Upvotes: 4
Reputation: 11
Use django refresh_from_db()
function in the object you need to be updated.
Upvotes: 1
Reputation: 6572
I had a similar issue doing a unit test and encountered an error where it appeared the save method wasn't working --> was as follows
p = MyModel.objects.get(pk=myparam)
self.assertEqual(p.my_attr, value)
myfunc() # Code that changed the same object p is referencing
self.assertEqual(p.my_attr, new_value)
The above failed even though I changed the object being referenced to the new value and then did .save() on the object.
To fix the issue, I had to reassign p to the MyModel object. My fixed code in the unit test looked something like this.
p = MyModel.objects.get(pk=myparam)
self.assertEqual(p.my_attr, value)
myfunc() # Code that changed the same object p is referencing
p = MyModel.objects.get(pk=myparam)
self.assertEqual(p.my_attr, new_value)
It appears to be an issue with the variable pointing to an old location in memory, but I only started programming 5 months ago so I'm in a little over my head :) I would really appreciate feedback if anyone can explain why this is happening as I'm still stumped.
If you REALLY don't think the save method is executing, you can do a sanity check by overwriting the save method and add a print statement. It might look similar to the following:
class MyModel(models.Model):
attr = models.IntegerField(default=0)
def save(self, *args, **kwargs):
super(MyModel, self).save(*args, **kwargs)
print('Did this attribute update? (attr):', self.attr)
print('Save method executed!')
EDIT: Inline with the memory location theory, I made this simple example:
In [3]: a = 1
In [4]: b = a
In [5]: hex(id(a))
Out[5]: '0x100240280'
In [6]: hex(id(b))
Out[6]: '0x100240280'
In [7]: a = 2
In [8]: b
Out[8]: 1
In [9]: hex(id(a))
Out[9]: '0x1002402a0'
In [10]: hex(id(b))
Out[10]: '0x100240280'
Would still love to hear anyones thoughts.
Upvotes: 5
Reputation: 7631
Try a manual commit. I don't know what else to suggest.
from django.db import transaction
@transaction.commit_manually
def viewfunc(request):
...
data.save()
transaction.commit()
Upvotes: 3