Django:条件为

时间:2017-03-24 13:58:47

标签: django django-models django-forms django-templates django-views

我正在尝试创建一个表单变量。默认播放器的级别为0,他只需更改名称即可。后来当他成为1级时,他可以改变名字而且是化身。当他是3级时,他可以改变名字,是化身并且是工作。等...

Models.py:

class Player(models.Model):
    level = models.SmallIntegerField(default=0) 
    name = models.CharField(max_length=50)
    avatar = models.URLField(default='http://default-picture.com/01.png')
    job =  models.TextField(null=True)

Fomrs.py:

class ProfileForm(forms.ModelForm):

class Meta:
    model = Player
    fields = ['name', 'avatar', 'job']
    widgets = {
        'name': forms.TextInput(),
        'avatar': forms.TextInput(),
        'job': forms.Textarea(),
    }

Views.py:

def game(request, id):
    user = get_object_or_404(Player, id=id)
    if request.method == 'POST':
        form = ProfileForm(request.POST, instance=user)
        if form.is_valid():
            form.save()
            return HttpResponse('Success')
    else:
        form = ProfileForm(instance=user)
    return render(request, "page/template.html",
            {'form': form})

Template.html:

{{ form }}

在将表单呈现给渲染工具之前,可以为表单的渲染添加条件吗?或者我需要在有条件的模板中执行此操作?

我只是在允许instanced对象根据其中一个参数获得更多或更少的positibilies(在例子中是播放器的级别)。

3 个答案:

答案 0 :(得分:3)

您可以覆盖表单的class ProfileForm(forms.ModelForm): ... def __init__(self, *args, **kwargs): super(ProfileForm, self).__init__(*args, **kwargs) if self.instance and self.instance.level < 3: self.fields['job'].disabled = True # still displays the field in the template # del self.fields['job'] # removes field from form and template if self.instance and self.instance.level < 1: self.fields['avatar'].disabled = True 方法,以有条件地删除或禁用字段:

/* --
1. use `bagof` to obtain a list of the solutions to query `generate_expression(N, E)` .
2. use recursion to :
    2a. iterate each item in the list .
    2b. then assign it a sequence number .
    2c. then print it  .
-- */

/*
example usage :

?- print_expressions_f .
(0000001, generate_expression(4,[op(neg),[[op(neg),[[op(neg),[[number(0)]]]]]]]))
(0000002, generate_expression(4,[op(neg),[[op(add),[[number(0)],[number(0)]]]]]))
(0000003, generate_expression(4,[op(add),[[number(0)],[op(neg),[[number(0)]]]]]))
(0000004, generate_expression(4,[op(add),[[op(neg),[[number(0)]]],[number(0)]]]))
true ;
false.
*/

print_expressions_f :-
    Stream = user_output,
    Prefix = '(',
    Suffix = ')',
    N = 4,
    print_expressions_f(Stream, Prefix, Suffix, N).

print_expressions_f(Stream, Prefix, Suffix, N) :-
    Query = generate_expression(N, E) ,
    bagof(Query,Query,BagofE) ,
    print_expressions_f_every(Stream, Prefix, Suffix, BagofE) .

print_expressions_f_every(Stream, Prefix, Suffix, BagofE) :-
    print_expressions_f_each(Stream, Prefix, Suffix, BagofE, 10'1) .

print_expressions_f_each(Stream, Prefix, Suffix, BagofE, Sequence_number) :-
    [] = BagofE ,
    true .

print_expressions_f_each(Stream, Prefix, Suffix, BagofE, Sequence_number) :-
    [BagofE_head|BagofE_tail] = BagofE ,
    print_expression(Stream, Prefix, Suffix, Sequence_number, BagofE_head) ,
    Sequence_number_next #= Sequence_number + 1 ,
    print_expressions_f_each(Stream, Prefix, Suffix, BagofE_tail, Sequence_number_next) .

答案 1 :(得分:1)

Django pre_save signal可用于解决此问题。 保存模型之前,将调用hook pre_save。您可以在那里写条件以检查是否允许用户更改字段。

您还需要存储模型的副本以比较pre_save中的状态,可以通过post_init挂钩来完成。

from django.dispatch import receiver , Signal
from django.db.models.signals import post_init , pre_save

@receiver(pre_init , sender = Player)
def cache(sender , instance , **kwargs):
    instance.__original_name = instance.name
    instance.__original_avatar = instance.avatar
    instance.__original_job = instance.job
@receiver(pre_save , sender= Player)
def check_update(sender , instance , **kwargs):
    if instance.level == 1:
        #Revert changes to avatar and job, and keep changes in the name
    if instance.level == 2:
        #Revert changes to job , and keep changes in the name and avatar
    if instance.level == 3:
        #Keep all changes

这样您就可以跟踪所有更新字段。

答案 2 :(得分:1)

您可以在init方法

中实现自定义表单

对于之前描述的情况,您可以执行以下操作:

class ProfileForm(forms.ModelForm):

    class Meta:
        model = Player
        fields = ['name', 'avatar', 'job']
        widgets = {
            'name': forms.TextInput(),
            'avatar': forms.TextInput(),
            'job': forms.Textarea(),
        }

    def __init__(self, *args, **kwargs):
        super(ProfileForm, self).__init__(*args, **kwargs)
        # checking if an instance exist
        if self.instance.id:
            # then at this point you can set as read only the fields about each case

            if self.instance.level < 1:
                self.fields["avatar"].widget.attrs["readonly"] = True
                self.fields["job"].widget.attrs["readonly"] = True
            elif self.instance.level >= 1 and self.instance.level < 3:
                self.fields["job"].widget.attrs["readonly"] = True