简体   繁体   中英

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

How can I populate manytomany form field with previous user selected subs.

In this code forms render choices with empty checkboxes. I want checkboxes to show which subscriptions user subscribed to.

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

forms.py

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

views.py

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

Please do not create a UserSubscription , now you defined two junction tables. This will result in duplicate data, and will make queries less efficient, and more error-prone logic.

What you need is a ManyToManyField from the Subscription to the User , so:

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

Then we can define a form to select the Subscription s:

from django import forms

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

Then in the view we can handle the form and subscribe the logged in user to all the subscriptions that have been selected:

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM