def resume_edit(request, r_id):
r = Resume.get.object(pk=r_id)
resume = ResumeModelForm(instance=r)
resume.fields['email'].widget.attrs['readonly'] = True
return render(request, 'resumes/resume.html', context)
I tried to do this but its not working, i know how to do it in Forms.py , but i want to know in views its possible or not?
Im using Django 2.0
Yes, since django-1.9, a field has a .disabled attribute that can be set to True:
So we can use:
def resume_edit(request, r_id):
r = Resume.get.object(pk=r_id)
resume = ResumeModelForm(instance=r)
resume.fields['email'].disabled = True
return render(request, 'resumes/resume.html', context)
This will not only ensure that the HTML of the corresponding form parts is disabled, but will also ignore possible changes when you post the Form (note that you of course first need to disable the field).
Since the render(..) call produces the HTML, the field should of course be altered before it is rendered, validated, or .save()'d.
The .disabled attribute is typically better than using readonly, etc. Since some form elements have a special way to disable the element at the HTML level (some use disabled instead). Furthermore like said before it does not only disable the form element at the HTML level. If a user wants to post malicuous values, then the form will simply ignore these.
Related
I have 3 forms with Checkboxes to configure the desired form (Final_Form). After the user chooses the desired fields (in form1, form2 and form3), i want to delet all fields that are not required in the final form and render the final form. The reason for that is, that i have 3 Subkategories with around 12 possible values, in each form (form1-form3) the user can choose one ore more subkategories. The subcategories are standardized and are used to describe a clinical incident. The users wished to have the subcategories (1-3; form1-form3) seperated and always with an example (right-side of the screen in an anther bootstrap col).
The finalform is than a combination of the the subcategories that matches best to describe the clinical incident. All fields in the Final_Form are TextAreaFields. The Input for the TextAreaFields is stored in a sqlite-db.
Here is how i tried it:
app.py:
if request.method == 'POST' and form1.form1Submit.data:
OnePointOne = form1.OnePointOne.data
if not OnePointOne:
del Final_Form.OnePointOne
return render_template('Form2.html', form2 = form2)
if request.method == 'POST' and form2.form2Submit.data:
TwoPointTwo = form2.TwoPointTwo.data
if not TwoPointTwo:
del Final_Form.TwoPointTwo
return render_template('Form3.html', form3 = form3)
if request.method == 'POST' and form3.form3Submit.data:
ThreePointThree = form3.ThreePointThree.data
if not ThreePointThree:
del Final_Form.ThreePointThree
return render_template('Final.html', Final_Form = Final_Form)
forms.py:
class form1(FlaskForm):
OnePointOne = BooleanField('Effect')
form1Submit = SubmitField('Submit Category')
class form2(FlaskForm):
TwoPointTwo = BooleanField('Measure')
form2Submit = SubmitField('Submit Category')
class form3(FlaskForm):
ThreePointThree = BooleanField('Result')
form3Submit = SubmitField('Submit Category')
class Final_Form(FlaskForm):
OnePointOne = TextAreaField('Example Effect')
TwoPointTwo = TextAreaField('Example Measure')
ThreePointThree = TextAreaField('Example Result')
Final_FormSubmit = SubmitField('Submit incident')
The problem is, that the formfields of the Final_Form objects dont get deleted (only inside the if statements). I am very thankful for every hint or explanation.
As you are showing three separate pages, there are three separate requests.
You Final_Form object cannot be simply kept between these requests.
I don't fully understand why you configure your third form this way, it would be helpful to explain your use-case for better advice.
Without more information, I'm thinking of some ways to do this:
You make it one page/request, where you go from form to form using AJAX.
You make it one page with all forms, controlling visualisation with JS + CSS
You save your desired value somewhere
probably you can keep it in cookie (session object)
or in database, if that makes sense in your context
Also, please include whole code of this function - it's not clear how you create those forms you use.
I'm trying to wrap my head around an issue I'm having.
I want to present the users with a page in which they can look up a user by entering his username.
Yet I can't wrap my head around how to do this. Do I provide a function in my view in which a query is executed that retrieves a user from the database? For example retrieve his username or id and go to his profile page? I can't seem to grasp how to do this, I have been looking for examples on this but I can't find anything so I hope someone here can help me out!
Yes, at the simplest level you would have a view that accepts a form submission which takes the value of the field and does something like User.objects.get(username=my_variable) and returns the results, if any. You should wrap the call in a try/ except block so your view doesn't blow up if no such user exists with that username. Django provides a shortcut function for doing just this, so instead of the line above you could do user = get_object_or_404(User, username=my_variable). Your whole view would look something like
from django.shortcuts import render, get_object_or_404
def username_search(request):
# if there are any form values sent in a GET
if request.GET:
my_variable = request.GET.get('username', '')
user = get_object_or_404(User, username=my_variable)
else:
user = None
return render(request, 'some_template.html', {'user': user}
In reality you might also create a Django form to do some validation on the submissions and make it easier to render your form.
I have an app that serves to update certain fields of a model. There are 4 possible fields that could be updated: resolution, upload4, upload5, and upload6. The upload fields are NOT required. If I do not include the request.FILES line, the uploaded file will not be saved to the database, but it seems like because I've included it, I need to always upload the 3 files, even though they are not required. The exception I am getting is "MultiValueDictKeyError" on the POST. How can I fix this? I want the option to add 3 files, but I don't want to have to every time. I understand how to make a field not required, I don't know how to code the request.FILES to understand that it is not required.
views.py
#login_required(login_url='/login/')
def report(request, case_id):
form = ReportForm()
case = get_object_or_404(Incident, pk=case_id)
# if this is a POST request we need to process the form data
if request.POST:
# create a form instance and populate it with the data from the request:
form = ReportForm(request.POST)
if form.is_valid():
resolution = (form.cleaned_data['resolution']) # grabbing action_taken from user input
case.resolution = resolution
case.upload4 = request.FILES['upload4']
case.upload5 = request.FILES['upload5']
case.upload6 = request.FILES['upload6']
case.status = Status.objects.get(status='closed')
case.save(update_fields=['resolution', 'status', 'upload4', 'upload5', 'upload6'])
context = { 'case': case,
'form': form}
return HttpResponseRedirect(reverse('dashboard_app:dashboard'))
template = "report.html"
#form = CaseForm()
context = { 'case': case,
'form': form}
return render(request, template, context)
The point is that you are ignoring the validation that form does, and going straight back to the data from the request. So, yes, that will break if the forms are not there. But this is exactly why we use forms.
case.upload4 = form.cleaned_data['upload4']
etc.
It would be even easier if you used a ModelForm; then you could pass case as the instance argument of the form, and just do form.save(), replacing almost all the code inside your is_valid block.
This will solve the problem.
case.upload4 = request.FILES.get('upload4')
case.upload5 = request.FILES.get('upload5')
case.upload6 = request.FILES.get('upload6')
I have written what I hope to be a re-usable Django app, but I have a bit of a conundrum on how to make the post form handling flexible. The simplified version of my view code looks like:
def do_form(request, entity_id, template_name, success_url):
form = MyForm(request.POST or None)
if request.method =='POST':
if form.is_valid():
#do some business logic
return HttpResponseRedirect(finished_url)
return render_to_response(template_name,
{'form': form},
context_instance=RequestContext(request))
I have followed the advice in James Bennets book "Practical Django Projects" and so you can now configure the template and the success url in the url conf, so for example my url conf could look like this:
urlpatterns = patterns('myapp.views',
url(r'^do/(?P<entity_id>\d+)/$',
view = 'do_form',
name = 'do_form_view',
kwargs={'template_name':'form.html',
'success_url':'/finish/'},),
url(r'^finish/$',
view = 'finish',
name = 'finish_view')
)
This is all very well and good but when I have come to use this in my real world application I find myself in a situation that this form sits in the middle of some workflow, and I want the success url to be something like /continue/<workflow_id>/ , and the problem is that you can only have a hardcoded url in the url conf, and the workflow_id will vary every time I hit the do_form code.
Can any one suggest a way to get around this?
You can achieve that by changing the following..
in do_form() in views.py
change the return HttpResponseRedirect to
return HttpResponseRedirect('/continue/%s' %(workflowid))
And in urls.py, you can have
url(r'^continue/(?P<workflowid>\d+)/$',
view = 'continue',
name = 'continue_view')
and for the continue() view in views.py
def continue(request, workflowid=None):
...
This way.. whenever you access the url /continue/ without a number, workflowid will be equal to None. Every other time when you do have a workflowid attached for e.g. like /continue/23/ , then inside your continue() view you can access that id through the variable workflowid.
When you pass a hypothethical "flexible" success_url to a view, that view MUST supply the desired identifier. So if you mismatch the URL and the view, we can't avoid having a "breach of contract" between the two.
Therefore if we are to have flexible URLs, some kind of contract shall have to be enforced, and there will be no loss of generality if we do this through a special syntax for URLs:
'finished_url': '/finish/<workflow_id>/'
Then, of course, the view shall have to instantiate the variable through a string replacement to honor its side of the contract: instead of
return HttpResponseRedirect(finished_url)
you will have
return HttpResponseRedirect(finished_url.replace('<workflow_id>', WorkflowID))
This should keep things reasonably simple.
When reusing code, you will have to keep in mind that <workflow_id> is whatever that app uses to call workflow id, and that's why I use a complicated string such as workflow_id instead of id or maybe $1.
EDIT: I was going to add the code for the next step (intercepting workflow ID in argument of finish), but I see that keithxm23 beat me to the punch :-)
You can do it the same way people have been "overriding" Django's function-based generic views for years: simply wrap the view in another view:
def custom_do_form(request, entity_id, template_name, success_url):
template_name = some_method_to_get_template()
return do_form(request, entity_id, template_name, success_url)
I need some guidance on best practice implementation of the following.
I have a scenario where I am building an app, but if it matches a certain "category" or "locale" and want to redirect it to a page in between else just go the normal route.
Here is my simple views.py
if form.is_valid():
...
kwargs = {'project_id':project_id, 'categories':request.POST['categories'], 'locale':request.POST['locale']}
process_se(request, **kwargs)
return HttpResponseRedirect(obj.next_url)
Here is what I have in my models.py file but it seems to be very inconsistent.
Is there a better way to handle this request?
def process_se(self, request, **kwargs):
if "All" or "Sweden" in kwargs['locale']:
if "Technology" or "Internet" in kwargs['categories']:
next_url = request.build_absolute_uri(reverse('project_new_se', kwargs={'project_id': self.id}))
else:
next_url = request.build_absolute_uri(reverse('project_new_step2', kwargs={'project_id': self.id}))
self.next_url = next_url
UPDATES:
I am using forms.ModelForm, categories and locales are ManyToManyField's
I have simulated a for in the shell and still seem to get no result
Here is the cleaned_data output
f.cleaned_data
{'locale': [<Locale: Sweden>, <Locale: All>], 'categories': [<Category: Technology>, <Category: Internet>]}
Although running this for fields in the form seem to render perfectly fine based on your solution
I originally proposed putting this code in the form class, but ApPeL revised the question to point out that locale and categories are many-to-many fields on the model. So now I suggest putting a method like this in your model:
def requires_swedish_setup(self):
"""
Return True if this project requires extra Swedish setup.
"""
return (self.locale.filter(name__in = ('All', 'Sweden')).exists())
and self.categories.filter(name__in = ('Technology', 'Internet')).exists())
and then implementing your view like this:
if form.is_valid():
project = form.save()
next = 'project_new_step2'
if project.requires_swedish_setup():
next = 'project_new_se'
next_url = reverse(next, kwargs={'project_id': project.id})
return HttpResponseRedirect(next_url)
Some notes:
I'm assuming that Locale and Category objects have name fields (if not, use whatever field contains the name you are testing).
It's not a good idea to read form data out of request.POST (widgets haven't had a chance to run, and it hasn't been validated): it's better to use form.cleaned_data.
You don't need to call request.build_absolute_uri in this case: it's fine to feed the result of reverse directly to HttpResponseRedirect.
"All" or "Sweden" in kwargs['locale'] is probably not what you mean: it parses like "All" or ("Sweden" in kwargs['locale']) and so is always true.