Django: Accessing URL variables in Class Based Views and Forms

人盡茶涼 提交于 2021-02-08 07:55:45

问题


I'm trying to create an object in Django using the standard class based views and form libraries. Three fields in my form are dependent upon a domain variable captured from the URL pattern. My questions are:

  • How do I access domain within CreateSubscription so that I can set Subscription.site to Site.objects.filter(domain=domain)[0]?
  • How do I limit the dropdown fields rendered from CreateSubscriptionForm so that plan displays only SubscriptionPlan.objects.filter(site=Site.objects.filter(domain=domain)[0]) and payment_profile is limited to PaymentProfile.objects.filter(user=request.user)?

For clarity's sake, the domain in r'^subscribe/(?P<domain>\w+\.\w+)/$' is unrelated to my own site's domain. The django.contrib.sites framework won't help me here.

Thanks in advance for helping me untangle all of these CBV methods. :)

The URL pattern is:

from django.conf.urls import patterns, url
from accounts.views import *

url(r'^subscribe/(?P<domain>\w+\.\w+)/$', 
    CreateSubscription.as_view(), name='subscribe_to_site'),
)

The view in question is:

from accounts.forms import *
from accounts.models import *

class CreateSubscription(CreateView):
    model = Subscription
    form_class = CreateSubscriptionForm

    def form_valid(self, form):
        form.instance.user = self.request.user
        return super(CreateSubscription, self).form_valid(form)

The relevant models are:

from django.conf import settings
from django.contrib.sites.models import Site
from django.db import models

class PaymentProfile(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL)

class SubscriptionPlan(models.Model):
    site = models.ForeignKey(Site)
    name = models.CharField(max_length=40)

class Subscription(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL)
    site = models.ForeignKey(Site)
    plan = models.ForeignKey(SubscriptionPlan)
    payment_profile = models.ForeignKey(PaymentProfile)

And, finally, my form is:

from accounts.models import *

class CreateSubscriptionForm(forms.ModelForm):
    class Meta:
        model = Subscription
        exclude = ('user', 'site', )

回答1:


To access the data passed to the view, use self.args and self.kwargs

from accounts.forms import *
from accounts.models import *

class CreateSubscription(CreateView):
    model = Subscription
    form_class = CreateSubscriptionForm

    def form_valid(self, form):
        form.instance.user = self.request.user
        form.instance.site = Site.objects.get(domain=self.kwargs['domain'])
        return super(CreateSubscription, self).form_valid(form)

To restrict the dropdown content, you need to set the queryset for those fields. Very basically, something along these lines:

class CreateSubscriptionForm(forms.ModelForm):
    plan = forms.ModelChoiceField(
        queryset=SubscriptionPlan.objects.filter(xxx)
    )

    ...

    class Meta:
        model = Subscription
        exclude = ('user', 'site', )

This can also be done inside the view so that you have access to the domain.

class CreateSubscription(CreateView):
    model = Subscription
    form_class = CreateSubscriptionForm

    def get_form(self, form_class):
        """
        Returns an instance of the form to be used in this view.
        """
        form = super(CreateSubscription, self).get_form(form_class)
        form.fields['plan'].queryset = SubscriptionPlan.objects.filter(site__domain=self.kwargs['domain'])
        return form

    ...

    def form_valid(self, form):
        form.instance.user = self.request.user
        form.instance.site = Site.objects.get(domain=self.kwargs['domain'])
        return super(CreateSubscription, self).form_valid(form)


来源:https://stackoverflow.com/questions/15511941/django-accessing-url-variables-in-class-based-views-and-forms

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