Problem with 'Cannot assign' error in django - python

I have something like this in my template.
<form action="" method="POST">
{% csrf_token %}
<select name='section'>
{% for item in all_sections %}
<option>{{ item.SectionName }}</option>
{% endfor %}
</select>
</form>
and in my view.py page:
obj=models.Section.objects.all()
context={
'all_sections':obj,
}
return render(request,'matab/add-service.html',context)
but i get this is error while saving data:
Cannot assign "'{item}'": "Services.Section" must be a "Section" instance.
also my models.py is like this:
class Section(models.Model):
SectionName=models.CharField(max_length=50)
SectionId=models.CharField(max_length=10)
class Services(models.Model):
Section=models.OneToOneField(
Section,
on_delete=models.CASCADE,
)
how can i solve it?

Services.Section is a OneToOneField, so you need to assign Section instance, not its name.
Depending on your code, it might work if you set the option value to the pk.
<select name='section'>
{% for item in all_sections %}
<option value="{{ item.pk }}">{{ item.SectionName }}</option>
{% endfor %}
</select>
As Iain suggests in the comments, it would be better to change your views to use Django forms instead of manually render select inputs.

Related

Django template language if tag not working

I have a django template with an update form, for an invoices application.
I want to allow to update the record after it was saved.
One of the model fields is manager which is a foreign key:
class Invoice(models.Model):
manager = models.ForeignKey(User, on_delete=models.CASCADE,null=True ,blank=True)
The problem is that I don't to display the manager's user id, but his/her first name, so I want to populate the select tag with all manager's first name. I have tried this:
<select id="id_manager" name="manager">
{% for manager in managers %}
{{ manager }} || {{ initial_manager }}
{% if manager == initial_manager %}
<option value="{{ manager.user.id }}" selected>{{ manager.user.first_name }}</option>
{% else %}
<option value="{{ manager.user.id }}">{{ manager.user.first_name }}</option>
{% endif %}
{% endfor %}
</select>
This is the views.py part:
managers = Profile.objects.filter(Q(role = 'manager') | Q(role = 'cfo') | Q(role = 'ceo') | Q(role = 'sec'))
projects = Project.objects.all()
form = InvoiceForm(instance = invoice)
initial_manager = invoice.manager
return render(request, "invoice/update.html", {'form': form, 'managers':managers, 'projects':projects, 'initial_manager':initial_manager})
I have added this to see the values of the variables:
{{ manager }} || {{ initial_manager }}
and I see for example " 102 || 102 ", which means that they are equal but the if part doesn't run, it always goes to the else part. It doesn't matter what I've tried, I have tried passing initial_manager as a string, comparing manager to " 102 " or to "102" or 102, but nothing works.
Can someone help me?
if both are the same value but it's returning false when using if
then try modify the code to make them both float using
floatformat
for your case
{% if manager|floatformat:"0" == initial_manager|floatformat:"0" %}
<option value="{{ manager.user.id }}" selected>{{ manager.user.first_name }}</option>
{% else %}
<option value="{{ manager.user.id }}">{{ manager.user.first_name }}</option>
{% endif %}
this will make them both float with 0 decimal so it's like converting them into an integer.
see this also
Thanks for the help. I've used stringformat instead of floatformat.
<select id="id_manager" name="manager">
{% for manager in managers %}
{{ manager }} || {{ initial_manager }}
{% if manager|stringformat:'s' == initial_manager|stringformat:'s' %}
<option value="{{ manager.user.id }}" selected>{{ manager.user.first_name }}</option>
{% else %}
<option value="{{ manager.user.id }}">{{ manager.user.first_name }}</option>
{% endif %}
{% endfor %}
</select>
Now it works. I appreciate your help

get values from html select in views with django

