vitalik / django-ninja

💨 Fast, Async-ready, Openapi, type hints based framework for building APIs
https://django-ninja.dev
MIT License
6.66k stars 396 forks source link

[Question] TypeError: cannot specify both default and default_factory #1080

Open unique1o1 opened 5 months ago

unique1o1 commented 5 months ago

I'm unable to use fields_optional='__all__' in some models?

here are my models:

class Topic(models.Model):
    name = models.CharField(max_length=100, db_index=True)
    certificate = models.ForeignKey(
        to=Certificate, on_delete=models.CASCADE, related_name='topics', db_index=True
    )
    is_free = models.BooleanField(default=False)
    updated_at = models.DateTimeField(
        default=timezone.localtime,
    )
    created_at = models.DateTimeField(
        default=timezone.localtime,
    )
    description = models.TextField(null=True, blank=True)
    updated_by = models.CharField(
        max_length=100,
        db_index=True,
    )
    number_of_questions = models.IntegerField(default=0)
    image = models.ImageField(upload_to='topic_image', null=True, blank=True)

class Question(models.Model):
    topic = models.ForeignKey(
        to=Topic, on_delete=models.CASCADE, related_name='questions', db_index=True
    )
    # publish_date = models.DateField(default=datetime.now)
    question = models.TextField()
    image = models.ImageField(upload_to='question_image', null=True, blank=True)
    answers = models.JSONField(default=default_answers)
    # multiple_right_answer = models.BooleanField(default=False)
    correct_answer = ArrayField(
        models.CharField(max_length=10, blank=True),
        help_text='Please choose from the above option you entered',
    )
    question_type = models.ForeignKey(
        to=QuestionType, on_delete=models.CASCADE, related_name='questions'
    )
    updated_at = models.DateTimeField(
        default=timezone.localtime(),
    )
    created_at = models.DateTimeField(
        default=timezone.localtime(),
    )
    updated_by = models.CharField(
        max_length=100,
    )

Schema:


class TopicUpdateSchema(ModelSchema):
    class Meta:
        model = Topic
        exclude = ['id', 'updated_by', 'updated_at', 'created_at']
        fields_optional = '__all__' <------------------works

class QuestionUpdateSchema(ModelSchema):
    class Meta:
        model = Question
        exclude = ['id', 'updated_by', 'updated_at', 'created_at']
                 fields_optional="__all__" <----------------doesn't work

Using fields_optional='__all__' in QuestionUpdateSchema does not work but it works in TopicUpdateSchema. Even adding the following fields in QuestionUpdateSchema didn't work .

fields_optional = [
            'certificate',
            'topic',
            'question',
            'image',
            'question_type',
             'answers',          <----------------but removing the this will then work.
            'correct_answer',
        ]

but when i remove answers field from fields_optional it starts working.

Versions

vitalik commented 5 months ago

Hi @unique1o1 could you define "doesn't work" - does it give some error ? or behaves differently (how) ?

unique1o1 commented 5 months ago

Hi @unique1o1 could you define "doesn't work" - does it give some error ? or behaves differently (how) ?

Hey, @vitalik Yeah, it gives an error saying TypeError: cannot specify both default and default_factory

fk128 commented 5 months ago

It seems this might be because when optional is set, it only sets default = None, but doesn't also set default_factory = None.

https://github.com/vitalik/django-ninja/blob/08af4b9b571c92a7d14edaeb53cf54bb673bea0d/ninja/orm/fields.py#L157-L159

mikezolo commented 4 months ago

There is a space before 'answers' in your quote:

fields_optional = [
            'certificate',
            'topic',
            'question',
            'image',
            'question_type',
             'answers',          <----------------but removing the this will then work.
            'correct_answer',
        ]

Sometimes parsers are demanding. Check if the space removal fixes the bug.

dc-p8 commented 3 months ago

i'm having the exact same issue. i'm creating all my write schemas this way :

class OrderWriteSchema(create_schema(Order, optional_fields="__all__")):
    pass

but for one very specific models, i'm having the TypeError: cannot specify both default and default_factory error.

I finally found the problematic field in my model, it's this one : default_order_datas = models.JSONField(null=False, default=dict)

I made the field nullable and removed the default factory and the error disappeared.