I have a form in my admin site where the user is to select a single object from a particular model from a dropdown.
thing_choices = [(x.id, x) for x in Things.objects.all()]
class ThingSelector(forms.Form):
thing = forms.ChoiceField(choices=thing_choices)
If I first add a new Thing object, then go to the page with the selector form, I find that the object does not appear in the dropdown. This is presumably the form was populated with choices when I first stood the server up. Testing bears this out, because if I restart Django, the new choice appears on the list.
How can I get around this so that I can create objects and have them appear on this form too?
(More info: the selected thing is submitted with the form in order for processing to be done upon it.)
Thanks...
If I first add a new Thing object, then go to the page with the selector form, I find that the object does not appear in the dropdown. This is presumably the form was populated with choices when I first stood the server up.
Correct, the variable thing_choices is calculated when your code is first run, and if its at the same scope as your form its unlikely to ever run again.
An easier way is to use a ModelChoiceField, which references a model, rather than a ChoiceField. Like so:
class ThingSelector(forms.Form):
thing = forms.ModelChoiceField(queryset=Things.objects.all()
This should mean that as new Thing objects are added, they are able to be selected in the form.
Related
I have flow where users can create (model) forms. If form is valid, object gets saved and flow continues, but selection is in multiple pages. I need to keep current state of created object, which cannot be saved before it's completely valid.
One thing I can do is to always pass things around those views in the ModelForm to make sure, that user never loses data, but I also wanna make sure, that if he leaves the flow and comes back, he doesn't lose data, that he already entered previously.
That's why I decided I wanna save all the fields to session.
Is this correct approach?
How would you do this?
Where would you put this session logic?
What's best way of getting the fields from incomplete form to be saved?
Edit:
Please don't give me advice on how to use session, I am talking more about high level logic and architecture than specific implementation.
I should describe my flow a bit more. Model has 3 fields.
normal dropdown (foreign key referencing another model)
textfield
another foreign key, but this time not done by select, but it's own separate page with lots of filters to help user pick the right (foreign) model
Flow is not linear, because user can start in different parts of page.
Sometimes user can go to page, where he has first 2 fields + button "Browse", which takes you to selection page for 3rd field. Then after he selects field there, he comes back.
But sometimes he selects first this field and then comes to screen with 2 remaining fields, where he needs to fill those.
django-formtools offers a great way to do this using Form wizard.
The form wizard application splits forms across multiple Web pages. It
maintains state in one of the backends so that the full server-side
processing can be delayed until the submission of the final form.
More info here https://django-formtools.readthedocs.io/en/latest/wizard.html
to save in session:
request.session["variable_name"] = "value"
to get from session request.session["variable_name"]. sure you can use request.session.get("..") in both too
I have a rather long form that users can't always complete in one sitting. I'd like users to be able to hit a button and save the form for completion later. My first thought was to simply save the form anyway and just flag it as incomplete somehow. However, I can't seem to get around the fact that incomplete forms are invalid and can't be forced to save. For example, if a required field near the end of the form is blank the form can't be saved to the database even if I skip the form.is_valid() step.
Is there another way to save the form's data temporarily? Also, I'm aware this question has been asked before but I'm afraid this answer wasn't very helpful: Django Save Incomplete Progress on Form
Update
Thank you all for the responses so far. Some of the answers below made me realize I omitted a detail from my original question. I need to be able to let the user choose whether or not to finish a form when they return. The users enter information into this form several times a day. They may come back to the form not ready to finish form item A but instead needing to fill out form item B from the beginning. So, just auto-populating the form with their last incomplete form won't quite do the trick. I'm sorry this didn't occur to me when I posted the original question.
If you use django-merlin you can split up that long ass form into lots of smaller forms, and each previous form will be saved in the user's session just waiting for them to come back to it. If they navigate away and come back to it through the wizard's base url, they will be resumed at the same place they left off.
I was asked to implement this type of functionality for the Django form wizard. The solution I came up with (without going too deep into the details) was to save the cleaned data at every step in a json format (json.dumps(self.get_all_cleaned_data()) to a table in my database.
Later, if someone wanted to resume the form, they could retrieve the record from the database and the information could be repopulated into the form using the (initial.update) method (def get_form_initial(self, step):). Hope this helps give you an idea.
I would like to add an Item entry into my database in my django app, but I am having problems. I'm still learning django (who isn't?), but I've done db entries before. Part of this is because of things like cart instance, and contenttype instances.
Generally I start with...
item1 = Item(Cart(...), ContentType(...), quanity='4',<etc.>)
And depending on what I put in, it will let me do that, but when I do item1.save(), it yells at me, and unfortunately the stack trace is hardly helpful. Or, maybe it's just me.
Any suggestions?
First suggestion is to post the stacktrace or even just the main exception; it's always more helpful to know what it's yelling.
My guess is first that you are passing in positional arguments and the model doesn't know what to do with which argument.
My second guess is that you are passing in unsaved instances Item(Cart()...) to foreign key fields that are non nullable so django or the database would complain if you didn't pass in an actual Cart instance with an ID defined.
So, explicitly define which fields you are passing to the constructor, and ensure you are passing in saved instances (not Cart() but Cart.objects.get(id=X))
cart = Cart.objects.latest('id')
item = Item(cart=cart, etc.)
item.save()
I will use model.id when referencing the id for the table in the database, and id when referencing the id given to elements in my html.
I have a django project where I am using some hidden form fields (all forms have the same id right now for that hidden field) to house the model.id. This works great as long as the model.id is known when the page is rendered.
I am now attempting to modify the process to work when no model.id is given (ie someone has chosen to create a new instance of my model). As far as the backend goes I have this working. No model.id supplied and the view knows it should give empty forms. At this point I choose not to create a new instance of the model, as I only want to if the user actually enters something in one of the forms.
If the user enters something in a form then the form processing creates a new instance of model and passes the id back to the users browser. What I was attempting to do is use the jquery form plugin to save the return data somewhere hidden, which I would then look at and use val to set all of the hidden fields' ids to the model.id that was returned so the next field/form the user submits will know to write to the model that was just created.
Now looking at this I'm guessing the idea of having multiple elements with the same id is bad, but I really do want them to always be the same and only have the hidden fields there to house that same Model.id on every form on the page.
I tried doing something like follows. However only one of the ids on the page actually got the value assigned. Is there a different way I should be accomplishing this goal? Is there something I should add to make all occurrences of id to be set with something like .val(model.id)? If not, does anyone have any suggestions on how to go about this? Maybe django provides a cleaner way of doing exactly what I'm trying to accomplish?
A response returned from form submission.
<response>
<the_model_id_brought_back>3732</the_model_id_brought_back>
...
<response>
The jQuery code attempting to set all of the "id_in_multiple_places" ids to the model.id returned.
jQuery('#descriptionForm').ajaxForm({
target: '#response',
success: function(data) {
the_model_id = jQuery('#response').find("the_model_id_brought_back").html();
jQuery('#id_in_multiple_places').val(the_model_id);
}
});
To explain why I have multiple forms like this. Forms consist of 1 visible field. Multiple forms are on the page. When a user leaves a field (which means they leave the form as well) I will submit that form to the server. This will allow their data to always be saved even if they stop half way through and throw their computer out a window. They can go to a different computer and pick up where they left off.
Thanks.
Now looking at this I'm guessing the idea of having multiple elements with the same id is bad
It's not only bad, it's impossible. You cannot do this. You can get around this by using classes, which don't have to be unique, but you probably shouldn't.
What you should do, is assign the elements sensible class names, and assign their common ancestor the ID. You can start at that element and traverse downwards to find the sub-elements by class name.
I have a view that handles a POST request and attempts to create a new object. However, I know that some of the POST'd data is invalid... But I want to fix it and go ahead and create the object.
The only way I can figure out to be able to 'fix' data in a ModelForm is to create a 'is_valid()' form. To do this, I can either create the form with the POST data, or I can create it with an already existing instance. Unfortunately, if I use the POST data, because some of it is invalid, the form won't validate and I am thus unable to get to the data in the form to fix it. If I create it with an already existing instance, this works, but when the form is displayed, any remaining errors are for whatever reason ignored (and thus don't show up on the web page.) I've tried a combination of creating the the Model form from the POST data and giving it an instance, but this doesn't seem to help. Additionally, I've tried modifying (a copy of) the POST data, fixing it, and then creating the ModelForm from the 'fixed' POST data. This sort of works, with the exception that I have some ImageFields in my form, and they seem to just be ignored.
Any help would be greatly appreciated. I have looked at every good page that I can find to no avail.
Perhaps there is a better way to do this? The problem I'm trying to solve is that I want to have a model that contains ImageFields. The first time I put up the form, the user needs to 'upload' images for each of the fields. However, if he doesn't update an image for one of the fields, I want the new form to come up with a Image upload button on the fields where images have not been uploaded, and just a text field with the image name for images that have been uploaded.
Edit 9/15/2010:
Ok, I think I can simplify all of the above question into this:
def testing( request ) :
test_form = UserProfileForm()
valid = test_form.is_valid()
return render( 'testing.tmpl', locals(), request )
When the above code is rendered, the 'valid' shows as False (as one might expect), but the 'test_form' renders without any errors. I've read through (if perhaps not understood?) the documentation on Models and ModelForms, and I see that most of the time a ModelForm (in my case: UserProfileForm) is created with a specified 'instance'. However, 1) I don't have an instance yet, 2) I would still expect the non-instance'd Form to display errors. I'm sure there is something I am missing. Please illuminate. :)
One more thing, which perhaps the answer to the above will answer anyway, but as far as I can tell, the is_valid() call is supposed to call the 'clean()' function I defined for the UserProfileForm. However, (not being a python guru) I placed 'raise ValidationError()' at the top of clean(), and when I run the code, no error is shown. Thoughts?
Update: I figured out the problem and the answer is below. Thanks!
You should have a look at how to clean form fields in django. You could either manipulate the data returned from the form there or make any kind of validation!
If your ImageFields are optional then you can still validate them (that they are otherwise correct).
Then it's a matter of adjusting your template to show either the uploaded file name or an file upload field depending on whether they've already uploaded one or not. Actually, it would probably be better to give them both fields in the first case. That's what the automatic admin does (the upload field is labeled "Change").
Well, after figuring out how to use the python debugger (pdb) and the fact that within emacs it kind of 'just works' (wow!?) I was able to find that my (empty) form was not bound. Googling bound forms pointed me to this page:
http://docs.djangoproject.com/en/dev/ref/forms/api/
RTFM'ing I find that I can pass an empty dictionary to my form and then everything starts to behave as I would expect. So, to summarize, there is a big difference between:
test_form = UserProfileForm()
and
test_form = UserProfileForm( {} )
The second version causes the rendering of the form to show all the errors (and to call 'clean()').
With risk of having this deleted by the moderator ;) Thank you to all those who commented and for your patience with a new django developer.