如何使用Django中的通用视图CreateView自定义窗体的视图

时间:2012-03-29 08:01:51

标签: django django-forms django-templates django-urls

我对Django的form不太满意。

以下是来自Order

models.py
class Order( models.Model ) :
    def __unicode__( self ) :
        return unicode( self.pk )

    def get_absolute_url( self ) :
        return reverse( 'orders_detail', args = [ self.pk ] )

    STATUS_CHOICES = (
        ( 'p', 'pending'  ),
        ( 'a', 'approved' ),
        ( 'r', 'rejected' ),
        ( 'c', 'closed'   ),
        ( 'l', 'locked'   ),
    )

    WORK_TYPE_CHOICES = (
        ( 'hc', 'Heating and cooling' ),
        ( 'el', 'Electrical'          ),
        ( 'pl', 'Plumbing'            ),
        ( 'ap', 'Appliances'          ),
        ( 'pe', 'Pests'               ),
        ( 'ex', 'Exterior'            ),
        ( 'in', 'Interior'            ),
        ( 'sa', 'Safety'              ),
        ( 'ot', 'Others'              ),
    )

    creator   = models.ForeignKey( User, related_name = 'creator' )
    approver  = models.ForeignKey( User, related_name = 'approver' )
    comments  = models.TextField( blank = True )
    status    = models.CharField( max_length = 1, choices = STATUS_CHOICES, default = 'p' )
    quote     = models.DecimalField( max_digits = 8, decimal_places = 2, null = True, blank = True )
    payment   = models.DecimalField( max_digits = 8, decimal_places = 2, null = True, blank = True )
    work_type = models.CharField( max_length = 2, choices = WORK_TYPE_CHOICES )
    vendor    = models.ForeignKey( Vendor, null = True, blank = True )
    created   = models.DateTimeField( auto_now_add = True )
    modified  = models.DateTimeField( auto_now = True )

class OrderCreateForm( ModelForm ) :
    class Meta :
        model = Order
        fields = (
            'creator',
            'approver',
            'comments',
            'work_type',
        )

到目前为止,我在[{1}}

中使用CreateView模型的通用视图Order
urls.py

在我的模板中,我只是

url(
    r'^orders/create/$',
    CreateView.as_view(
        model = Order,
        template_name = 'doors/orders/create.html',
        form_class = OrderCreateForm
    ),
    name = 'orders_create'
),

它会像这样创建一个部分表单(没有提交按钮)

但是,我想根据{% extends "base.html" %} {% block title %}Create order{% endblock %} {% block content %} {{ form }} {% endblock %} 控制creatorapprover字段的可见性。如果登录用户的user.get_profile().user_type不是管理员,则user_type会自动设置为用户,creator也会自动设置。如果approver 是管理员,那么该用户可以将这两个字段指定给不同的用户。

我还希望能够命名每个字段的实际标签。例如,将user_type更改为Work type

目前我认为唯一的方法是在模板中执行Category并运行一堆像{% for field in form %}这样的行。有一种比一堆受控循环和if-then语句更简单的方法吗?

1 个答案:

答案 0 :(得分:2)

  

我想根据user.get_profile()。user_type控制创建者和审批者字段的可见性。如果登录用户的user_type不是管理员,则创建者将自动设置为用户,并且还将自动设置批准者。如果user_type是管理员,则该用户可以将这两个字段指定给不同的用户。

我只为用户制作另一种形式:

class UserOrderCreateForm( ModelForm ) :
    class Meta :
        model = Order
        fields = (
            'comments',
            'work_type',
        )

    def __init__(self, *args, **kwargs):
         self.user = kwargs.pop('user')
        super(UserOrderCreateForm, self).__init__(*args, **kwargs)

    def save(self):
        result = super(UserOrderCreateForm, self).save(commit=False)
        result.creator = self.user
        result.approver = self.user.some_other_field # "will be set also set automatically"
        result.save()
        return result

然后您可以决定在视图中使用哪种表单。像

一样使用它
form = UserOrderCreateForm(user=request.user)

我认为您必须花一些时间才能使其与CreateView一起使用。这就是我不喜欢CBV的原因。 : - )

  

我还希望能够命名每个字段的实际标签。例如,将Work type更改为Category

work_type = models.CharField( max_length = 2, choices = WORK_TYPE_CHOICES, verbose_name=u'Category')