开发者

Django Form with no required fields

I want to make a form used to filter searches without any field being required. For example given this code:

models.py:

class Message(models.Model):
    happened = models.DateTimeField()
    filename = models.CharField(max_length=512, blank=True, null=True)
    message = models.TextField(blank=True, null=True)
    dest = models.CharField(max_length=512, blank=True, null=True)
    fromhost = models.ForeignKey(Hosts, related_name='to hosts', blank=True, null=True)
    TYPE_CHOICES = ( (u'Info', u'Info'), (u'Error', u'Error'), (u'File', u'File'), (u'BPS', u'BPS'),)
    type = models.CharField(max_length=7, choices=TYPE_CHOICES)
    job = models.ForeignKey(Jobs)

views.py:

WHEN_CHOICES = ( (u'', ''), (1, u'Today'), (2, u'Two days'), (3, u'Three Days'), (7, u'Week'),(31, u'Month'),)

class MessageSearch(ModelForm): #Class that makes a form from a model that can be customized by placing info above the class Meta
        message = forms.CharField(max_length=25, required=False)
        job = forms.CharField(max_length=25, required=False)
        happened = forms.CharField(max_length=14, widget=forms.Select(choices=WHEN_CHOICES), required=False)
        class Meta:
            model = Message

That's the code I have now. As you can see it makes a form based on a model. I redefined message in the form because I'm using an icontains filter so I didn't need a giant text box. I redefined the date mostly because I didn't want to have to mess around with dates (I hate working with dates! Who doesnt?) And I changed the jobs field because otherwise I was getting a drop down list of existing开发者_JAVA百科 jobs and I really wanted to be able to search by common words. So I was able to mark all of those as not required

The problem is it's marking all my other fields as required because in the model they're not allowed to be blank.

Now in the model they can't be blank. If they're blank then the data is bad and I don't want it in the DB. However the form is only a filter form on a page to display the data. I'm never going to save from that form so I don't care if fields are blank or not. So is there an easy way to make all fields as required=false while still using the class Meta: model = Message format in the form? It's really handy that I can make a form directly from a model.

Also this is my first serious attempt at a django app so if something is absurdly wrong please be kind :)


You can create a custom ModelForm that suit your needs. This custom ModelForm will override the save method and set all fields to be non-required:

from django.forms import ModelForm

class SearchForm(ModelForm):
    def __init__(self, *args, **kwargs):
        super(SearchForm, self).__init__(*args, **kwargs)
        for key, field in self.fields.iteritems():
            self.fields[key].required = False

So you could declare your forms by simply calling instead of the ModelForm, e.g.:

class MessageForm(SearchForm):
    class Meta:
        model = Message


You could also pass empty_permitted=True when you instantiate the form, e.g.,

form = MessageSearch(empty_permitted=True)

that way you can still have normal validation rules for when someone does enter data into the form.


I would give a try to the django-filter module :

http://django-filter.readthedocs.io/en/develop/

fields are not required. these are filters actually. It would look like this :

import django_filters

class MessageSearch(django_filters.FilterSet):

    class Meta:
        model = Message
        fields = ['happened', 'filename', 'message', '...', ]

    # django-filter has its own default widgets corresponding to the field
    # type of the model, but you can tweak and subclass in a django way :
    happened = django_filters.DateFromToRangeFilter()

mandatory, hidden filters can be defined if you want to narrow a list of model depending on something like user rights etc.

also : setup a filter on a 'reverse' relationship (the foreignkey is not in the filtered model : the model is referenced elsewhere in another table), is easy, just name the table where the foreign key of the filtered model field is :

    # the 'tags' model has a fk like message = models.ForeignKey(Message...)
    tags= django_filters.<some filter>(name='tags')

quick extendable and clean to setup. please note I didn't wrote this module, I'm just very happy with it :)

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