Test Django ModelForm which depends on model with manytomanyfield

487 views Asked by At

I am trying to unit test one of my Django forms, which I use in the admin of a Django-based app. The Meta class of that form has a model field. Not sure about what approach is better:

  • Instantiate a model, and the build the ModelForm using it.
  • Instantiate the ModelForm just using data parameter, without a model object

I prefer the second approach (I think this approach is the one used when I just fill the form in my browser, right?), but I don't know how to represent a ManyToMany field

Here, some (simplified) code:

First, the models

class Segment(models.Model):
    name = models.CharField(max_length=150)
    app_name = models.CharField(max_length=150)

class ProceduralDocument(models.Model):
    name = models.CharField(max_length=150)
    content = models.TextField(null=True, blank=True, default=None)
    deleted = models.BooleanField(default=False)
    date_added = models.DateTimeField(auto_now_add=True)
    date_updated = models.DateTimeField(auto_now=True)
    segments = models.ManyToManyField(Segment)

As you can see, there are just 2 mandatory fields in ProceduralDocument:

  • name (text field)
  • segments (manytomany field)

Now, the admin

class ProceduralDocumentAdminForm(forms.ModelForm):
    class Meta:
        model = ProceduralDocument
        widgets = {'content': RedactorEditor(redactor_options={
            'lang': 'es',
            'redactor_css': "styles/pydocx_styles.css"
        }), }
        exclude = ['deleted']

    def clean_name(self):
        """ 
         Just a validation function. Not important
        """
        self.cleaned_data['name'] = remove_accents(self.cleaned_data['name'])

        return self.cleaned_data['name']



class ProceduralDocumentAdmin(admin.ModelAdmin):
    form = ProceduralDocumentAdminForm

    search_fields = ['name']
    list_filter = ['name']
    list_per_page = 300


    def save_model(self, request, obj, form, change):
        # Do some stuff here, not important
        pass

If I want to test ProceduralDocumentAdminForm, I can do this (look at 'segments' part)

form = ProceduralDocumentAdminForm(
    data={
        'name': u'áÉíÓúñÑ', 
        'segments': "..."}) # What to put here??

form.save()

# Here the assertions...

My problem is: what should I use as value for 'segments' in data? It matches a manytomany field.

And another question: Am I choosing the right approach? Testing the AdminForm without creating a model object, just passing JSON data

1

There are 1 answers

0
Shikhar Tyagi On

You will have to provide list of segment object ids. Do this:

segment_list = []
for i in range(5):
    seg = Segment.objects.create(
        name=f"Segment-{i}"
    )
    segment_list.append(seg)


form = ProceduralDocumentAdminForm(
    data={
        'name': u'áÉíÓúñÑ', 
        'segments': [seg.id for seg in segment_list],
    }
)