Django/Wagtail - Dynamically generate choices based on uploaded document - django

I am trying to implement a Chart Block in Wagtail where a user can upload a spreadsheet via the DocumentChooserPanel and then a chart is generated based on the data in that spreadsheet.
I currently have it functioning, but the user must explicitly specify the variable they want the chart to be based off of:
class ChartBlock(blocks.StructBlock):
data_file = DocumentChooserBlock()
primary_variable = blocks.CharBlock(required=True,max_length=255)
class Meta:
template = 'dataviz/blocks/Chart.html'
icon = 'cogs'
label = 'Chart'
I was wondering if there is any way to have the primary_variable field dynamically populated with the column headers from the spreadsheet uploaded and stored in Documents - so that the user would be able to choose from a list of available variables instead of having to remember what a variable was called.
Thank you so much!

This wouldn't be easy to achieve with a vanilla implementation of Wagtail.
The page edit form is generated on page load, including the population of choice lists. I'm pretty sure that the same is true of choice lists in StreamField blocks, that they are populated as the block is added.
The code for this hangs between wagtailadmin.edit_handlers, wagtailadmin.views.pages and wagtailcore.blocks. It would be a pretty complex customisation.
Another possible route for investigation would be using the insert_editor_js hook to update the primary_variable field once a document was uploaded. However, I'm not sure you'll find a dependable ID to hang an event listener off of.
However, you will soon be able to custom validate the submitted page. A PR has just been submitted to allow this custom validation. That should reduce the amount of user error when adding the primary_variable.
This feature should be available in Wagtail 1.4, which I believe is due for release pretty soon.
I hope that helps.

Related

SPField.FieldRenderingControl equivalent to CSOM or JSOM

Using the Microsoft.SharePoint dll, I can render SP Fields in custom application page using the below server side code.
BaseFieldControl editControl = field.FieldRenderingControl;
editControl.ID = field.Id.ToString()
editControl.ControlMode = SPControlMode.New;
editControl.ListId = list.ID;
editControl.FieldName = field.InternalName;
pnlFields.Controls.Add(editControl);
Now, we're converting our farm solutions to Addins/SPFx. I cannot find an equivalent of the above code via CSOM/JSOM. What is the way to render SP Fields in a custom page via client side programatically (Addins/SPFx) and How?
This will be used in a Batch Edit page, wherein the custom Batch Edit page contains the SP Fields visible in the default edit form of the list. And on the Batch Edit page, the user can input their updates to the items (just like entering inputs on the edit form).
You can't find it because a FieldRenderingControl does not exist in the SPFx world :)
I would highly recommend this sample to see how to dynamically render fields:
https://github.com/SharePoint/sp-dev-fx-webparts/tree/master/samples/react-list-form
It shows you how to read the list schema and render fields accordingly. You will have to render each field yourself, as well as handle any storing of data after an update. In the sample they have added code for most fieldtypes.
You can also batch these update calls (as you mention batch edit in your question) using the Microsoft graph:
https://learn.microsoft.com/en-us/graph/json-batching
This will save you a bunch of requests as you can do 20 item updates per call by using this.

Generate pdf in coldfusion with current form inputs

We have a form with a dynamic running totals table beneath the form. For example, when a user changes a value in the Quantity field, the running totals update based on the input (via javascript). The table is displayed only, nothing is saved in the database
We want to be able to generate a pdf that includes the updated running totals. Basically I'm searching if there is some way to pass the current innerHTML within a div to a pdf.
This may have been already asked and answered here- Generate pdf from current document , but the user didn't specifically say that the form updates data after the initial page load. So I just want to be sure I'm not missing something. Thanks. I have a feeling I should look into localStorage for this.
(From the comments)
I think you may be over-complicating the PDF functionality. It is not necessary to keep up with the local changes that the users make as far as generating a PDF is concerned. Most likely the users will make whatever changes to the page and then click a link/button to generate a PDF only after completing all of the changes. At that point you could simply submit a form with all of the updated values to ColdFusion and generate your PDF file. Instead of/or in conjunction with updating the innerHTML of a div, update the hidden form fields as well. Then on the ColdFusion server you could use something like the CFDocument tag to create your PDF from the form fields that were submitted. (Remember to validate all of the form field data before using it.)

