GeneratedField based on ID

Hello,

I’m currently testing out the new GeneratedField functionality in 5.0. Has anyone had any success creating a field based on the ID? (for human-readable IDs inspired by stripe & django-spicy-id)

Here is what I’m trying (with little success). Any input to get it working would be cool

human_id = models.GeneratedField(
        expression=Concat(
            models.Value("prefix_"),
            "id",
            output_field=models.CharField(),
        ),
        output_field=models.CharField(),
        db_persist=True,
    )

Which database engine are you using?

In the docs for GeneratedField there’s a note talking about how each different database engine puts different restrictions on what expressions are allowed. So check the appropriate docs to see if there are any issues with using an auto field in a GeneratedField.

Also, note that the Concat docs specify:

… Each argument must be of a text or char type. …

so trying to Concat an integer with a char field will not work. I think you may need to enclose that “id” column within a Cast.

Thanks for the redirect. Turns out that the concat function is not considered immutable on postgres. Switching to the operator with a touch of RawSQL got it working

Here’s what I used to get it working

human_id = models.GeneratedField(
        expression=RawSQL("('prefix_' || id::text)",()),
        output_field=models.CharField(),
        db_persist=True,
    )

I guess I’ll stick with UUIDs for the moment. I had wanted to create a virtual field that has a human-readable ID that is built by encoding the integer IDs so that the lookup is just a decode + integer-based search (like django-spicy-id) but that looks like a difficult ask if dealing RawSQLs throughout the codebase

1 Like

I’m curious - why would you have raw SQL throughout the code base for this field?

You’ve created a real field that will contain the prefix and id that may look something like prefix_123. Everywhere else in your code you’ll be able to filter (or get) on human_id="prefix_123".