Whenever I try to save without editing any fields in Author in the admin page, I get a TooManyFields
error. I am aware that I can simply set this in settings.py.
DATA_UPLOAD_MAX_NUMBER_FIELDS = None
# or DATA_UPLOAD_MAX_NUMBER_FIELDS = some_large_number
However, not setting a limit would open up an attack vector and would pose security risks. I’d like to avoid this approach as much as possible.
My admin model AuthorAdmin
has a TabularInline
called PostInline
.
admin.py
class AuthorAdmin(admin.ModelAdmin)
inlines = [PostInline]
class PostInline(admin.TabularInline)
model = Post
models.py
class Author(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return str(self.name)
class Post(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
def __str__(self):
return str(self.title)
The reason this error is being raised is that an Author
can have multiple posts. Whenever this Author
is saved (without any field change), it sends out a POST
request which includes the post_id
and the post__series_id
based on the number of posts under that same author. This can easily exceed the default limit set by Django
which is set to 1000
.
Is there a way to not include unchanged fields in the POST
request upon save? Or a better approach to solve this issue without having to resort to updating DATA_UPLOAD_MAX_NUMBER_FIELDS
?
Note
This is just an oversimplification of what I’m trying to solve. The author and post models are just examples, but they represent the relationship of the actual models I’m using. I would like to get an approach which involves not removing the inline.
Welcome @FaitAccompli !
Is there a way? Sure, but it’s going to involve writing the JavaScript necessary to do that. You would have to build the post data elements yourself from the values in the formsets, and then writing the code in the views to handle the sparse submissions.
Or, you could take another approach and gather all the data into a single JSON object in the browser, and submit it through a custom API that would process it. (You could, in theory, expand it from JSON to a regular POST submission on the server, then pass that POST data to the normal view processing it.)
But either way, since this work does need to be done in the browser, there’s going to be some JavaScript involved to solve it if you don’t want to change the max number of fields.
Hi @KenWhitesell, thank you for the reply. I’m contemplating if it’s worth the effort to do so. On one hand, I’ve considered the following:
- A user can just go to the
Post
page in admin and filter by Author
there.
- Just increase the
DATA_UPLOAD_MAX_NUMBER_FIELDS
- Use a third-party library to perform paginations on inlines (django-admin-inline-paginator). Although, I don’t think this is going to be maintained anymore and will likely break in future versions.
I also tried making the fields read-only
but they seem to still be included in the POST
request upon save. How would you go about this?
I generally don’t rely upon the admin for my non-administrative UI.
This means I’d already be building my view for this situation, and if it were likely that I would regularly exceed the 1000 by a significant margin, then I’d probably go the route of converting the post data to a JSON submission to an API-style endpoint.
I’d have no problems doubling that value to 2000. Actually, I see where that setting was introduced for version 1.10, in 2016. Given the change in server capacity since then, I don’t see where increasing it to 2000 would create more risk than the 1000 setting 8 years ago.
Actually, if I thought I was going to have a situation where I’d have more than 2000 widgets on a page, I’d be seriously rethinking the purpose of that page and how it was constructed. I’d be looking real hard to find some way to make that more practical.
Correct, you’d need to mark them as disabled. However, the server would also need to know which fields were disabled, leaving you in effectively the same position as before.
1 Like
Thanks @KenWhitesell. It’s also mentioned in the documentation:
DATA_UPLOAD_MAX_NUMBER_FIELDS
You can set this to None
to disable the check. Applications that are expected to receive an unusually large number of form fields should tune this setting.
I’m guessing Django isn’t really against changing this to a higher value but it’s better for us to consider if it’s worth for our models that have this relationship to be an inline
in the admin page to begin with.
I’ve tried using the pagination approach and it works well for our use case. I hope in future versions Django decides to support this although I get why they aren’t.