Dynamically Update a Form in Django AFTER Initial Creation/Display

Is there away to dynamically modify and validate a Django form AFTER it's been created and displayed.(I have found a few snippets that show dynamic form creation, but these require that the dynamic fields are known/defined prior to creating the form.) My requirement is different.
Use Case:
I have a form where I want to display and validate additional input fields based on the selection from a dropdown on the initial form. Based on the selection additional fields are 1) added and 2)must then be validated with appropriate error handling.
(In case you are wondering the data elements to be added are a set of name/value pairs stored in csv format in the model, but when displayed they are shown as separate input fields - the input data will be converted to a csv string prior to saving).
I got this partially working using ajax to dynamically add the additional fields to a template, but have not found a way to validate these new fields. I'm not sure if this is a workable approach. I could probably do this in the browser using javascript, but would prefer a Django/server side solution.
OK - So none responded to my question so far. However I did a bit more googling and found an excellent article that describe the solution I was looking for. Major Kudo's to the author of this blog.
Create a Django Dynamic Form with JQuery - Dynamic Field Addition and Removal

Django app that can provide user friendly, multiple / mass file upload functionality to other apps

I'm going to be honest: this is a question I asked on the Django-Users mailinglist last week. Since I didn't get any replies there yet, I'm reposting it on Stack Overflow in the hope that it gets more attention here.
I want to create an app that makes it easy to do user friendly,
multiple / mass file upload in your own apps. With user friendly I
mean upload like Gmail, Flickr, ... where the user can select multiple
files at once in the browse file dialog. The files are then uploaded
sequentially or in parallel and a nice overview of the selected files
is shown on the page with a progress bar next to them. A 'Cancel'
upload button is also a possible option.
All that niceness is usually solved by using a Flash object. Complete
solutions are out there for the client side, like: SWFUpload
http://swfupload.org/ , FancyUpload http://digitarald.de/project/fancyupload/
, YUI 2 Uploader http://developer.yahoo.com/yui/uploader/ and probably
many more.
Ofcourse the trick is getting those solutions integrated in your
project. Especially in a framework like Django, double so if you want
it to be reusable.
So, I have a few ideas, but I'm neither an expert on Django nor on
Flash based upload solutions. I'll share my ideas here in the hope of
getting some feedback from more knowledgeable and experienced people.
(Or even just some 'I want this too!' replies :) )
You will notice that I make a few assumptions: this is to keep the
(initial) scope of the application under control. These assumptions
are of course debatable:
All right, my idea's so far:
If you want to mass upload multiple files, you are going to have a
model to contain each file in. I.e. the model will contain one
FileField or one ImageField.
Models with multiple (but ofcourse finite) amount of FileFields/
ImageFields are not in need of easy mass uploading imho: if you have a
model with 100 FileFields you are doing something wrong :)
Examples where you would want my envisioned kind of mass upload:
An app that has just one model 'Brochure' with a file field, a
title field (dynamically created from the filename) and a date_added
field.
A photo gallery app with models 'Gallery' and 'Photo'. You pick a
Gallery to add pictures to, upload the pictures and new Photo objects
are created and foreign keys set to the chosen Gallery.
It would be nice to be able to configure or extend the app for your
favorite Flash upload solution. We can pick one of the three above as
a default, but implement the app so that people can easily add
additional implementations (kinda like Django can use multiple
databases). Let it be agnostic to any particular client side solution.
If we need to pick one to start with, maybe pick the one with the
smallest footprint? (smallest download of client side stuff)
The Flash based solutions asynchronously (and either sequentially or
in parallel) POST the files to a url. I suggest that url to be local
to our generic app (so it's the same for every app where you use our
app in). That url will go to a view provided by our generic app.
The view will do the following: create a new model instance, add the
file, OPTIONALLY DO EXTRA STUFF and save the instance.
DO EXTRA STUFF is code that the app that uses our app wants to run.
It doesn't have to provide any extra code, if the model has just a
FileField/ImageField the standard view code will do the job.
But most app will want to do extra stuff I think, like filling in
the other fields: title, date_added, foreignkeys, manytomany, ...
I have not yet thought about a mechanism for DO EXTRA STUFF. Just
wrapping the generic app view came to mind, but that is not developer
friendly, since you would have to write your own url pattern and your
own view. Then you have to tell the Flash solutions to use a new url
etc...
I think something like signals could be used here?
Forms/Admin: I'm still very sketchy on how all this could best be
integrated in the Admin or generic Django forms/widgets/...
(and this is were my lack of Django experience shows):
In the case of the Gallery/Photo app:
You could provide a mass Photo upload widget on the Gallery detail
form. But what if the Gallery instance is not saved yet? The file
upload view won't be able to set the foreignkeys on the Photo
instances. I see that the auth app, when you create a user, first asks
for username and password and only then provides you with a bigger
form to fill in emailadres, pick roles etc. We could do something like
that.
In the case of an app with just one model:
How do you provide a form in the Django admin to do your mass
upload? You can't do it with the detail form of your model, that's
just for one model instance.
There's probably dozens more questions that need to be answered before
I can even start on this app. So please tell me what you think! Give
me input! What do you like? What not? What would you do different? Is
this idea solid? Where is it not?
Thank you!
I just released a simple app for this about a month ago: django-uploadify.
It's basically a Django template tag that acts as a wrapper for the very nifty Uploadify (requires jQuery). Using it is as simple as adding this to your template...
{% load uploadify_tags }{% multi_file_upload ‘/upload/complete/url/’ %}
The tag will fire events (1 per file) on both the client-side and server-side (Django signal) to indicate when an incoming file has been received.
For example, assuming you have a model 'Media' that handles all user-uploaded files...
def upload_received_handler(sender, data, **kwargs):
if file:
new_media = Media.objects.create(
file = data,
new_upload = True,
)
new_media.save()
upload_recieved.connect(upload_received_handler, dispatch_uid=‘whatever.upload_received’)
Check out the wiki for info on how to set it up and create the signal handlers (client/server).
About your conceptual implementation from above, here's a few points of consideration:
Having the app automatically create the "File Model" instance probably isn't as robust as people may already have their own models they're working with
If you want to implement any type of security or authentication, you need an open system and less of an 'auto-create' type
I really think signals/events are the way to handle this, and also handle the 'DO OTHER STUFF' part of what you mentioned.
My conclusion was that multi-upload can never really be a form widget in the sense that Django implements form widgets. 1 file will most likely be represented by 1 model instance (with some exceptions), which means that we end up with a situation where 1 widget can represent N model instances. However Django is setup so that a widget represents 1 value for 1 field in 1 instance. It just doesn't fit for the majority of use-cases to have it as a widget (hence why I went the template tag route).

