django-extra-views 将 InlineFormSet 字段值公开到 get_context_data() 和 forms_valid() 方法中

django-extra-views expose InlineFormSet field values into get_context_data() and forms_valid() methods

我想访问 InlineFormSet 的字段以便在视图中使用。

这是一个基于https://django-extra-views.readthedocs.io/en/latest/views.html#createwithinlinesview-and-updatewithinlinesview的例子:

from extra_views import InlineFormSet, CreateWithInlinesView,


class ItemsInline(InlineFormSet):
    model = Item


class TagsInline(InlineFormSet):
    model = Tag


class OrderCreateView(CreateWithInlinesView):
    model = Order
    inlines = [ItemsInline, TagsInline]

    def get_success_url(self):
        return self.object.get_absolute_url()

如何在 get_context_data()forms_valid() 方法中公开 InlineFormSet 字段? 警告:下面的代码失败了!

class OrderCreateView(CreateWithInlinesView):

    [... see above ...]

    def get_context_data(self, **kwargs):
        context = super(OrderCreateView, self).get_context_data(**kwargs)
        if self.request.POST:
            context['items'] = ItemsInline(self.request.POST)
            context['tags'] = TagsInline(self.request.POST)
        else:
            context['items'] = ItemsInline()
            context['tags'] = TagsInline()
        return context

    def forms_valid((self, form, inlines):

        [...]    

        return super(OrderCreateView, self).forms_valid(form, inlines)

我用这个模型复制了你的例子:

STATUS_CHOICES = (
    (0, 'Placed'),
    (1, 'Charged'),
    (2, 'Shipped'),
    (3, 'Cancelled'),
)

class Order(models.Model):
    name = models.CharField(max_length=255)
    date_created = models.DateTimeField(auto_now_add=True)
    date_modified = models.DateTimeField(auto_now=True)
    action_on_save = models.BooleanField(default=False)


class Item(models.Model):
    item_name = models.CharField(max_length=255)
    sku = models.CharField(max_length=13)
    price = models.DecimalField(decimal_places=2, max_digits=12, db_index=True)
    order = models.ForeignKey(Order, related_name='items', on_delete=models.CASCADE)
    status = models.SmallIntegerField(default=0, choices=STATUS_CHOICES, db_index=True)
    date_placed = models.DateField(default=now, null=True, blank=True)

    def __unicode__(self):
        return '%s (%s)' % (self.item_name, self.sku)


class Tag(models.Model):
    tag_name = models.CharField(max_length=255)
    content_type = models.ForeignKey(ContentType, null=True, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField(null=True)
    content_object = GenericForeignKey('content_type', 'object_id')

    def __unicode__(self):
        return self.tag_name

网址:

from django.conf.urls import url
from .views import OrderCreateView, OrderUpdateView

urlpatterns = [
    url(r'^inlines/new/$', OrderCreateView.as_view()),
    url(r'^inlines/(?P<pk>\d+)/$', OrderUpdateView.as_view()),
]

表格:

from django import forms
from .models import Order, Item


class OrderForm(forms.ModelForm):
    class Meta:
        model = Order
        fields = ['name']

    def save(self, commit=True):
        instance = super(OrderForm, self).save(commit=commit)
        if commit:
            instance.action_on_save = True
            instance.save()
        return instance


class ItemForm(forms.ModelForm):
    flag = forms.BooleanField(initial=True)

    class Meta:
        model = Item
        fields = ['item_name', 'sku', 'price', 'order', 'status']

观看次数:

from django.contrib.contenttypes.models import ContentType
from extra_views import InlineFormSet, CreateWithInlinesView, UpdateWithInlinesView
from extra_views.generic import GenericInlineFormSet
from .forms import OrderForm
from .models import Item, Order, Tag


class ItemsInline(InlineFormSet):
    model = Item
    fields = ['item_name', 'sku', 'price', 'order', 'status']


class TagsInline(GenericInlineFormSet):
    model = Tag
    fields = ['tag_name']


class OrderCreateView(CreateWithInlinesView):
    model = Order
    fields = ['name']
    context_object_name = 'order'
    inlines = [ItemsInline, TagsInline]
    template_name = 'extra_views/order_and_items.html'

    def get_success_url(self):
        return '/inlines/%i' % self.object.pk


class OrderUpdateView(UpdateWithInlinesView):
    model = Order
    form_class = OrderForm
    inlines = [ItemsInline, TagsInline]
    template_name = 'extra_views/order_and_items.html'

    def get_success_url(self):
        return ''
  • OrderCreateView 中您无法读取 TagItem 中的记录 get_context_data 方法,因为它们尚未创建。

  • OrderCreateView可以读取forms_valid之后的所有记录 方法照常。

  • OrderUpdateView中您可以读取 get_context_data 方法类似于 forms_valid 方法。

看起来像这样:

class OrderCreateView(CreateWithInlinesView):
    # ... 

    def get_context_data(self, **kwargs):
        data = super(OrderCreateView, self).get_context_data(**kwargs)
        from pprint import pprint
        pprint(self.request.POST)  # there is only post data here
        return data

    def forms_valid(self, form, inlines):
        instance = super(OrderCreateView, self).forms_valid(form, inlines)
        ct = ContentType.objects.get_for_model(self.model)
        print('all items', [item.item_name for item in self.object.items.all()])  # items
        print('all tags', [tag.tag_name for tag in
                           TagsInline.model.objects.filter(content_type=ct, object_id=self.object.id)])  # tags
        return instance

class OrderUpdateView(UpdateWithInlinesView):
    # ... 

    def get_context_data(self, **kwargs):
        context = super(OrderUpdateView, self).get_context_data(**kwargs)
        ct = ContentType.objects.get_for_model(self.model)
        print('all items', [item.item_name for item in self.object.items.all()])  # items
        print('all tags', [tag.tag_name for tag in
                           TagsInline.model.objects.filter(content_type=ct, object_id=self.object.id)])  # tags
        return context