Determine if a model field should be provided with `create`

Apologies if this isn’t the right section to post this.

I’m writing a tool to enhance the Django typing experience, and was trying to understand when a model field should be provided when using Manager/QuerySet.create.

Consider the following model:

from django.db import models

class MyModel(models.Model):
    name = models.CharField("name", max_length=255)

    flag = models.BooleanField("flag")

Without the flag field, MyModel.objects.create() seems to work, as a default empty string value is provided for name (and this without having null=True or default=... provided).

However, with the flag field present, running the same empty create() call leads to:

django.db.utils.IntegrityError: NOT NULL constraint failed: app_mymodel.flag.

So my question is, how can I accurately infer a field as being required or not when using create? I’ve tried using Field.get_default, but it always falls back to an empty string (i.e. models.BooleanField("flag").get_default() == "").

I have the feeling that this cannot really be inferred accurately (as the exception thrown above happens at “the database level”, so Django seems to try to insert the row and catch any error that can happen, and does not perform any check beforehand). If that is the case, what signature would you expect when using create? Should all fields be optional (i.e. provide = ... in the signature), as we can’t know in advance if they are required or not?

Should some fields be set as required (i.e. do not provide = ... in the signature) in some cases? Thinking about:

  • a field that does not provide a default/db_default (even if it works, as seen with CharField)
  • a field that does not allow null=True (don’t know if this influences the fact that the field value doesn’t have to be provided).

Thanks!

1 Like

Hmmm…

You’re actually not going to be able to definitively determine this from within Django in the general case.

Why?

Because you have no way to ensure that there isn’t something in the database itself that will generate the value of a field. (Database-level default, trigger, etc)

In the common case, I’d say you’d have to provide a value unless the field definition includes one or more of the following:

  • null=True
  • default=<some_value> or db_default=...
  • it’s a date or datetime field with auto_now or auto_now_add clauses
  • The save method is overridden with a value assignment for that field
  • The model overrides the create method as a classmethod, assigning a value to that field
  • The model uses a custom manager with a create method that assigns a value to the field

And there may be others. (This is just what I can think of off-hand)

1 Like

Yeah I think Ken is right. Django ultimately leans on the database for many features, so you can’t be sure unless you try it.

Ken’s list is good and definitely incomplete. Another example would be custom model fields which may override the default value logic.

2 Likes

Thanks, this is what I kind of expected. As I do have access to the current application models when generating my stubs, I’ll probably be able to apply some logic based on the conditions you guys provided; except the ones related to overridden methods (apart from doing some smart code analysis, there’s no real way to programmatically infer these things).
If this is still not achievable, I can still set all fields as having a default value in the signature, it would still provide auto-completion which is a great enhancement anyway.