Excluding fields in generic CRUD views

被刻印的时光 ゝ 提交于 2019-11-28 10:57:09

问题


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.


回答1:


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.



来源:https://stackoverflow.com/questions/6725080/excluding-fields-in-generic-crud-views

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!