2017-08-03 73 views
0

我想訪問InlineFormSet的字段以供消耗到視圖中。django-extra-views將InlineFormSet字段值暴露到get_context_data()和forms_valid()方法

這裏是基於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的InlineFormSet字段()forms_valid()方法警告:以下代碼失敗!

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) 

回答

1

我轉載這個模型的例子:

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 

的url:

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你不能在 get_context_data方法,因爲他們還沒有被創建讀TagItem記錄。

  • 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 
+0

對不起,這似乎並沒有工作。我嘗試添加inlines_names = ['items','tags']來直接訪問命名變量,因爲我不知道如何訪問'inline_instance'。你能更加明確嗎?謝謝! – jcuot

+0

哦,你想從模型中讀取數據,而不是'InlineFormSet'字段。我更新了答案,請檢查。 –