I'm creating a panel where a user can assign an assignment to other users. I'm attempting to build this with the ModelMultipleChoiceField and a form called AssignedUsersForm
forms.py
class AssignedUsersForm(ModelForm):
class Meta:
model = Assignment
fields = ['users']
custom_users = CustomUser.objects.all()
users = forms.ModelMultipleChoiceField(queryset=custom_users, widget=forms.CheckboxSelectMultiple())
template
<form method="post" id="assigned_users_form">
{% csrf_token %}
{{ assigned_users_form.errors }}
{{ assigned_users_form.non_field_errors }}
<div class="fieldWrapper">
{{ assigned_users_form.content.errors }}
{% for user in assigned_users_form.users %}
<div class="myradio">
{{ user }}
</div>
{% endfor %}
<br>
<div style="text-align:center;">
<input class="input-btn" type="submit" value="Save" name='submit_assigned_users_form'>
</div>
</form>
I've successfully rendered each of the options for CheckboxSelectMultiple individually in my HTML.
Unfortunately, each iteration of 'user' renders CustomUser object (#) - the default name for the object.
From what I understand, the Checkbox widget does not pass the original queryset to the template. Thus, I'm unable to access the model attributes of each user and render information such as name, profile picture, etc.
Is there a method of accessing the actual object that's represented in the checklist, instead of the _ str _ value?
I've considered running a parallel iteration of queryset in the template, but I'm not sure if that's possible in Django.
I've also considered creating custom template tags to access each object based on the id in str, but that seems like overkill?
Is there a more intuitive method that I'm missing here?
I found a work around by creating a template_filter that takes the checkbox value and returns the corresponding object to the template.
template_tags.py
#register.filter(name='get_user')
def get_user(user_id):
user = CustomUser.objects.get(pk=user_id.value)
return user
template
<form method="post" id="assigned_users_form">
{% csrf_token %}
{{ assigned_users_form.errors }}
{{ assigned_users_form.non_field_errors }}
<div class="fieldWrapper">
{{ assigned_users_form.content.errors }}
{% for user in assigned_users_form.users %}
<div class="myradio">
{% with customuser=user.data.value|get_user %}
{{user.tag}} {{customuser.first_name }}
{% endwith %}
</div>
{% endfor %}
<br>
<div style="text-align:center;">
<input class="input-btn" type="submit" value="Save" name='submit_assigned_users_form'>
</div>
</form>
Essentially, this code looks at the checkbox widget iteration (user) and gets the value, passes that value to the template tag and then returns the associated object back to the page.
Not the best solution given that you're repeating the query search for each object, rather than gathering them all in one go. But this is the best I could come up with.
Related
I'm new to Django and trying to solve a simple problem. I looked through many similar questions but still is not able to find the solution.
In my template I have a few checkboxes which are built according to records in the database.
My Model is:
class Status(models.Model):
statusCode=models.IntegerField()
definition = models.CharField(max_length=30)
def __str__(self):
return f"{self.definition}"
In my view I'm getting the values of checkboxes that user chose and store them in the list:
if request.method == "POST":
status_list = request.POST.getlist('statuses')
I pass this list as a context:
return render(request, 'search/index.html',{"chosen_statuses": status_list,
"statuses": Status.objects.all()}
Then I want to display results of the query keeping the checkboxes that user selected - selected.
This is my code in template:
<div>
<label for="status">Include statuses: </label>
{% for status in statuses %}
<input type='checkbox' value='{{ status.id }}' name='statuses'
{% if status.id in chosen_statuses %}
checked
{% endif %}>
<label for='{{ status }}'>{{ status }}</label>
{% endfor %}
</div>
The list "chosen_values" contains the user's choices as needed, and the results of the query are correct. But the checkboxes are left unchecked.
I would appreciate some help.
Well, after hours, probably this a newbee mistake.
It turned out I cannot pass list to template to compare its values to query object.
In my views I should pass the query object instead (which takes list as a parameter in filter:
"chosen_statuses": Status.objects.filter(statusCode__in = status_list)
and then I adjust if statement in template:
<div>
<label for="status">Include statuses: </label>
{% for status in statuses %}
<input type='checkbox' value='{{ status.id }}' name='statuses'
{% if status in chosen_statuses %}
checked
{% endif %}>
<label for='{{ status }}'>{{ status }}</label>
{% endfor %}
</div>
I have a Profile Object which has a many to many reationship with a Hobbies object. A profile is used for creating a User. Each User can also have a load of hobbies that are predefined. What I want to do is let Users pick some hobbies they are interested in. However, I am not sure how to display all these Hobbies and let Users pick them on the actual display. Here is the code:
TYPES = (
("Football", "Football"),
("Cricket", "Cricket"),
("Swimming", "Swimming"),
("Cycling", "Cycling")
)
class Hobby(models.Model):
myfield = MultiSelectField(choices = TYPES)
And the User :
class Profile(models.Model):
email = models.CharField(max_length=200)
hobbies = models.ManyToManyField(Hobby)
And the HTML code I use is here:
<span class="fieldname">Hobbies</span>
{% for hobby in all_hobbies %}
<input type="checkbox" name={{hobby}} value={{hobby}}> {{hobby}}<br>
{% endfor %}
However this only displays
What I want it to display is all the hobbies with the choices, instead of the whole Object. I am not sure how to do this and would appreciate any help.
Try doing something like
<span class="fieldname">Hobbies</span>
{% for hobby in all_hobbies %}
<input type="checkbox" name="{{ hobby.myfield }}" value="{{ hobby.myfield }}"> {{ hobby.myfield }}<br />
{% endfor %}
Under Hobby class, you should add the str method that will display the value of your hobby instead of 'Object'
def __str__(self):
return self.myfield
You can also use __unicode__ instead of __str__ if you are with Python 2.x
Edit:
After I read again your question, I understood that your problem was specifically not having several checkboxes for the multiple choices you have, here is how you can show all the choices, you should pass the hobbies field as a context :
{% for value, text in form.hobbies.field.choices %}
<div class="ui slider checkbox">
<input id="id_hobbies_{{ forloop.counter0 }}" name="{{ form.hobbies.name }}" type="checkbox" value="{{ value }}"{% if value in checked_hobbies %} checked="checked"{% endif %}>
<label>{{ text }}</label>
</div>
{% endfor %}
I'd like to add a single form input field to a DetailView that will append tags to my model. I'm not sure if I need a separate view for that, or I can simply add a form. Using django-bootstrap3, I have the following:
<div class="row">
<form action="add-tag" method="post"
enctype=multipart/form-data>
{% csrf_token %}
{{ form.media }}
{% bootstrap_field form.tags show_label=False %}
<input type="submit" value="{% trans "submit" %}"/>
</form>
</div>
forms.py:
class MyModelAddTagsForm(forms.ModelForm):
class Meta:
model = models.MyModel
fields = ('tags',)
I get the error:
BootstrapError at /someurl/1/view
Parameter "field" should contain a valid Django BoundField.
I'm not sure what else I exactly need. A view and url or modifying my DetailView? Or using an UpdateView instead?
I have a simple form which uses a SessionWizardView to spread it over a number of pages. Below is an example of one of the questions.
first_name = forms.CharField(max_length=100, label='What is your first name?', error_messages={'required': 'Please enter your first name'})
Which renders out as
<label for="id_0-first_name">What is your first Name?</label>
<ul class="errorlist">
<li>Please enter your first name</li>
</ul>
<input id="id_0-first_name" maxlength="100" name="0-first_name" type="text" />
Can anyone tell me hwo to change the error output so that it is in <p> Paragraph </p> format rather than <li> List item </li> format?
I am using Django 1.6.2
You'll have to create a class that does renders the HTML as you would want it. See the docs here.
The example from the docs:
from django.forms.util import ErrorList
class DivErrorList(ErrorList):
def __unicode__(self):
return self.as_divs()
def as_divs(self):
if not self: return u''
return u'<div class="errorlist">%s</div>' % ''.join([u'<div class="error">%s</div>' % e for e in self])
f = ContactForm(data, auto_id=False, error_class=DivErrorList)
f.as_p()
You can do as #schillingt suggested and create your own error list class.
Or, if you want to handle this in your template, you can use something like:
<form method="post" action="/some-view/">
... other fields, etc. omitted ...
<!-- The label and form field -->
{{ form.first_name.label_tag }}
{{ form.first_name }}
<!-- Output any errors -->
{% for error in form.first_name.errors %}
<p>{{ error }}</p>
{% endfor %}
... other fields, etc. omitted ...
<button type="submit">Submit</button>
</form>
Update
In order to do this in a cleanly repeatable way, make a template named form-field.html:
{{ field.label_tag }}
{{ field }}
<!-- Output any errors -->
{% for error in field.errors %}
<p>{{ error }}</p>
{% endfor %}
Then, update your main template:
<form method="post" action="/some-view/">
... other fields, etc. omitted ...
{% with field=form.first_name %}
{% include "form-field.html" %}
{% endwith %}
... other fields, etc. omitted ...
<button type="submit">Submit</button>
</form>
You can then make updates to the single form-field.html template and update all of your forms, and it makes your main template a bit simpler
I am working with forms sets, I was wondering how one could use
<input type='hidden'
inside a form set. (Django formsets allow us to use multiple forms instances of a single form)
Its easy to do in normal single form where you just put the field with the type='hidden' and name='fieldname' e.g.
<input type='hidden' name='user' value='{{request.user.id}}'>
Dealing with formsets is a bit catchy, how to achieve the same behavior with the forms sets?
Views.py
PictureFormSet = modelformset_factory(Picture, form=UpdatePictureForm, extra=0)
formset_qset = Picture.objects.filter(id__in=[15, 16, 17, 18, 19, 20])
if request.method == POST:
ctx['form_set'] = PictureFormSet(request.POST, queryset=formset_qset)
ctx['form_set'].save()
ctx['form_set'] = PictureFormSet(queryset=formset_qset)
return render_to_response('temp tabs.html', context_instance=RequestContext(request, ctx))
Template
<form method="POST" action="" class="form-horizontal">
{% for form in form_set %}
{{form.id}}
<div class="form-group">
<label class="col-lg-2 control-label">
{% with form.meta_data.value|load_meta_data as meta %}
<div class="portfolio-item video-container">
<a class="" href="{% url 'view_image' form.id.value %}?in=pro">
<i style="background-image: url({{ meta.image_size.thumbnail_small }});"
class="ds-thumbnail-container"></i>
</a>
</div>
{% endwith %}
</label>
<div class="col-lg-8 ">
{{ form.name }}
</div>
</div>
{% endfor %}
{{ form_set.management_form }}
{% csrf_token %}
<input type="submit" value="Submit">
</form>
Explanation
Here in this code, We are rendering images from the database for editing there names. we have url information inside the meta_data, so we have selected
fields=['id', 'meta_data', 'name']
We want to change/Update the name, but not the meta_data
This code works fine for the most part, but how i want to keep one field unchanged for the modal?
I have meta_data field that I am using in the template, but i do not want that field to be modified, that value should be in the form like this
{{form.meta_data}}
This turns it into text area, with different name and id. and it expects it be changing. but i want to declare a hidden field and sets its value to the form.meta_data.value
If you have any questions regarding this please do not hesitate to ask.
Thanks.