21

Is it possible to override values inside a Model? I am getting 'MyModel' object does not support item assignment.

my_model = MyModel.objects.get(id=1)
print my_model.title

if my_model.is_changed:
    my_model['title'] = 'something' # 'MyModel' object does not support item assignment

params = {
        'my_model': my_model,
         ...
    }
return render(request, 'template.html', params)
Pompeyo
  • 1,459
  • 3
  • 18
  • 42

4 Answers4

43

Models are objects, not dictionaries. Set attributes on them directly:

if my_model.is_changed:
    my_model.title = 'something'

Or, if the attribute name is dynamic, use setattr:

attr_name = 'title' # in practice this would be more complex
if my_model.is_changed:
    setattr(my_model, attr_name, 'something')

This changes the in-memory copy of the model, but makes no database changes - for that your attribute would have to be a field and you'd have the call the save method on my_model. You don't need to do that if you just want to change what the template receives in its context, but just for completeness's sake:

if my_model.is_changed:
    my_model.title = 'something'
    my_model.save()

Dictionaries are mutable, if you actually have a dictionary:

mydict = {'title': 'foo'}
# legal
mydict['title'] = 'something'

But not everything is a dictionary.

Peter DeGlopper
  • 36,326
  • 7
  • 90
  • 83
  • In general, object attributes are in fact stored as a dictionary (`my_model.__dict__`, for this case) so your intuition isn't far wrong. But there are very sound reasons not to directly access or edit that dictionary. – Peter DeGlopper Sep 12 '13 at 09:01
  • @PeterDeGlopper I believe that you need to call `.save()` in order to update a django model. – Games Brainiac Sep 12 '13 at 09:03
  • 1
    @GamesBrainiac If you want the edits to be recorded to the database, yes. I intended my statement in the answer to address that: "This changes the in-memory copy of the model, but makes no database changes - for that your attribute would have to be a field and you'd have the call the `save` method." Do you think that's missing something? I'll edit in more info if necessary. – Peter DeGlopper Sep 12 '13 at 09:04
  • @PeterDeGlopper I think your answer is perfect, just a link to some django docs would be the cherry on top! :D I always do that, since more often than not, the docs have all the answers you want. – Games Brainiac Sep 12 '13 at 09:06
  • I'm saving it, but it's not working? I'm trying to change the value of a field from the form with index 0 in a formset. – AnonymousUser Apr 20 '22 at 04:31
  • You should probably ask a separate question or find an existing one that discusses editing formset data - it doesn't sound like your situation is as simple as editing an in-memory model instance. – Peter DeGlopper Apr 20 '22 at 15:34
2

Yes, you can change values, but this is not how its done. Django Models are Python classes that have models to represent fields. For example a CharField is for holding a string in a database. Let me demonstrate (code from django docs):

from django.db import models

class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)

As you can see above the Python class is a custom Django model. It is linked to a databse, and when you run manage.py syncdb, it will interact with your database to create the tables and columns that you need it to.

Now, in your case:

if my_model.is_changed:
    my_model.title = "Something"
    my_model.save()
Games Brainiac
  • 80,178
  • 33
  • 141
  • 199
  • @PeterDeGlopper Thanks for that, I was editing another question on a on a different forum, so I pasted the wrong thing both there, and here! :P – Games Brainiac Sep 12 '13 at 09:10
0

my_model is an object. So, try this:

if my_model.is_changed:
    my_model.title = 'something'
    my_model.save()
0

I was using inlineformset_factory, what I had to do was:

Instead of using my_model.title = 'something',

I had to use my_model.instance.title = 'something'


views.py

...

if request.method == "POST":
        formset = modelName2(request.POST, instance=modelName1)
        
        
        
        if formset.is_valid():

            if changeInstance == True:
                models = formset

                # change the title if changeInstance is True
                index = 0
                model = models[index]
                model.instance.title = "something else"
        
                model.save()
        ...
AnonymousUser
  • 690
  • 7
  • 26