简体   繁体   中英

Django CreateView validate field not in fields

So, I have a Django generic view:

class Foobaz(models.Model):
    name = models.CharField(max_length=140)
    organisation = models.ForeignKey(Organisation)


class FoobazForm(forms.ModelForm):
    class Meta:
        model = Foobaz
        fields = ('name')


class FoobazCreate(CreateView):
    form_class = FoobazForm

    @login_required
    def dispatch(self, *args, **kwargs):
        return super(FoobazCreate, self).dispatch(*args, **kwargs)

What I'm trying to do is to take the organisation id from the URL:

/organisation/1/foobaz/create/

And add it back to the created object. I realise I can do this in CreateView.form_valid() , but from what I understand this is then completely unvalidated.

I've tried adding it to get_form_kwargs() but this does not expect the organisation kwarg as it is not in the included fields.

Ideally what I'd like to do is to add it to the instance of the form to validate it with the rest - ensuring it is a valid organisation, and that the user in question has the correct permissions to add a new foobaz to it.

I'm happy to just roll my own view if that is the best way of doing this, but I may just be simply missing a trick.

Thanks!

I thnik it would be better to include the organisation field and define it as hidden and readonly, this way django will validate it for you.

You can then override get_queryset method like this:

def get_queryset(self):
    return Foobaz.objects.filter(
        organisation__id=self.kwargs['organisation_id'])

where organisation_id is a keyword in url pattern.

You can do it overriding the View's get_kwargs() method and the Form's save() method. In the get_kwargs() I "inject" the organization_id into the initial data of the form, and in save() I retrieve the missing info with the supplied initial data:

In urls.py:

urlpatterns('',
    #... Capture the organization_id
    url(r'^/organisation/(?P<organization_id>\d+)/foobaz/create/',
        FoobazCreate.as_view()),
    #...
)

In views.py:

class FoobazCreate(CreateView):
    # Override get_kwargs() so you can pass
    # extra info to the form (via 'initial')
    # ...(all your other code remains the same)
    def get_form_kwargs(self):
        # get CreateView kwargs
        kw = super(CreateComment, self).get_form_kwargs()
        # Add any kwargs you need:
        kw['initial']['organiztion_id'] = self.kwargs['organization_id']
        # Or, altenatively, pass any View kwarg to the Form:
        # kw['initial'].update(self.kwargs)
        return kw

In forms.py:

class FoobazForm(forms.ModelForm):
    # Override save() so that you can add any
    # missing field in the form to the model
    # ...(Idem)
    def save(self, commit=True):
        org_id = self.initial['organization_id']
        self.instance.organization = Organization.objects.get(pk=org_id)
        return super(FoobazForm, self).save(commit=commit)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM