I would like to display an alert box after a form has been submitted.
The box would be hidden when a user first visits the page and will display "new category created" or "category already exists" upon submission.
I think I know would I can do this in the template but I'm not sure how to pass the variable into the template on the redirect.
Below is the view. Any thoughts how I can accomplish this?
I appreciate the feedback.
#login_required
#locationed
def manage_cat_subcat(request, location):
form = AddCategory()
if request.method == 'POST':
form = AddCategory(request.POST)
if form.is_valid():
submitted_cat_name = form.cleaned_data['category_name']
_, was_created = Category.objects.get_or_create(name=submitted_cat_name)
return HttpResponseRedirect(reverse('manage_cat_subcat', args=(location.slug,)))
return render(request, 'inventory/manage_cat_subcat.html', {'location': location, 'form': form})
You don't have to use any hidden data, just use this:
https://docs.djangoproject.com/en/dev/ref/contrib/messages/#using-messages-in-views-and-templates
It looks like you're talking about rendering a dialog based upon a user submitting certain information. If so, I strongly recommend using JQuery to pull the value of the category field once the field loses focus, then pass that category information right away via an AJAX call to a dedicated method in your views file. Depending on the response, you'll show the appropriate dialog. So it would be something like this in your views.py:
#render_json
def ajax_category_check(request){
if request.method == 'POST' and 'category_name' in request.POST:
#insert your code that checks new or existing categories
#if the category exists...
return {'exists': True}
return {'exists': False}
}
One advantage of AJAX is that it makes the user experience a lot smoother by removing the burden of having them deal with form submission/browser page refreshing.
On the other hand, if you're talking about simply showing an alert dialog before the form is even submitted, intercept the form submission and show the dialog using JQuery:
$('form').click(function(event){
$('#dialog').show();
/* after a delay or after dialog confirmation, etc... */
$('form').submit();
});
Related
I am using Boostrap modal fade window which renders Django form to update my database records. And what I fail to do is not to reload the page if the user has opened the Update window and did not change anything. It will be easier to get my idea if you look at the code below:
def updateTask(request, task_id):
#cur_usr_sale_point = PersonUnique.objects.filter(employees__employeeuser__auth_user = request.user.id).values_list('agreementemployees__agreement_unique__sale_point_id',flat=True)
selected_task = Tasks.objects.get(id=task_id)
task_form = TaskForm(instance=selected_task )
taskTable = Tasks.objects.all()
if request.method == 'POST':
task_form = TaskForm(request.POST,instance=selected_task)
if task_form.has_changed():
if task_form.is_valid():
# inside your model instance add each field with the wanted value for it
task_form.save();
return HttpResponseRedirect('/task_list/')
else: # The user did not change any data but I still tell Django to
#reload my page, thus wasting my time.
return HttpResponseRedirect('/task_list/')
return render_to_response('task_management/task_list.html',{'createTask_form':task_form, 'task_id': task_id, 'taskTable': taskTable},context_instance=RequestContext(request))
The question is, is there any way to tell Django to change the url (like it happens after redirecting) but not to load the same page with same data for the second time?
It's not trivial, but the basic steps you need are:
Write some javascript to usurp the form submit button click
Call your ajax function which sends data to "checking" view
Write a "checking" view that will check if form data has changed
If data have changed, submit the form
If not, just stay on page
This blog post is a nice walkthrough of the entire process (though targeted towards a different end result, you'll need to modify the view).
And here are some SO answers that will help with the steps above:
Basically:
$('#your-form-id').on('submit', function(event){
event.preventDefault();
your_ajax_function();
});
Call ajax function on form submit
Gotta do yourself!
Submit form after checking
I have a Django page with a form. I have some view code which deals with the form as normal but prepopulates the form with initial data from the a user's session if available. This is so that when a user returns to this form they see previously selected options (yes, the form is quite extensive).
My views,py:
def myView(request):
...
form = ProjectInfoForm(request.POST or None)
if form.is_valid():
# process form, including a redirect
...
# if there is form data in the session, let's use that
# to initaliaze our from with data
if key in request.session:
form = ProjectInfoForm(
initial={
'model': request.session.get('model'),
...
}
)
return render_to_response(template_name, {
...
}, RequestContext(request))
Problem is: if I load the session data then the page does not display any error messages. The form does fail validation, I am just not getting the any output. Is there some conflict here with initial?
Any help would be much appreciated.
Well, from that snippet, if the session data is found then you completely re-initialize the form: the original, validated instance, which contained the POST data and any errors, has now been disposed. Presumably you would want to only enter that second if if the request is not a POST.
I have a template that creates a text entry field and a checkbox. When the checkbox is unchecked, the text field is disabled and cleared, when it's checked, it's enabled, and the user may or may not have typed in it. In my controller I need to distinguish between the 2
cases when the checkbox is unchecked, and the checkbox is checked but the text field is blank. I can get the value of the text field, but not of the checkbox. Is there some way to do this? I've googled this, and I see it's been asked a few times here, but noneof the solutions seem to work for me.
request.POST.get('my_checkbox_field')
P.S. In Django, they're called "views" not controllers.
UPDATE (based on comment)
I'm taking "controller" to mean "view" since Django doesn't have a concept of controllers and they're closest to views. If that's not the case, by all means correct me. Given that, all function-based views at the very least require a request parameter. If you're using class-based views, then request is simply stored on the view object, so you just need to modify it to self.request. I suggest you take some more time to thoroughly read the docs, as this is pretty much bare minimal understanding stuff that is well documented.
Are you looking for this?
def myview(request):
form = MyForm()
if request.method == 'POST':
form = MyForm(request.POST)
if form.is_valid():
checkbox = request.POST.get('my_checkbox', False) # will be True if checked
if checkbox:
# check textfield content
else:
# do something else
return render_to_response(template, kwvars, context_instance=RequestContext(request))
I've seen Django's samples and I can see they have decent error handling. However I want to see if there is yet a better approach, a general pattern to handle form validation errors in Django. This is the sample I found here:
def contact(request):
if request.method == 'POST': # If the form has been submitted...
form = ContactForm(request.POST) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
# Process the data in form.cleaned_data
# ...
return HttpResponseRedirect('/thanks/') # Redirect after POST
else:
form = ContactForm() # An unbound form
return render_to_response('contact.html', {
'form': form,
})
In particular, I was wondering:
How can the view in "/thanks/" be sure that the form was validated? Are there any common ways to pass the successful validation of the form to the next view? Or do I need to do something manually such as setting a flag in request's session?
How can one write this code in a way that when form is NOT valid and the page is shown with errors upon submission, if user refreshes the browser it wouldn't ask the user if they want to POST data again?
EDIT: With regards to #1 I am referring to cases like user manually entering the '/thanks/' url or going back and forth through history pages and accidentally openning it without any form being validated. (Do we still show the "thanks" page? or we need to somehow re-validate why we are in thanks view).
The view can be sure that the form is validated because it will only be called if the form is valid...
If the page is generated through a post request the browser will always ask you that when hitting refresh... I guess the only way to avoid this would be redirecting to another page!
How can the view in "/thanks/" be sure that the form was validated?
form.is_valid() should thoroughly check any field or - if necessary - any combination, cornercase, etc. That's basically it. The views knows, the form was valid if it renders. There is no need to include redundant information in the session.
How can one write this code in a way that when form is NOT valid and the page is shown with errors upon submission, if user refreshes the browser it wouldn't ask the user if they want to POST data again?
I am not sure what the point would be. The form contains errors and the user may correct them or leave. To render a page that would not ask for form resubmission, one could use a redirect, just as in the valid case. The error markup would have to be done manually in that case.
i'm trying to build a mini reply system, based on the user's posts on a mini blog.
Every post has a link named reply. if one presses reply, the reply form appears, and one edits the reply, and submits the form.The problem is that i don't know how to take the id of the post i want to reply to. In the view, if i use as a parameter one number (as an id of the blog post),it inserts the reply to the database.
But how can i do it by not hardcoding?
The view is:
def save_reply(request):
if request.method == 'POST':
form = ReplyForm(request.POST)
if form.is_valid():
new_obj = form.save(commit=False)
new_obj.creator = request.user
new_post = New(1) #it works only hardcoded
new_obj.reply_to = new_post
new_obj.save()
return HttpResponseRedirect('.')
else:
form = ReplyForm()
return render_to_response('replies/replies.html', {
'form': form,
},
context_instance=RequestContext(request))
i have in forms.py:
class ReplyForm(ModelForm):
class Meta:
model = Reply
fields = ['reply']
and in models:
class Reply(models.Model):
reply_to = models.ForeignKey(New)
creator = models.ForeignKey(User)
reply = models.CharField(max_length=140,blank=False)
objects = NewManager()
mentioning that New is the micro blog class
thanks
heyy there. i solved the problem,using your advices, but I've created another.
I was thinking that as the reply form is in another page, simply clicking on that reply link ain't gonna help me retain the post id anyhow, because the blog page is gone, after i push thet reply button. So, in my view, i 've created a function that holds the id of the blog post as a parameter. It saves just as it should, no problem, but now my problem is: HOW CAN I PASS A LINK LIKE
url(r'^save_reply/(?P<id>\d+)/$',
save_reply,
name='save_reply'),
(this is what i hold in my urls.py)
to the reply under each post? I mean, until now, my reply link was simply calling the function replies/save_reply(i had Reply) but now, when i have the id as a parameter, how can i put it in my a href = 'what here'?
here is my views.py that works right:
def save_reply(request, id):
if request.method == 'POST':
form = ReplyForm(request.POST)
if form.is_valid():
new_obj = form.save(commit=False)
new_obj.creator = request.user
u = New.objects.get(pk=id)
new_obj.reply_to = u
new_obj.save()
return HttpResponseRedirect('.')
else:
form = ReplyForm()
return render_to_response('replies/replies.html', {
'form': form,
},
context_instance=RequestContext(request))
and i'm callin it by typing in my browser:
http://127.0.0.1:8000/replies/save_reply/1/ (for instance)
of course, i've removed my foreign key field, as now it is unnecessarry
Thank you!
You need to have a hidden field in your form to capture the PK of whichever instance of New the comment is related to.
Since you're using a ModelForm, your Reply model already has the ForiegnKey relationship established. You can set the widget type to be hidden, so your users don't see it..
# forms.py
class ReplyForm(ModelForm):
class Meta:
model = Reply
fields = ['reply', 'reply_to']
widgets = {
'reply_to': forms.HiddenInput),
}
When you initialize the ReplyForm, you can populate the reply_to field like form = ReplyForm({'reply_to': new.pk}) - where new is an instance of New
BTW you might consider changing the name of your New model to something like Post. 'New' is a bit hard to talk about, and a little confusing since 'new' usually means something completely different in a programming context.
if one presses reply, the reply form appears,
I think this is the part you need to work on. When the reply form is rendered it needs to have the id of the post being replied to with it (the instance of New). This presumably has to come via the request unless you have some other way of keeping track of it?
Something along the lines of:
def save_reply(request):
...
else:
form = ReplyForm()
form.reply_to = New.objects.get(id=request.REQUEST["post_id"])
Thus you'll need to ensure that the link which causes the form to be rendered includes a 'post_id' param (or similar - presumably you already have an equivalent, used for displaying the post in question?).
Alongside the
widgets = {
'reply_to': forms.HiddenInput),
}
code this should render the form as you need it.
The post id has to be passed all the way along the chain
--post_id-> Render Post --post_id-> Render Reply Form --post_id-> Store Reply