Banging head against the wall again. I'm trying to add tags using other known fields
# models.py
class MyModel(models.Model):
...
tags = models.ManyToManyField(Tag, blank=True)
field_m2m = models.ManyToManyField('M2mModel', blank=True)
field_fk = models.ForeignKey('FkModel', blank=True, null=True)
...
def save(self, *args, **kwargs):
for inst in self.field_m2m.all():
self.tags.add(Tag.objects.get(name=inst.name))
self.tags.add(Tag.objects.get(name=self.field_fk.name))
super(MyModel, self).save(*args, **kwargs)
class FkModel(models.Model):
name = models.CharField(max_length=255, unique=True)
...
class M2mModel(models.Model):
name = models.CharField(max_length=255, unique=True)
...
I am 100% sure my field_m2m and field_fk aren't empty and what's not less important: there are instances corresponding to EXISTING tags. I have other functions covering this part well. I have also tried hardcoding the strings (Tag.objects.get(name="mystring")
) to be 101% sure.
Yet, no tags are assigned through admin panel. I tried to go through the steps in shell and it works there.
>>> m = MyModel.objects.get(name='something')
>>> t = Tag.objects.get(name='sometag')
>>> m.tags.add(t)
>>> m.tags.all()
[<Tag: sometag>]
How to make it work from save() method?
Also until the the model instance is created for the first time, traceback is complaining about: "<MyModel: Something>" needs to have a value for field "mymodel" before this many-to-many relationship can be used.
I guess I should save the model instance before even doing aforementioned assignments, right? How can I do it all at once?
Figured it out thanks to this hint: https://stackoverflow.com/a/6200451/1344854
Model save() method stays default. First I tied a tag to my FkModel and M2mModel instances. The rest of the job is done in ModelAdmin.
# models.py
class FkModel(models.Model):
name = models.CharField(max_length=255, unique=True)
tag = models.ForeignKey(Tag, blank=True, null=True, related_name='fk')
...
class M2mModel(models.Model):
name = models.CharField(max_length=255, unique=True)
tag = models.ForeignKey(Tag, blank=True, null=True, related_name='m2m')
...
# admin.py
class MyModelAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
form.save() # as I learned, without saving at this point, obj.field_m2m.all() will be empty
tags = []
if obj.field_m2m.all():
tags += [m2m.tag for m2m in obj.field_m2m.all()]
if obj.field_fk:
tags += [obj.field_fk.tag]
form.cleaned_data['tags'] = tags
super(MyModelAdmin, self).save_model(request, obj, form, change)