Django custom form with non-model fields in Admin / AdminInline

I am having trouble setting up admin pages in Django to use custom forms or non-model fields.

The site I am working on will be used as a storage utility for reporting some production processes. The database will have three main tables, two of which will have ForeignKey in the fourth table. Each row in the fourth table is essentially one row from the CSV file to be loaded. The model for the fourth table looks like this:

bandwidthrawid = models.IntegerField(...) 
testdate = models.DateTimeField(...)
frequency = models.FloatField(...)
power = models.FloatField(...)
uncalibratedpower = models.FloatField(...)

      

I let Django generate the id field automatically. The test date will be static for every record from the same test. The Frequency, Power and UncalibratedPower fields will contain the same value from the same line in the CSV file. The BandwidthRawId field will contain integers in sequential order, re-iterating over and over, indicating which test was. So, for example, let's say that a user tests the same module twice in the frequency range from 1 to 60 Hz in 1 Hz steps, a CSV file will be created that looks something like this:

1,0,0
2,0,0
3,0,0
4,0,0
5,0,0
...
60,0,0

      

The second test will also generate a similar file. When these files are uploaded to the system, the recording date will be recorded and assigned a BandwidthRawId, which is the incremented value of the current maximum value in this column. So, the entry in the table for two files will look like this:

Id, Date, BWID, F, P, UP
1,  Date1, 1,   1, 0, 0
2,  Date1, 1,   2, 0, 0
...
60,  Date1, 1,   60, 0, 0
61,  Date2, 2,   1, 0, 0
62,  Date2, 2,   2, 0, 0
...
120,  Date2, 2,   60, 0, 0

      

This is where things start to get complicated. Sometimes the files aren't all in the same order, so the CSV Importer won't work. Sometimes the files do not contain all the information you need. Files NEVER have dates in them, and NEVER have header lines. To combat all of these things, I created a widget / field that creates a CSV Preview and allows the user to choose which actual field each column belongs to. I named this CSVPreviewField.

To test this field / widget in the "field", I overridden the BandwidthRawID field in the model and used that to handle all processing. I originally thought it would be easy to override this field, do the processing and then populate that field with the correct integer and then pass that on for processing. Unfortunately, this won't work. I'm getting an error that the BandwidthRawID field is of invalid type (in the database it's an integer, in the model it's CSVPreviewField / FileInput).

Then I tried to add a CSVPreviewField (called BandwidthRawFile) to the ModelForm that uses BandwidthRaw as the model and will override the form field of the ModelAdmin class I wrote to handle the bandwidth_raw table. Unfortunately, no matter what I do, I cannot display this field, the error I get is "BandwidthRawFile not found in form fields" or something similar. I also got an error indicating that the database does not have a column corresponding to "BandwidthRawFile".

After that, I learned about inline strings and tried to do the same with inline form, which also fails for similar reasons. Either it fails because I am not specifying the model (hoping I could make a custom form), the model does not contain a BandwidthRawFile field, or the database does not contain that field.

At this point I have been working on this for two days and have completely exhausted ideas. Basically, the best solution would be an inline form. If I could somehow place my widget on two other admin pages that require a BandwidthRawId and then return that value as a result of processing the widget, that would be the ideal situation. Right now, I'd be happy if the little green + next to the foreign key would launch a custom form that handles all the processing and returns a BandwidthRawId.

+3


source to share


2 answers


Since nobody seems to have an answer to this, I'm going to go and "answer".

The answer I found is that you cannot have non-model fields in a model form. Frames are simply ignored. Adding your own inline forms doesn't work well either, the same errors end up.

How I fixed this problem:



  • Create CSV preview widget
  • Embedding a widget in a CSV field
  • Write field / widget logic
  • Create my own form - NOT model-form
  • Create form handlers
  • Create a view to host the form
  • Override add_view in models to return a custom form
  • Override get_form function in models to add csv widget to form

Actually I am not like this answer, but I have no better solution.

+3


source


If you are not too picky about the implementation, you can look at something like Postgres External Data Wrappers (file_fdw is a csv interface). Since the files are very homogeneous, you will end up with a nice ORM interface and save a ton of headaches on the import side.



0


source







All Articles