I would like to get the value and even the string if possible of the selected value in my HTML file.
index.html
<form action="#" method="post">
<select id="drop1">
<option disabled selected value> -- select value -- </option>
{% for i in df %}
<option value="{{ i }}">{{ i }}</option>
{% endfor %}
</select>
</form>
views.py
def index(request):
if request.method == 'POST':
selected_value = request.POST.get('drop1')
print(selected_value)
else:
return render(request, 'index.html', {'df': df.designation_list})
With this, nothing is returned. I saw that I have to use <form></form> to get an html value but I can't find what to put in the action= field.
Can you see what is missing in my code?
Thanks in advance
The action attribute specifies where to send the form-data when a form is submitted.
In your case, you have to add the url of the view that will hand that data. For example:
<form action="{% url 'index' %}" method="post">
<select id="drop1">
<option disabled selected value> -- select value -- </option>
{% for i in df %}
<option value="{{ i }}">{{ i }}</option>
{% endfor %}
</select>
</form>
Note: Change the index with the name you specified in your URL pattern.

Django 3 Pass Get The Selected Value Dropdown select option

Django dropdown option selected. Get data in template and select option. My code is.
views.py
def home(request):
compType = Type.objects.all()
comptype = request.GET.get('comp_type')
context = {
'compType': compType
}
return render(request, 'compapp/dashboard.html', context)
search.html
<div class="form-group">
<label>Type</label>
<select class="form-control select2" name="comp_type" style="width: 100%;">
<!-- <option disabled="true" selected >Company Type</option> -->
{% for i in compType %}
<option value="{{ i }}" {% if request.GET.items == i %}selected{% endif %}>{{ i }}</option>
{% endfor %}
</select>
imagine you have a form, (search form), that user filled it and submitted. you received this form and made the queryset and then you want to show a page contains the search results and, also the form has its fields filled with selected values. So you have to pass that values to the results page too! 'request.GET.items' is not working ever.
what you should do is:
if the had a field named 'dr_select', in the views.py search function you should get that fields value via
selected = get_object_or_404(Type, id==int(request.GET['dr_select']))
then pass 'selected' to the results page, and then in that template you can do what you want.
{% for item in compType %}
<option value="{{ item.id }}"
{% if selected == item %}selected{% endif %}>{{ item } </option>
{% endfor %}
*note: because I used 'item.id' for 'value' in 'option' tag, so in backend I have to filter the Model by id too.

How to get all the options submitted by form

How to get all the options submitted by the form in Django, this is the form which I used.
{% extends 'quiz/base.html' %}
{% block content%}
<h1>You are at quiz page</h1>
<form action="{% url 'quiz:process_data' %}" method="post">
{% csrf_token %}
{% for question in question_set %}
<h3>{{question.id}}.{{question.question_text }}</h3>
{% for option in question.options_set.all %}
<input type="radio" name="choice{{question.id}}" value="{{ option.options}}" > {{option.options}}<br>
{% endfor %}
{% endfor %}
<input type="Submit" name="Submit">
</form>
{% endblock%}
I tried selected_choice=request.POST ,but getting this as output csrfmiddlewaretokenchoice1Submitchoice3. How can I solve this? Thank you
In django request.POST is dictionary-like object, see details here.
So to obtain argument choice in view you can use following syntax:
selected_choice=request.POST.get('choice')
which return choice value or None in case this is empty.
Since request.POST is dict-like object you can use items() method to get all values and filter them:
for k, v in request.POST.items():
if k.startswith('choice'):
print(k, v)
this will print only those params with choice text in name.
selected_choice=request.POST.get('choice')
The above should work just fine, but if you're crazy, you can try this:
{% extends 'quiz/base.html' %}
{% block content%}
<h1>You are at quiz page</h1>
<form action="{% url 'quiz:process_data' %}" method="post" id= "crazyform">
{% csrf_token %}
{% for question in question_set %}
<h3>{{question.id}}.{{question.question_text }}</h3>
{% for option in question.options_set.all %}
<input type="radio" name="choice" value="{{ option.options}}" > {{option.options}}<br>
{% endfor %}
{% endfor %}
<input type="hidden" name="crazychoice" class="crazy" value="nothing">
<input type="Submit" name="Submit">
</form>
{% endblock%}
Then some JQuery:
$('#crazyform input').on('change', function() {
$(".crazy").val($('input[name=choice]:checked', '#crazyform').val())})
Everytime you click a radio button, the value of the hidden input field changes to the value of the selected radio button.
Then in your view you can:
selected_choice = request.POST.get("crazychoice", "")

Problem with logic in Django template

Supose this portion of a Django template. regs is a list of Reg objects. Reg.editable is a BooleanField.
I want to render a radio button per element in the list. If r.editable is False, the radio button must be disabled:
{% for r in regs %}
<input type="radio" value="{{ forloop.counter }}"
{% if forloop.first %}checked="checked"{% endif %}
{% if not r.editable %}disabled="disabled"{% endif %}/>
{% endfor %}
As you can see, I'm using forloop.first to check the first radio button, but this has a problem! What about if the first element has editable == False? The first radio button will be rendered disabled and chequed. If then a user submit "the form" I'll receive a value not expected.
Am I clear with the problem here? How can I rewrite this template to render as checked the FIRST ENABLED radio button?
Thanks
Djangos templating language doesn't give you a lot in the way of logic in the template (I've heard positive things about Jinja2 if you want to change that). There's also the "Smart" {% if %} tag which adds some more functionality and incidentally is being proposed for inclusion in Django 1.2.
As for solving this problem I would most likely move the logic over to the view. (Disclaimer: don't have the time to test this code snippet but it should provide the general idea)
def my_view(request, *args, **kwargs):
# QuerySet is fetched however it's done...
regs = Regs.objects.all()
# Wrap regs in display information
checked = False
radio_buttons = []
for r in regs:
if r.editable:
if not checked:
radio_buttons.append( { 'checked':True, 'enabled':True, 'object':r } )
# Set to true once
checked = True
else:
radio_buttons.append( { 'checked':False, 'enabled':True, 'object':r } )
else:
radio_buttons.append( { 'checked':False, 'enabled':False, 'object':r } )
# Then pass in radio_buttons for the value of regs down here
render_to_whatever(..., { 'regs':radio_buttons } )
In this case we've wrapped the QuerySet which will give our template some more details about rendering. The template becomes "dumb" now.
{% for r in regs %}
<input type="radio" value="{{ forloop.counter }}"
{% if r.checked %}checked="checked"{% endif %}
{% if not r.enabled %}disabled="disabled"{% endif %}/>
{% comment %} To access the original object use: {{ r.object }} {% endcomment %}
{% endfor %}
The real answer to this question is as follows:
Such logic has no place in the template. You can preprocess the context before passing it to the template, thus eleminating the need to do this using the (intentionally) crippled template engine logic.
In my opinion, what you are doing is wrong. I mean, django has perfectly fine forms api, why render the inputs directly then? Some might argue, that django's forms api is inflexible, but for this specific need it will undoubtely be sufficient.
And to reiterate - this kind of logic does not belong in the presentation layer. So don't put it there, it will bite you. In fact it already did.
Just adjust your ifs
{% for r in regs %}
{% if forloop.first %}
<input type="radio" value="{{ forloop.counter }}" checked="checked"/>
{% else %}
{% if not r.editable %}
<input type="radio" value="{{ forloop.counter }}" disabled="disabled"/>
{% endif %}
{% endif %}
{% endfor %}
PS: Your question did not clearly explain what you wanted. I made some reasonable assumption. Update the question if what you want is something else.
Similar to T. Stone's answer of doing this logic in the view, you could just add a new template variable that indicated the first checked radio:
def my_view(request, *args, **kwargs):
regs = Regs.objects.all()
checked_index = None
for i, reg in enumerate(regs):
if reg.enabled:
checked_index = i
break
# pass checked_index into the template...
Template:
{% for r in regs %}
{% ifequal forloop.counter0 checked_index %}
<input type="radio" value="{{ forloop.counter }}" checked="checked"/>
{% else %}
<input type="radio" value="{{ forloop.counter }}" {% if not r.editable %}disabled="disabled"{% endif %}/>
{% endif %}
{% endfor %}
Similar to becomingGuru but solving your problems:
{% for r in regs %}
{% if not r.editable %}
<input type="radio" value="{{ forloop.counter }}" disabled="disabled"/>
{% else %}
{% if forloop.first %}
<input type="radio" value="{{ forloop.counter }}" checked="checked"/>
{% endif %}
{% endif %}
{% endfor %}
It first checks if r is editable, and then checks if it is the first.
Regards.

Categories

Resources