I've found a solution to render tags registered in taggit models as choices list by doing:
from taggit.models import Tag
class BlogPost(models.Model):
tags = models.ForeignKey(Tag, on_delete=models.CASCADE, default='')
(i changed something in taggit folder i guess, .... i forgot but i works without any problem )
but i would like to change label name ("Tags" by default)
i tried in forms.py:
imports ...
class PostForm(forms.ModelForm):
tag = [(i, i) for i in Tag.objects.all()]
tags = forms.ChoiceField(label='another label name', choices=tag )
class Meta:
model = BlogPost
fields = ('tags',)
it shows the result i expected but when i save or POST it return a form validation error 'Cannot assign "u'tag name'": "BlogPost.tags" must be a "Tag" instance.'
so can someone handle this and thanks
you need to use pk as key
class PostForm(forms.ModelForm):
tag = [(i.pk, i.title) for i in Tag.objects.all()]
# ^^^^^
tags = forms.ChoiceField(label='another label name', choices=tag )
and may be better solution is to use ModelChoiceField
tags = forms.ModelChoiceField(queryset=Tag.objects.all(), empty_label=None)
I have some form modelformset_factory with model contains ForeignKey, but I need display this ForeignKey(ModelChoiceField) like CharField.
I use like that:
class SingleNeedFormWithDescription(ModelForm):
helper = StandardFormHelper()
helper.template = 'template.html'
need = CharField()
class Meta:
model = NeedMembershipOrganization
fields = ['need', 'description']
I have id of need in my template, but I need need.title or need.__str__().
My model:
class NeedMembershipOrganization(Model):
need = ForeignKey('needs.Need')
organization = ForeignKey(Organization)
description = TextField(blank=True, null=True, verbose_name='description')
Thanks!
You can change the ModelChoiceField widget to a TextInput, but you might have to figure out some way to validate and parse the input.
class SingleNeedFormWithDescription(ModelForm):
need = forms.ModelChoiceField(
queryset=Need.objects.all(),
widget=forms.TextInput)
I need have a search box, one of fields of the model has a M2M field. I got to put it works but only works when i look for the id of the M2M field, not for the name. my models:
class Specialities(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Profile(models.Model):
user = models.OneToOneField(User)
name = models.CharField(max_length=200)
specialities = models.ManyToManyField(Specialities)
def __str__(self):
return self.name
And my view:
class SearchView(TemplateView):
template_name = 'contadores/search.html'
def post(self,request,*args,**kwargs):
buscar = request.POST['buscar']
contadores = Profile.objects.filter(specialities=buscar)
ctx = {'contadores':contadores}
return render_to_response('contadores/resultados.html',ctx,context_instance=RequestContext(request))
The queryset in "contadores" works fine, but as i told before, the search box only receive the id of the M2M field, if i look for the word in the search box django says: invalid literal for int() with base 10: 'niif' I know the reason, but how can i pass to the search box the word of the M2M field associated to the Specialities model instead the id?
What you can do is search by related table, like this:
contadores = Profile.objects.filter(specialities__name__iexact = request.POST['buscar'])
Try like this:
buscar = Specialities.objects.filter(name__iexact = request.POST['buscar'])
if buscar.exists():
contadores = Profile.objects.filter(specialities=buscar[0])
I have the following model:
class InfoBox(models.Model):
type = models.ForeignKey(InfoBoxType)
content = models.TextField()
product = models.ForeignKey(Product)
I want to add a css class to my foreignkey. I've tried the following:
forms.py
class InfoBoxForm(ModelForm):
class Meta:
model = InfoBox
widgets = {
'type': ChoiceField(attrs={'class': 'hej'}),
}
I've also tried this but with the same result...
class InfoBoxForm(forms.Form):
type = forms.ChoiceField(
widget=forms.ChoiceField(attrs={'class':'special'}))
admin.py
class InfoBoxInline(admin.StackedInline):
model = InfoBox
extra = 0
form = InfoBoxForm
But im only getting this:
__init__() got an unexpected keyword argument 'attrs'
Im thinking that this would be pretty easy to do, so what am I doing wrong...?
Try:
widgets = {
'type': Select(attrs={'class': 'hej'}),
}
This is the correct widget for your field.
If you don't want to overwrite the widget, you can use:
self.fields['type'].widget.attrs['class'] = 'hej'
in the form's init method
I have a form where a couple of fields are coming out as required when I don't want them too. Here is the form from models.py
class CircuitForm(ModelForm):
class Meta:
model = Circuit
exclude = ('lastPaged',)
def __init__(self, *args, **kwargs):
super(CircuitForm, self).__init__(*args, **kwargs)
self.fields['begin'].widget = widgets.AdminSplitDateTime()
self.fields['end'].widget = widgets.AdminSplitDateTime()
In the actual Circuit model, the fields are defined like this:
begin = models.DateTimeField('Start Time', null=True, blank=True)
end = models.DateTimeField('Stop Time', null=True, blank=True)
My views.py for this is here:
def addCircuitForm(request):
if request.method == 'POST':
form = CircuitForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/sla/all')
form = CircuitForm()
return render_to_response('sla/add.html', {'form': form})
What can I do so that the two fields aren't required?
If you don't want to modify blank setting for your fields inside models (doing so will break normal validation in admin site), you can do the following in your Form class:
def __init__(self, *args, **kwargs):
super(CircuitForm, self).__init__(*args, **kwargs)
for key in self.fields:
self.fields[key].required = False
The redefined constructor won't harm any functionality.
If the model field has blank=True, then required is set to False on the form field. Otherwise, required=True
Says so here: http://docs.djangoproject.com/en/dev/topics/forms/modelforms/
Looks like you are doing everything right.
You could check the value of self.fields['end'].required.
Expanding on DataGreed's answer, I created a Mixin that allows you to specify a fields_required variable on the Meta class like this:
class MyForm(RequiredFieldsMixin, ModelForm):
class Meta:
model = MyModel
fields = ['field1', 'field2']
fields_required = ['field1']
Here it is:
class RequiredFieldsMixin():
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
fields_required = getattr(self.Meta, 'fields_required', None)
if fields_required:
for key in self.fields:
if key not in fields_required:
self.fields[key].required = False
It's not an answer, but for anyone else who finds this via Google, one more bit of data: this is happening to me on a Model Form with a DateField. It has required set to False, the model has "null=True, blank=True" and the field in the form shows required=False if I look at it during the clean() method, but it's still saying I need a valid date format. I'm not using any special widget and I get the "Enter a valid date" message even when I explicitly set input_formats=['%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', ''] on the form field.
EDIT: Don't know if it'll help anyone else, but I solved the problem I was having. Our form has some default text in the field (in this case, the word "to" to indicate the field is the end date; the field is called "end_time"). I was specifically looking for the word "to" in the form's clean() method (I'd also tried the clean_end_time() method, but it never got called) and setting the value of the clean_data variable to None as suggested in this Django ticket. However, none of that mattered as (I guess) the model's validation had already puked on the invalid date format of "to" without giving me a chance to intercept it.
This is a bug when using the widgets:
workaround:
Using Django time/date widgets in custom form
or ticket 12303
From the model field documentation,
If you have a model as shown below,
class Article(models.Model):
headline = models.CharField(
max_length=200,
null=True,
blank=True,
help_text='Use puns liberally',
)
content = models.TextField()
You can change the headline's form validation to required=True instead of blank=False as that of the model as defining the field as shown below.
class ArticleForm(ModelForm):
headline = MyFormField(
max_length=200,
required=False,
help_text='Use puns liberally',
)
class Meta:
model = Article
fields = ['headline', 'content']
So answering the question,
class CircuitForm(ModelForm):
begin = forms.DateTimeField(required=False)
end = forms.DateTimeField(required=False)
class Meta:
model = Circuit
exclude = ('lastPaged',)
this makes begin and end to required=False