I am trying to populate a form using a combination of str and lists. The string fields in the form populate without issue. However the selectfield in the form appears to only display the last entry given in the list it receives as if it's overwritten the previous contents in the form.
If the list (later converted to tuple) is :
[['one#email.com', 'two#email.com'], ['one#2email.com', 'two#2email.com]]
What gets displayed in the choices throughout the form will be:
one#2email.com
two#2email.com
I've tried various iterations but no luck so far.
class BulkAddFields(Form):
ip_addr = StringField(label='ip_addr')
dom_emails = StringField('dom_emails')
new_emails = SelectField('new_emails', coerce=int)
class BulkAddForm(FlaskForm):
incidents = FieldList(FormField(BulkAddFields))
submit = SubmitField('Submit')
form = BulkAddForm()
# i = str, d = str, n=list
for i, d, n, in data:
form.ip_addr = i
form.dom_emails = d
form.incidents.append_entry(form)
email = list(enumerate(n))
for sub_form in form.incidents:
sub_form.new_emails.choices = email
I've added a picture/link that shows how the string fields are replicated down the page as expected but the selectfield replicates the last item in the list only.
enter image description here
Try changing it from
new_emails = SelectField('new_emails', coerce=int)
to
new_emails = SelectField('new_emails', coerce=str)
You should then be able to pass the choices as a list. Let me know if that helps.
Below is the code that ended up working. Although I don't like adding a field to the form each time, knowing that the field is going to exist everytime I wanted to include it in the BulkAddFields but couldn't figure out how.
class BaseForm(FlaskForm):
#classmethod
def append_field(cls, name, field):
setattr(cls, name, field)
return cls
class BulkAddFields(BaseForm):
ip_addr = StringField(label='ip_addr')
dom_emails = StringField('dom_emails')
class BulkAddForm(BaseForm):
incidents = FieldList(FormField(BulkAddFields))
submit = SubmitField('Submit')
form = BulkAddForm()
for i, d, n, in data:
email = list(enumerate(n))
bulkfields = BulkAddFields()
bulkfields = bulkfields.append_field('new_emails',
SelectField('New Emails', choices=email))
form.ip_addr = i
form.dom_emails = d
form.incidents.append_entry(form)
Picture with repeating selectfield for New Emails
New to python and self-taught so I'm probably going about this horribly wrong but I'm trying to find the best way to list out objects while also placing them in a list. I was advised to find a way to do this by a friend to avoid double entry of creating my object then typing my object's name in. I'm open to any critiques and advice, thanks!
The way I have it set up now is giving me the error
line 16, in <module>
Starters.append(Botamon = Digi("Botamon",0,1,1,1,1,[""]))
TypeError: list.append() takes no keyword arguments"
#Class
class Digi:
def __init__(self,mon,age,offense,defense,speed,brains,evo):
self.mon = mon
self.age = age
self.offense = offense
self.defense = defense
self.speed = speed
self.brains = brains
self.evo = evo
#Digilist
Starters = []
Starters.append(Botamon = Digi("Botamon",0,1,1,1,1,[""]))
Starters.append(Poyomon = Digi("Poyomon",0,1,1,1,1,[""]))
Starters.append(Punimon = Digi("Punimon",0,1,1,1,1,[""]))
Starters.append(Yuramon = Digi("Yuramon",0,1,1,1,1,[""]))
Digilist = []
Digilist.append(Koromon = Digi("Koromon",1,3,3,3,3,["Botamon"]))
Digilist.append(Tokomon = Digi("Tokomon",1,3,3,3,3,["Poyomon"]))
Digilist.append(Tsunomon = Digi("Tsunomon",1,3,3,3,3,["Punimon"]))
Digilist.append(Tanemon = Digi("Tanemon",1,3,3,3,3,["Yuramon"]))
#Starter
self = random.choice(Starters)
name = self.mon
The problem is you are naming your variables while appending them. If you are never going to access them by their name just do it like so:
Starters = []
Starters.append(Digi("Botamon",0,1,1,1,1,[""]))
Starters.append(Digi("Poyomon",0,1,1,1,1,[""]))
Starters.append(Digi("Punimon",0,1,1,1,1,[""]))
Starters.append(Digi("Yuramon",0,1,1,1,1,[""]))
If you have to access them by name later on, create them then append them:
Botamon = Digi("Botamon",0,1,1,1,1,[""])
Starters.append(Botamon)
and so on... However in the code example you have provided it looks like you will not have to access them by their variable name.
I am trying to add the required behavior to a CharFiled or TextField so I can store a list of lists and retrieve it as a list of lists again. I am not asking for a solution rather I would like to see an example where a subclassing of an already supported field type is done as I didn't find any in the documentation or the Internet.
Do I have to do it as explained in the documents for creating a custom type?
for example:
class mylistoflists(TextField):
if yes, then what do I have to assign to field_type?
Example code (see tests/fields.py for full example):
class ListField(TextField):
def db_value(self, value):
return ','.join(value) if value else ''
def python_value(self, value):
return value.split(',') if value else []
class Todo(TestModel):
content = TextField()
tags = ListField()
class TestCustomField(ModelTestCase):
requires = [Todo]
def test_custom_field(self):
t1 = Todo.create(content='t1', tags=['t1-a', 't1-b'])
t2 = Todo.create(content='t2', tags=[])
t1_db = Todo.get(Todo.id == t1.id)
self.assertEqual(t1_db.tags, ['t1-a', 't1-b'])
t2_db = Todo.get(Todo.id == t2.id)
self.assertEqual(t2_db.tags, [])
t1_db = Todo.get(Todo.tags == Value(['t1-a', 't1-b'], unpack=False))
self.assertEqual(t1_db.id, t1.id)
What I want to do seems simple : I have a MultipleChoiceField in a django form which proposes the id and pseudo of all books in a model named Dico :
class FiltreMonoForm(forms.Form):
dico_choices = []
for dic in Dico.objects.all().order_by('pseudo'):
dico_choices.append((dic.id, dic.pseudo))
dico_choices=tuple(dico_choices)
dicos = forms.MultipleChoiceField(required=False, widget=forms.CheckboxSelectMultiple, choices=dico_choices, initial=[c[0] for c in dico_choices], label="Diccionaris sorsas")
I get this form back in a view :
def monollist(request):
if request.GET:
getcopy = request.GET.copy()
form = FiltreMonoForm(getcopy)
dicos = form.cleaned_data['dicos']
else:
form = FiltreMonoForm()
I would like to have all the books checked if the user have checked none of them. Something like :
if request.GET:
getcopy = request.GET.copy()
form = FiltreMonoForm(getcopy)
dicos = form.cleaned_data['dicos']
for dic in Dico.objects.all().order_by('pseudo'):
dico_choices.append((dic.id, dic.pseudo))
dico_choices=tuple(dico_choices)
if len(dicos)==0:
form['dicos']=dico_choices
But I can't find how to change the value of the MultipleChoicesField. I tried with
form.data['dicos']=dico_choices
but it seems that I can only give one value to form.data['dicos'], it won't accept lists nor tuples.
I tried to override the __init__ method in my form in adding
self.data.update(dicos=dico_choices)
but I have the same issue, it works only if dico_choices is a single value.
Do you have any idea how to override my MultipleChoiceField with multiple values ?
Thanks
if 'dicos' not in getcopy:
for dic in Dico.objects.all():
getcopy.update({'dicos': dic.id})
Say I have an entry form for a GUI window that asks for a new setting and a value for that setting, which it then passes to another object that manages settings and expects **kwargs as input:
class SettingsForm(someFormClass):
def onSubmit(self):
new_setting = self.content['new setting'].get()
new_value = self.content['value'].get()
settings_instance.add_setting(new_setting=new_value)
This sets new_value to the literal string 'new_setting'. I've tried various ways to get around this, such as using a dictionary:
class SettingsForm(someFormClass):
def onSubmit(self):
new_setting = self.content['new setting'].get()
new_value = self.content['value'].get()
mydict = {}
mydict[new_setting] = new_value
settings_instance.add_setting(**mydict)
This works, but doesn't make much sense for a single pair of values... is there an obvious way that I'm missing?