8

A customer wants to add custom fields to a django model we provide.

He wants to do this on his own, without programming.

These things should be addable:

  • boolean (yes/no) fields. Optional "unset"
  • single choice fields
  • multiple choice fields
  • single line text fields
  • textarea fields
  • date

Example:

The customer wants to add a field he calls "was successful". And the field > should have these choices: yes/no/unset. Defaulting to unset.

Things would be easy if I could do it by creating or extending a model. But in this case no source code changes are allowed :-(

How to solve this?

Update

Querying for instances with given values needs to be supported. Example: Show all instances where "was successful" is True.

6
  • 1
    When you say no source code changes... surely you accept that something must change for anything to be added? is a JSONField enough? Commented Feb 10, 2016 at 8:56
  • I updated the question. Querying needs to be supported. I am unsure if a JSONField supports this. Commented Feb 10, 2016 at 9:10
  • 1
    It sounds more like a case where what the customer is asking for isn't actually what they want. I would be very skeptical about giving any external entity free reign on what they could taint my database with Commented Feb 10, 2016 at 9:11
  • @Sayse yes, I don't want the customer to change my database schema. This would scare me ... I would try to avoid it as much as possible. Commented Feb 10, 2016 at 9:16
  • Thats conversations you need to have with the customer first then to figure out what they want and preferably why they want it. Sure you could let them stick in whatever they wanted in a jsonfield (if it was for a rest api) but you'd never be able to implement it in your own templates etc because there isn't any guarrantee values would be there, you can't make a stable query where you don't know if the field exists etc. Commented Feb 10, 2016 at 9:18

6 Answers 6

7
+75

You can create a table that follows the EAV principle (Entity Attribute Value). Basically this is a denormalised table with following columns:
[ID (and/or slug), float_value, integer_value, string_value] (Add more columns to this table)

Now say you've a existing table called "Member". When customer adds a dynamic field via your UI, you add the entries here and use "ID" to look them up for a given member.

Sign up to request clarification or add additional context in comments.

Comments

2

I use Django Dynamic Forms. Out of the box, it lets users create their own forms through the admin. You might want to extend it to build a more user-friendly UI, but this should get you pretty far. It supports

  • boolean
  • choices (select)
  • multiple choices (multiple select)
  • date
  • datetime
  • time
  • email
  • integer
  • single line text
  • multi line text

Comments

2

Well, when I had such problem, I used to create a custom field model, with a name field and a type field, usually a choice field with choices for the possible field types. You can also add a is_active field to filter the active and inactive CustomFields.

Than, when I create the for, I search this objects to know which fields I must have in that form.

To store the data, I'd have another model, called CustomFieldAnswer, or somethink like this. This model should have a ForeignKey to the main model that should have this data, and the custom field.

Doing so, You can have any kinds of fields for yout model dinamically and wothout you client needing to code anything.

You could use metaprogramming to create acutual fields in a form based on the query in the CustomFields. Or, you could just put the fields in the template and change the type of the input for each CustomField.

Hope that helps!

Comments

0

If that's really what you want.

  1. Create enough fields that your customer ever need.

    boolean_field_1 = models.BooleanField(..)
    boolean_field_2 ..
    date_field_1 = ..
    date_field_2 = ..
    
  2. Store alias mapping somewhere.

    I could add a field for alias mapping.

    json_mapping_field = JSONField()
    # this has is_successful: boolean_field_1
    
  3. Then find places where you can substitute the alias back to the real field name

    for simple filter and update, you could override

    1. QuerySet.filter Queryset.exclude
    2. QuerySet.update, UpdateQuery.add_update_values
    3. finally use from_queryset for your manager to use the overidden QuerySet.

3 Comments

Ok, this could work. But maybe you could create one Model for each data type instead of "boolean_field_1", "boolean_field_2", ... Background: Maybe one customer wants 20 boolean_fields ...
Or you could think of different scheme of distributing possible fields. If this is for questionnaire app, client might have idea of type of questions that have different field need criteria. One could distribute arbitrary set of fields to tables as long as you can have a mapping rule.
One could even have table for 10 booleans max, and 100 booleans max, and use 10 if he needs less than 10, or 100. (As long as you can implement mapping rules in step #3)
0

I know it sounds like an awful hack, but maybe you can build an interface that creates text files?

  1. One file would be models.py, with model definitions, and excluding this model from migrations with managed = False
  2. Another file is the SQL with DROP and CREATE table if the customer wants a new table, or just ALTER table.
  3. Another script can run the SQL script, copy the models.py file to the correct directory, and reload django.

1 Comment

Down vote? It's a not common question, that requires not common solutions.
0

I just discovered, that there is even a comparison grid on djangopackages about this:

https://www.djangopackages.com/grids/g/dynamic-models/

Heading:

Apps to add fields to models in the settings, or even at runtime.

Some StackOverflow administrator deleted this answer, that's why I write it again.

Reason of deletion was:

While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes.

Here are the current packages which are listed on the comparison grid today:

1 Comment

Please tell me why this answer gets down-voted. It is not a link-only answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.