2 questions:
- How can I stop duplicates from being created when parent=None and name is the same?
- Can i call a model method from within the form?
Please see full details below:
models.py
class MyTest(models.Model):
parent = models.ForeignKey('self', null=True, blank=True, related_name='children')
name = models.CharField(max_length=50)
slug = models.SlugField(max_length=255, blank=True, unique=True)
owner = models.ForeignKey(User, null=True)
class Meta:
unique_together = ("parent", "name")
def save(self, *args, **kwargs):
self.slug = self.make_slug()
super(MyTest, self).save(*args, **kwargs)
def make_slug(self):
# some stuff here
return generated_slug
note: slug = unique as well!
forms.py
class MyTestForm(forms.ModelForm):
class Meta:
model = MyTest
exclude = ('slug',)
def clean_name(self):
name = self.cleaned_data.get("name")
parent = self.cleaned_data.get("parent")
if parent is None:
# this doesn't work when MODIFYING existing elements!
if len(MyTest.objects.filter(name = name, parent = None)) > 0:
raise forms.ValidationError("name not unique")
return name
Details
The unique_together
contraint works perfectly w/ the form when parent != None
. However when parent == None
(null) it allows duplicates to be created.
In order to try and avoid this, i tried using the form and defined clean_name to attempt to check for duplicates. This works when creating new objects, but doesn't work when modifying existing objects.
Someone had mentioned i should use commit=False on the ModelForm's .save, but I couldn't figure out how to do/implement this. I also thought about using the ModelForm's has_changed to detect changes to a model and allow them, but has_changed returns true on newly created objects with the form as well. help!
Also, (somewhat a completely different question) can I access the make_slug() model method from the Form? I believe that currently my exclude = ('slug',)
line is also ignoring the 'unique' constraint on the slug field, and in the models save field, I'm generating the slug instead. I was wondering if i could do this in the forms.py instead?