我正在尝试创建一个表单变量。默认播放器的级别为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(在例子中是播放器的级别)。
答案 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