How to select from a large number of options when completing a form

I am building a web app that allows our field staff to create appointments. This involves creating a record that contains many foreign keys, of which some come from very large tables. For example, the staff will need to select one of potentially thousands of customers.
What's the best way of doing this in Django?
A pop-up box that allows the users to search for customers, gives them the results, the user selects the results, then fills out the main appointment form and then
disappears?
Changing the appointments form to a customer selection page that
then reloads the appointments page with the data in a hidden form? Or
holding the data in some session variables?
Some from of Ajax approach.
A wizard where the flow is: a customer search page, a list of results and they select from results, then a search page for the next option (for example product selection), etc etc
(I'd like to keep it as simple as possible. This is my first Django
project and my first web project for more years than I care to
remember)
ALJ
Imho you should consider some kind of autocomplete fields. I think this results in the best usability for the user. Unfortunately, this always involves Ajax. But if you think that all users have JS turned on this is no problem.
E.g.
django-autocomplete
or what is probably more powerful:
django-ajax-selects
If you do the wizard approach, it will take longer for the user to accomplish the task and makes it harder to change selections.
Edit:
Well with django-ajax-selects you can define how the results should look like. So you can e.g. add the address behind the name.
Quote:
Custom search channels can be written when you need to do a more complex search, check the user's permissions, format the results differently or customize the sort order of the results.
I have done this before by integrating a jQuery autocomplete plugin. But, seeing as this is your first project and your desire to keep it simple, I suppose you could go with the session data option. For instance, you could show a search page where users could search for and select a customer. You could then store the, say, ID of the selected customer object as session data, and use it to pre-populate the corresponding field in the form when displaying the form. That's what I think offhand.