Comments (9)
How are you building the choices for the CharField? Is there a different form field that converts the values to a ChoiceField and back?
Can you show a code example?
from django-semanticui-forms.
We are sending quotes to customers, and each quote has one of a customer's contacts associated with it. Note in the first model below that recipient is a CharField. We are filling it with comma-separated values (email addresses), and we also allow users to add emails that aren't in the database.
class EmailMessage(models.Model):
sender = models.CharField(max_length=255, null=True, blank=True)
recipient = models.CharField(max_length=255, null=True, blank=True)
subject = models.CharField(max_length=255, null=True, blank=True)
content = models.TextField(null=True, blank=True)
class ContactMethod(BaseModel):
contact = models.ForeignKey(Contact)
method_type = models.ForeignKey(ContactMethodType, null=True, blank=True)
label = models.CharField(max_length=255, null=True, help_text="Further clarification of type e.g. 'Home', 'Work', etc.", blank=True)
value = models.CharField(max_length=255, null=True, blank=True)
is_active = models.BooleanField(default=True, editable=False)
Contact method types are email, phone, fax. The form field is rendered like this:
<script type="text/javascript">
$(function(){
$('#recipient').dropdown({allowAdditions: true});
});
</script>
{% for field in form %}
{% if field.name == 'recipient' %}
<div class="inline field">
<label for="recipient">To</label>
<div id="recipient" class="ui multiple search selection dropdown">
<input name="recipient" type="hidden" value="{{ field.initial }}">
<i class="dropdown icon"></i>
<input class="search" autocomplete="off" tabindex="0">
<div class="default text">Choose or enter email(s)</div>
<div class="menu">
{% for e in quote.contact.active_emails %}
<div class="item" data-value="{{ e.value }}">{{ e.contact.first_name }} {{ e.contact.last_name }}</div>
{% endfor %}
</div>
</div>
</div>
{% else %}
{% render_field field _inline=1 %}
{% endif %}
{% endfor %}
Note this in the above: <div class="item" data-value="{{ e.value }}">
. Instead of using the id of the contact method, we're using the value (in this case the email address since we're only working with emails). Therefore, it is the above data-value
into which I would like to be able to place the value of the value
field of the ContactMethod model.
from django-semanticui-forms.
While this would ideally be worked into EmailMessage's ModelForm itself, it's less code and easier just to put it in the view.
I'm not at my dev desktop right now to test anything out, but I think you could do something like this.
def my_view(request):
form = EmailSomethingModelForm()
quote = Quote.objects.filter(...).first()
form.fields["recipient"] = forms.ModelMultipleChoiceField(
queryset=quote.contact.active_emails, to_field_name="value"
)
Let me know if that works for you
utils.py#L46
from django-semanticui-forms.
Thanks for pointing me in the right direction - I wasn't familiar with to_field_name. When I tried your suggestion in views, it gave this error message, which I understand: 'instancemethod' object is not iterable. So therefore it doesn't look like I can set it in the view. I did prefer to add the declaration to forms.py anyway, and I was already setting the queryset in forms.py, so I just set it up in forms like this:
Under Meta:
widgets={ 'recipient': forms.SelectMultiple}
In init and after super():
self.fields['recipient'].queryset = contact.active_emails()
self.fields['recipient'].to_field_name = 'value'
HOWEVER, while the recipient field (declared in models.py as models.CharField) is rendered correctly as a "ui multiple selection dropdown", it WILL NOT render the menu when I use {% render_form form %}. It just renders an empty <div class="menu"></div>
. Could this be a tiny shortcoming in django-semanticui-forms? Here is the only thing that it renders - copied straight from the rendered code (even though there are two results in the queryset [I've written that to a log to verify it] and the same two results are initialized in the recipient field):
<div class=" field">
<label for="id_recipient">Recipient</label>
<div class="ui multiple selection dropdown" tabindex="0">
<select multiple="multiple" class="search" id="id_recipient" maxlength="255" name="recipient"></select>
<i class="dropdown icon" tabindex="0">
<div class="menu" tabindex="-1"></div>
</i>
<div class="default text">Select</div>
<div class="menu" tabindex="-1"></div>
</div>
</div>
Odd that it's rendering two empty menus - and one of them is within tags. Also, when I use my previously set up html for hand-rendering the field, it works fine with the above in forms.py - so it seems that the problem has to be in the rendering of the SelectMultiple on an element that is declared as models.CharField.
from django-semanticui-forms.
I see what's happening here. queryset
won't be evaluated because it's not a Model*
field. When you're changing the widget to SelectMultiple
, there are no "choices" set so that's why there are no options.
Select / SelectMultiple
widgets are made to put out select
and option
nodes.
And also confusingly, SelectMultiple
widget is only for an array of values meaning Django will tell you that a custom entry is invalid.
However, you can use a TextInput
widget, and override the wrapper to use the dropdown wrapper. Afterwards changing the style to contain "multiple" and "search" should give you the results you want.
from django.db.models import Value
from django.db.models.functions import Concat
class ModelForm(forms.ModelForm):
class Meta:
widgets = {"recipient": forms.TextInput(attrs={
"_style": "search multiple", "_override": "Select"
})}
def __init__(self, *args, **kwargs):
super(__class__, self).__init__(*args, **kwargs)
self.fields["recipient"]._choices = (
contact.active_emails()
.prefetch_related("contact")
.annotate(full_name=Concat("contact__first_name", Value(" "), "contact__last_name"))
.values_list("value", "full_name")
)
Let me know!
from django-semanticui-forms.
Getting the error below. Below this first screen shot is another that could be helpful. Should line 64 in your utils.py be choices._insert(...) ?
from django-semanticui-forms.
Oops! Try making the queryset an actual list
self.fields["recipient"]._choices = list(
contact.active_emails()
.prefetch_related("contact")
.annotate(full_name=Concat("contact__first_name", Value(" "), "contact__last_name"))
.values_list("value", "full_name")
)
from django-semanticui-forms.
That did it except for one tiny item - it is automatically rendering a '--------' as the first item in the dropdown. I don't think that this should happen for a SUI multiple dropdown. At this point I'm just removing it upon page load with JS.
Also, the ContactMethod model has a 'label' field that can be used to designate 'home', 'work', etc. Therefore, the final rendering ended up like this:
self.fields["recipient"]._choices = list(
contact.active_emails()
.prefetch_related("contact")
.annotate(full_name=Case(
When(Q(label__isnull=False),
then=Concat("contact__first_name", Value(" "), "contact__last_name", Value(' ('), "label", Value(")"))
),
default=Concat("contact__first_name", Value(" "), "contact__last_name")
)
).values_list("value", "full_name")
)
That lets us, in the dropdown, distinguish between the types of emails for the same person.
Thank you for your incredible responsiveness and help on this. The above seems pretty deep to me - it's a shame this wasn't on StackOverflow. If you'll reply to acknowledge receipt of this final message, then I'll close it out. Thanks again!
from django-semanticui-forms.
Cool! I'm glad it worked out for the most part.
In a bit I'll take a look at the empty value being thrown in there.
from django-semanticui-forms.
Related Issues (20)
- Checkboxes are requiring intitialization with Javascript HOT 3
- Property added in forms.py does not come through to field HOT 1
- Metadata on <input type="number"> HOT 4
- Layout Requested HOT 3
- Placement of classes in forms.py HOT 2
- Formsets HOT 1
- How to render icon inside search selection dropdown? HOT 1
- Initial ChoiceField value ignored when boolean
- Field div could have id allowing easily hooking up some JS
- ChoiceField breaks if choices is a callable
- Choice fields break with non-ascii choices
- ChoiceField Search always returns undefined HOT 1
- How to set style on FormSet?
- ModelChoiceField dropdown does not work
- Extend library
- Hidden fields render visible HOT 2
- Inline fields HOT 2
- Typo in Attributes explanation HOT 1
- Django forms empty_label not rendering in dropdown HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from django-semanticui-forms.