Django - Multiple custom models on the same form

Pol Frances

I'm using Django 2.1 and PostgreSQL. My problem is that I'm trying to create a form to edit two different models at the same time. This models are related with a FK, and every example that I see is with the user and profile models, but with that I can't replicate what I really need.

My models simplified to show the related information about them are:

# base model for Campaigns.
class CampaignBase(models.Model):
    ....
    project = models.ForeignKey(Project, on_delete=models.CASCADE)
    creation_date = models.DateTimeField(auto_now_add=True)
    start_date = models.DateTimeField(null=True, blank=True)
    end_date = models.DateTimeField(null=True, blank=True)
    ....

# define investment campaign made on a project.
class InvestmentCampaign(models.Model):
    ....
    campaign = models.ForeignKey(CampaignBase, on_delete=models.CASCADE, null=True, blank=True)

    description = models.CharField(
        blank=True,
        max_length=25000,
    )
    ....

And the form that I want to create is one that includes the end_date of the FK CampaignBase, and the Description from the InvestmentCampaign.

Now I have this UpdateView to edit the InvestmentCampaign, and I need to adapt to my actual needs, that are also update the CampaignBase model:

class ProjectEditInvestmentCampaignView(LoginRequiredMixin, SuccessMessageMixin, generic.UpdateView):
    template_name = 'webplatform/project_edit_investment_campaign.html'
    model = InvestmentCampaign
    form_class = CreateInvestmentCampaignForm
    success_message = 'Investment campaign updated!'

    def get_success_url(self):
        return reverse_lazy('project-update-investment-campaign', args=(self.kwargs['project'], self.kwargs['pk']))

    # Make the view only available for the users with current fields
    def dispatch(self, request, *args, **kwargs):
        self.object = self.get_object()
        # here you can make your custom validation for any particular user
        if request.user != self.object.campaign.project.user:
            raise PermissionDenied()
        return super().dispatch(request, *args, **kwargs)

    # Set field as current user
    def form_valid(self, form):
        campaign = InvestmentCampaign.objects.get(pk=self.kwargs['campaign'])
        form.instance.campaign = campaign
        form.instance.history_change_reason = 'Investment campaign updated'
        return super(ProjectEditInvestmentCampaignView, self).form_valid(form)

    def get_context_data(self, **kwargs):
        project = Project.objects.get(pk=self.kwargs['project'])
        context = super(ProjectEditInvestmentCampaignView, self).get_context_data(**kwargs)
        context['project'] = project
        return context

My forms are:

class CreateCampaignBaseForm(forms.ModelForm):
    class Meta:
        model = CampaignBase
        fields = ('end_date',)
        widgets = {
            'end_date': DateTimePickerInput(),
        }

    def __init__(self, *args, **kwargs):
        # first call parent's constructor
        super(CreateCampaignBaseForm, self).__init__(*args, **kwargs)
        # evade all labels and help text to appear when using "as_crispy_tag"
        self.helper = FormHelper(self)
        self.helper.form_show_labels = False
        self.helper._help_text_inline = True


class CreateInvestmentCampaignForm(forms.ModelForm):
    class Meta:
        model = InvestmentCampaign
        fields = ('description')
        widgets = {
            'description': SummernoteWidget(attrs={'summernote': {
                'placeholder': 'Add some details of the Investment Campaign here...'}}),
        }

    def __init__(self, *args, **kwargs):
        # first call parent's constructor
        super(CreateInvestmentCampaignForm, self).__init__(*args, **kwargs)
        # evade all labels and help text to appear when using "as_crispy_tag"
        self.helper = FormHelper(self)
        self.helper.form_show_labels = False
        self.helper._help_text_inline = True

I've read everywhere that the best way of doing this is using function based views, and call each of the forms that I have and then do the validation. the thing is that I don't know how can I populate the fields with the right object in both forms, and also, I don't know how to do the equivalent of the get_context_data nor getting the self arguments to do the equivalent of the get_success_url (because with function based views I only have the request attr so I can't access the kwargs).

I've seen some people using the django-betterforms, but again, the only examples are with the auth and profile models and I don't see the way to replicate that with my own models.

Thank you very much.

dirkgroten

If the only thing you want to change is one field end_date on BaseCampaign, then you should use just one form. Just add end_date as an additional field (e.g. forms.DateTimeField()) on your CreateInvestmentCampaignForm and in your form.valid() method, after saving the form, set the value on the associated campaign:

def form_valid(self, form):
    inv_campaign = form.save(commit=False)
    inv_campaign.campaign.end_date = form.cleaned_data['end_date']
    inv_campaign.campaign.save()
    inv_campaign.history_change_reason = ...
    return super().form_valid(form)

Here's how to add end_date to your form and initialize it correctly:

class CreateInvestmentCampaignForm(ModelForm):
    end_date = forms.DateTimeField(blank=True)

    class Meta:
        model = InvestmentCampaign
        fields = ('description')

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if self.instance.campaign:
            self.fields['end_date'].initial = self.instance.campaign.end_date

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

Django: posting information to multiple models with one html form

分類Dev

custom form update in django

分類Dev

checking if values are the same in django form

分類Dev

Django - dropdown form with multiple select

分類Dev

Multiple rows from the same entity in single form

分類Dev

Clean Django form fields with same name

分類Dev

How to merge multiple models in serializers / views Django REST Framework?

分類Dev

Django custom form field layout without manually redoing the whole form

分類Dev

How to display instances from two different django models on the same template, inside the same table?

分類Dev

Multiple Django sites on the same domain - CSRF fails

分類Dev

Flask WTForms - Custom validators based of multiple form fields

分類Dev

Django custom form with non-model fields in Admin/AdminInline

分類Dev

Python Pyserial read data form multiple serial ports at same time

分類Dev

Custom object of same type added multiple times inside for loop

分類Dev

Drawing Multiple Models with glDrawArrays

分類Dev

Multiple models - no data retrieved

分類Dev

Handling duplicates in django models

分類Dev

Conditionals in django models arguments

分類Dev

Django admin page: Customize dictionary (JSONField) of IDs through multiple Models selects instead of raw text

分類Dev

Can you use a Django form multiple times in one view?

分類Dev

Django: How to custom save a model/form based on a non-persistent field of a form?

分類Dev

Laravel get all related models for multiple models

分類Dev

Django: multiple admin page consuming same model but different auth mode

分類Dev

Does using the same trainControl object for cross-validation when training multiple models with caret allow for accurate model comparison?

分類Dev

Multiple models in Metal. How?

分類Dev

Rails will paginate table with multiple models

分類Dev

Django delete models from db

分類Dev

Using Django Models across Apps

分類Dev

django-import-export form <input> not render in custom admin template w / grappelli

Related 関連記事

  1. 1

    Django: posting information to multiple models with one html form

  2. 2

    custom form update in django

  3. 3

    checking if values are the same in django form

  4. 4

    Django - dropdown form with multiple select

  5. 5

    Multiple rows from the same entity in single form

  6. 6

    Clean Django form fields with same name

  7. 7

    How to merge multiple models in serializers / views Django REST Framework?

  8. 8

    Django custom form field layout without manually redoing the whole form

  9. 9

    How to display instances from two different django models on the same template, inside the same table?

  10. 10

    Multiple Django sites on the same domain - CSRF fails

  11. 11

    Flask WTForms - Custom validators based of multiple form fields

  12. 12

    Django custom form with non-model fields in Admin/AdminInline

  13. 13

    Python Pyserial read data form multiple serial ports at same time

  14. 14

    Custom object of same type added multiple times inside for loop

  15. 15

    Drawing Multiple Models with glDrawArrays

  16. 16

    Multiple models - no data retrieved

  17. 17

    Handling duplicates in django models

  18. 18

    Conditionals in django models arguments

  19. 19

    Django admin page: Customize dictionary (JSONField) of IDs through multiple Models selects instead of raw text

  20. 20

    Can you use a Django form multiple times in one view?

  21. 21

    Django: How to custom save a model/form based on a non-persistent field of a form?

  22. 22

    Laravel get all related models for multiple models

  23. 23

    Django: multiple admin page consuming same model but different auth mode

  24. 24

    Does using the same trainControl object for cross-validation when training multiple models with caret allow for accurate model comparison?

  25. 25

    Multiple models in Metal. How?

  26. 26

    Rails will paginate table with multiple models

  27. 27

    Django delete models from db

  28. 28

    Using Django Models across Apps

  29. 29

    django-import-export form <input> not render in custom admin template w / grappelli

ホットタグ

アーカイブ