Search code examples
djangoinline-formset

BaseInlineFormSet clean method in admin false trigger?


I am trying to update a field in Admin but it raises Validation Error from clean method which I have defined as follows in forms.py:

class BasePhoneFormSet(BaseInlineFormSet):

    def clean(self):
        super(BasePhoneFormSet, self).clean()
        if any(self.errors):
            return

        phone_numbers = []
        for form in self.forms:
            if form.cleaned_data.get('number') in phone_numbers:
                raise forms.ValidationError(
                    'Duplicate Entry')
            phone_numbers.append(form.cleaned_data.get('number'))



PhoneFormSet = inlineformset_factory(
    Post, 
    Phone,
    formset=BasePhoneFormSet,
    form=PostForm, 
    fields = ('number',), 
    can_delete=False, # admin still shows delete next to the phone number
    extra=0,
    validate_min=True,
    min_num=1,

)

This code works in the views , but in the admin, I can't update or add any phone number since it raises the same ValidationError for duplicate entry.

here is my models.py

class Post(TimeStampedModel, models.Model):
    unique_id = models.CharField(max_length=6, unique=True)
    user = models.ForeignKey(User, related_name='posts')
    city = models.ForeignKey(City, related_name='posts')

class Phone(TimeStampedModel, models.Model):
    number = models.CharField(
        validators=[phone_regex],  max_length=15)
    post = models.ForeignKey(Post)

And this is admin.py

class PhoneInline(admin.StackedInline):
    model = Phone
    formset = PhoneFormSet

class PostAdmin(admin.ModelAdmin):
    inlines = [
        PhoneInline,
    ]

I looked into BaseInlineFormSet in models.forms but I got confused more.


Solution

  • class PhoneInline(admin.StackedInline):
        model = Phone
        formset = BasePhoneFormSet
        fields = ('number',)
        can_delete = False
        extra = 0
        min_num = 1