Why is my Django modelformset always invalid when i use a custom model manager?
After stripping down my code to the minimum, it still does not work. I alway get the hint:
(Hidden field id) Select a valid choice. That choice is not one of the available choices.
This is what my forms looks like:
class ChangeItemForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(ChangeItemForm, self).__init__(*args, **kwargs)
for key in self.fields:
self.fields[key].required = False
class Meta:
model = Item
fields = ('name','tags','no')
ChangeItemFormset=modelformset_factory(Item,extra=0,form=ChangeItemForm)
and my view looks like this:
def manage_view(request):
if request.method=='POST':
itemforms=ChangeItemFormset(request.POST,
queryset=Item.objects.filter(creator=request.user))
else:
itemforms=ChangeItemFormset(queryset=Item.objects.filter(creator=request.user))
messages.info(request,str(itemforms.is_valid())) #always prints False
context=RequestContext(request)
context.update({'formset':itemforms,
})
return render_to_response('sonitem/test_forms.html',context)
and in my template i do this:
<form action="." method="post" name="upload_image">
<button type="submit" name="action" value="change">change</button>
{%for form in formset.forms%}
{{form}}
{%endfor%}
{{formset.management_form}}
{%csrf_token%}
</form>
messages:
{%for message in messages%}
<div>{{message}}</div>
{%endfor%}
Thats it. I don't have a clue where to look further. Maybe i do it all wrong? At least i am sure i somehow missed an important piece of how formsets work... if someone could please help me out.
edit:
looks like it's somehow related to my model Item. Just made a new, simplified model, Item2, and this code worked exactly as it should. Item2 had just the fields that are in the form above. Back to Item: Why (and more important - how) can modelfields that are not in the formset affect the formset validation?The Item2 model, the one that is working:
class Item2(models.Model):
name=models.CharField(max_length=50)
tags=TagField()
no=models.IntegerField(blank=True,null=True)
creator = models.ForeignKey(User, related_name='creator')
edit2:
I think i have encircled what causes the trouble: i have defined a model manager as default, that is looking for a status - which is a models.IntegerField. As soon as i put this into the class, it stops working and delivers exactly the error message from above. The Item model looks somewhat like this:class Item(models.Model):
PRIVATE_STATUS=1
PUBLIC_STATUS=2
RELEASED_STATUS=3
STATUS_CHOICES=((PRIVATE_STATUS ,'private'),
(PUBLIC_STATUS ,'public' ),
(RELEASED_STATUS,'released'))
status = models.IntegerField(choices=STATUS_CHOICES,default=PRIVATE_STATUS)
public = PublicItemManager()
objects = models.Manager()
name=models.CharField(max_length=50)
tags=TagField()
no=models.IntegerField(blank=True,null=True)
file=models.FileField()
creator = models.ForeignKey(User, related_name='creator')
status=models.IntegerField(blank=True,null=True)
So i have to extend my question above. Is it possible to use the status (which definitely is a required field) in the model and still use a formset? The formset is only for editing, not for creating the items. And it is always prepopulated, there is no chance there will be an empty status-field.
I still don't understand how a field that is not even in the form can impede the va开发者_如何学运维lidation of it. And, by the way, if i am using just the ChangeItemForm, it does not.
edit 3:
here is the manager, stripped down to the most simple version causing trouble:class PublicItemManager(models.Manager):
def get_query_set(self):
return super(PublicItemManager,
self).get_query_set().filter(status=self.model.PUBLIC_STATUS)
when i
#public=PublicItemManager
everything runs smooth.
edit 4:
oh, and by the way: Why is the public manager affecting any validation, when i have the queryset working with the objects manager?queryset=Item.**objects**.filter(creator=request.user)
After studying the django-docs for quite a while i was able to find the solution. Looks like in certain situations django creates "automatic" managers that are not the _default_manager. Docs are here: http://docs.djangoproject.com/en/1.2/topics/db/managers/#controlling-automatic-manager-types
And here is the code for the working Manager:
class PublicItemManager(models.Manager):
#this is the important line:
use_for_related_fields = True
def get_query_set(self):
return super(PublicItemManager,self).get_query_set().filter(status=self.model.PUBLIC_STATUS)
精彩评论