开发者

Why is my Django modelformset always invalid when i use a custom model manager?

开发者 https://www.devze.com 2023-02-10 02:29 出处:网络
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.

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)
0

精彩评论

暂无评论...
验证码 换一张
取 消