Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
575 views
in Technique[技术] by (71.8m points)

python - Excluding fields in generic CRUD views

I have a model named Domain which looks like this:

class Domain(models.Model):
    """
    Model for storing the company domains
    """
    user = models.ForeignKey(
        User
    )
    host = models.CharField(
        null=False, verbose_name="Host", max_length=128, unique=True
    )

I'd like to use Django's generic views for doing CRUD operations on this. There is one field in this model that needs user input but the foreign key field doesn't need any user input. How can I exclude that field from the form that my generic view generates but assign it the value of the current authenticated user.

Thanks.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Have a look at Russel's answer to a similar question on the django-users group earlier this week.

Quoting the answer*:

Forms and Views solve different problems.

The View is solving the problem of "how do I handle this request and convert it into a response?". The Form is solving the problem of "How do I convert the POST data in this request into a model object (or a change to a model object)?".

Very roughly, a view is doing the following:

  1. View gets a request
  2. View works out whether this is a GET or a POST
  3. If its a POST, View asks the Form to turn the Post into a model change
  4. Form returns success or failure
  5. View responds to the success or failure of the Form.
  6. View returns a response.

The functionality of the Form is a complete subset of the functionality of the View -- and for this reason, it's a completely interchangable internal component.

Now, in simple situations, it's possible for a View to guess all the defaults for the form -- all it needs to know is that you're dealing with a Foo model, and it can construct a default Foo ModelForm. However, if you have more sophisticated form requirements, you're going to need a customized Form.

We could have implemented this by exposing all the options of ModelForm on the View class; but in order to keep everything clean, we kept the ModelForm isolated, and provided the View with a way to specify which Form class it's going to use.

So - to cover your use case of excluding fields, you define a ModelForm that excludes the fields, then let the CreateView know the form you want to use:

class CampaignForm(forms.ModelForm):


    class Meta:
        model = Campaign
        exclude = ('user', 'name', 'content_inlined')

class CreateCampaignView(CreateView):
    form_class = CampaignForm
    template_name = "forms/create.html"

I'm guessing when you say "fix a values for a field", you mean setting the values of user, name and content_inlined before you save the new Campaign instance; to do this, you need to inject some extra code into the form processing logic of the form:

class CreateCampaignView(CreateView):
    form_class = CampaignForm
    template_name = "forms/create.html"

    def form_valid(self, form):
        form.instance.user = ... (something meaningful.. e.g., self.request.user)
        return super(CreateCampaignView, self).form_valid(form)

This overrides the default behavior when the form is valid, and sets the extra values. The super() implementation of form_valid() will then save the instance.

For the record, this could also be done by overriding the save() method on the ModelForm -- however, if you do that, you lose the request object, which you will need if you're trying to set the instance values to something that is request-sensitive.

*the original answer set self.object.user instead of form.instance.user. This gives an AttributeError so I have changed it above.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...