python - Django - 如何通过用户先前选择的选项填充表单中的 manytomany 字段

标签 python django forms orm

如何使用以前用户选择的子项填充 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(),
        }

View .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'
    )

然后我们可以定义一个表单来选择订阅:

from django import forms

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

然后在 View 中我们可以处理表单并为登录用户订阅所有已选择的订阅:

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()
        <b>initial['subscriptions'] = self.request.user.subscriptions.all()</b>
        return initial
    
    def form_valid(self, form):
        subs = form.cleaned_data['subscriptions']
        self.request.user.subscriptions.add(*subs)
        return redirect(<em>'name-of-some-view'</em>)

Note: You can limit views to a class-based view to authenticated users with the LoginRequiredMixin mixin [Django-doc].


Note: In case of a successful POST request, you should make a redirect [Django-doc] to implement the Post/Redirect/Get pattern [wiki]. This avoids that you make the same POST request when the user refreshes the browser.

关于python - Django - 如何通过用户先前选择的选项填充表单中的 manytomany 字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68592908/

相关文章:

javascript - Django 模板 - 如果在另一个表单中选择特定项目,则隐藏表单

python - 希望使用 Django ORM 行的每个值与标准值有所不同

python - 如何强制django立即保存而不是在循环后进行批量更新

python - 我应该如何转义 ldap 特殊字符?

python - PyQt - 如何检查 QDialog 是否可见?

python - Django url正则表达式的问题

php - 从一张表中复制和删除数据

javascript - 如何使用输入值在 HTML 上书写?

python - Project euler #23 棘手的冲突

python - Python中的 'print'是什么?