簡體   English   中英

Django - 如何通過用戶先前選擇的選項在表單中填充 manytomany 字段

[英]Django - How to populate manytomany field in forms by previously selected options by users

如何使用以前用戶選擇的子項填充 manytomany 表單字段。

在此代碼表單中,呈現帶有空復選框的選項。 我希望復選框顯示用戶訂閱了哪些訂閱。

模型.py

class Subscription(models.Model):
    SUBSCRIPTION_TYPES = (
        ('SUB1', _('sub 1')),
        ('SUB2', _('sub 2')),
    )

    subscription_type = models.CharField(choices=SUBSCRIPTION_TYPES, max_length=30, unique=True)
    description = models.CharField(max_length=255, blank=True)

class UserSubscription(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    subscriptions = models.ManyToManyField(Subscription, related_name='subscriptions',
                                           related_query_name='subscriptions')

表格.py

class SubscriptionForm(forms.ModelForm):
    class Meta:
        model = UserSubscription
        fields = ('subscriptions',)
        widgets = {
            'subscriptions': forms.CheckboxSelectMultiple(),
        }

視圖.py

class SubscriptionFormView(FormView):
    template_name = 'profile/subscription.html'
    form_class = SubscriptionForm

不要創建UserSubscription ,現在你定義了兩個結表。 這將導致重復數據,並使查詢效率降低,並且更容易出錯的邏輯。

您需要的是從SubscriptionUserManyToManyField ,因此:

class Subscription(models.Model):
    # …
    subscribers = models.ManyToManyField(
        settings.AUTH_USER_MODEL,
        related_name='subscriptions'
    )

然后我們可以定義一個表單來選擇Subscription

from django import forms

class SubscribingForm(forms.Form):
    subscriptions = forms.ModelMultipleChoiceField(
        queryset=Subscription.objects.all(),
        widget=forms.CheckboxSelectMultiple()
    )

然后在視圖中我們可以處理表單並為登錄用戶訂閱所有已選擇的訂閱:

from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import redirect

class SubscriptionFormView(LoginRequiredMixin, FormView):
    template_name = 'profile/subscription.html'
    form_class = SubscribingForm
    
    def get_initial(self):
        initial = super().get_initial()
        initial['subscriptions'] = self.request.user.subscriptions.all()
        return initial
    
    def form_valid(self, form):
        subs = form.cleaned_data['subscriptions']
        self.request.suer.subscriptions.add(*subs)
        return redirect('name-of-some-view')

注意:您可以使用LoginRequiredMixin mixin [Django-doc]將基於類的視圖的視圖限制為經過身份驗證的用戶。


注意:如果 POST 請求成功,您應該進行redirect [Django-doc]以實現Post/Redirect/Get模式 [wiki] 這可以避免您在用戶刷新瀏覽器時發出相同的 POST 請求。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM