博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
rbac 权限分配, 基于formset实现,批量编辑
阅读量:4926 次
发布时间:2019-06-11

本文共 7124 字,大约阅读时间需要 23 分钟。

已经完成了  批量添加的功能。 还想要一个批量修改的功能了。

随之而来的第一个问题就是,  我们的formset 并不是一条记录。而是 多条记录,甚至整个表的记录。
那么显而易见的问题就是,当前端页面把数据,返回给服务端的时候。  我怎么就知道,这条数据,是对应的数据库的那一条记录呢?
毕竟  不管是  title、 url、 name、 menu_id、 pid_id  都无法保证我去数据库中,找到与之相对应的这条记录。

所以我们就只能再加上一个字段,就是每一条数据的 主键 id 字段。

所以,我的form类,就得这么写了:

UpdateMultiPermissionForm
class UpdateMultiPermissionForm(forms.Form):    id = forms.IntegerField(widget=forms.HiddenInput)    title = forms.CharField(widget=forms.TextInput(attrs={
"class": "form-control"})) url = forms.CharField(widget=forms.TextInput(attrs={
"class": "form-control"})) name = forms.CharField(widget=forms.TextInput(attrs={
"class": "form-control"})) menu_id = forms.ChoiceField( # ChoiceField 和 choices 就表示数据源 choices=[(None, "---------")], widget=forms.Select(attrs={
"class": "form-control"}), required=False ) pid_id = forms.ChoiceField( choices=[(None, "---------")], widget=forms.Select(attrs={
"class": "form-control"}), required=False ) # 因为 menu_id 和 pid_id ,应该是一个可以选择的下拉框形式, 所以重写了 __init__初始化函数。 # 让fields对象中的这两个字段, 与数据库中查询出的结果,进行拼接 def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields["menu_id"].choices += models.Menu.objects.values_list("mid", "title") self.fields["pid_id"].choices += models.Permission.objects.filter(pid__isnull=True).exclude( menu__isnull=True).values_list("id", "title") # 过滤出 pid==Null的 可以做二级菜单的, exclude排除 menu==Null,不属于任何一个一级菜单的。所有的权限记录
id = forms.IntegerField(widget=forms.HiddenInput) 这个HiddenInput 就是要在前端页面上,渲染成一个隐藏的 input 标签。(ps:如果在控制台更改了这个input标签的value值,你猜会怎么样?)

anyway! 再创建一个编辑用的,页面吧! multi_edit.html

    
Title
{
% csrf_token %} {
{ formset.management_form }}
{
% for form in formset %}
{
% for field in form %} {
% if forloop.first %} {
{ field }} {
% else %}
{
% endif %} {
% endfor %}
{
% endfor %}
标题 url Code Menu 权限
{
{ field }} { { field.errors.0 }}
multi_edit.html

还记得  field  对象是什么样子吗?

 对 这就是 field 对象, 里面保存的东西!  可以看到,一共有 6 个标签。

第一个是一个需要隐藏起来的  input 标签。 因为这个是 id  不能让用户,更改。 更改了这个。 可就没法确定这条数据是对应的数据库那条记录了。
然后前端页面渲染的时候,也不能直接就,还像添加页面那样处理。   因为第一个标签,是需要隐藏起来的, 不能给他添加一个 <td></td> 标签。否则页面就乱了
所以加上一个判断  forloop.first  如果是第一次循环的话, 就只放一个 input 标签在这就好, 并且因为是隐藏的,不会扰乱页面。

OK 到这里。 渲染工作。 就做得差不多了! 然后就是 要怎么更新数据了!

def multi_edit(request):    formset_class = formset_factory(UpdateMultiPermissionForm, extra=0)    if request.method == "POST":        formset = formset_class(data=request.POST)        if formset.is_valid():            post_row_date = formset.cleaned_data            for i in range(0, formset.total_form_count()):                row = post_row_date[i]                if not row:                    continue                permission_id = row.pop("id")                models.Permission.objects.filter(pk=permission_id).update(**row)        return render(request, "multi_edit.html", {
"formset": formset}) formset = formset_class(initial=models.Permission.objects.all() .values("id", "title", "url", "name", "menu_id", "pid_id")) return render(request, "multi_edit.html", {
"formset": formset})
def multi_edit(request):

这样就可以进行保存了。   然后问题就又 回来了!!   还是 唯一性 的问题:

def multi_edit(request):    formset_class = formset_factory(UpdateMultiPermissionForm, extra=0)    if request.method == "POST":        formset = formset_class(data=request.POST)        if formset.is_valid():            post_row_date = formset.cleaned_data            for i in range(0, formset.total_form_count()):                row = post_row_date[i]                if not row:                    continue                permission_id = row.pop("id")                try:                    permission_obj = models.Permission.objects.filter(pk=permission_id).first()  # 取出数据库中与当前permission_id相对应的数据对象           #  然后 对应的 赋值。 在没有 seve() 之前, 是不会对数据库 有任何更改的。 说白了permission_obj现在只是内存中的一个model对象。                    permission_obj.title = row.get("title")                    permission_obj.name = row.get("name")                    permission_obj.url = row.get("url")                    permission_obj.menu_id = row.get("menu_id")                    permission_obj.pid_id = row.get("pid_id")                    permission_obj.validate_unique()  # 全部赋值完成之后,检测唯一性。  存在就抛出已存在的异常。                    permission_obj.save()  # 如果没有抛出异常, 就进行保存的操作。                except Exception as e:                    pass        return render(request, "multi_edit.html", {
"formset": formset}) formset = formset_class(initial=models.Permission.objects.all() .values("id", "title", "url", "name", "menu_id", "pid_id")) return render(request, "multi_edit.html", {
"formset": formset})
def multi_edit(request):

 emmmmm  这样搞虽然麻烦一点,但是还是能完成任务的。  有没有简单一点的方法呢?

答案是一定有的:  这里用到了 类中  反射思想。   如果忘了,去看看笔记把:
完整版代码:

def multi_edit(request):    formset_class = formset_factory(UpdateMultiPermissionForm, extra=0)    if request.method == "POST":        formset = formset_class(data=request.POST)        if formset.is_valid():            post_row_date = formset.cleaned_data            flag = True            for i in range(0, formset.total_form_count()):                row = post_row_date[i]                if not row:                    continue                permission_id = row.pop("id")                try:                    permission_obj = models.Permission.objects.filter(pk=permission_id).first()                    for key, value in row.items():                        setattr(permission_obj, key, value)                    permission_obj.validate_unique()                    permission_obj.save()                except Exception as e:                    formset.errors[i].update(e)                    flag = False            if flag:                return HttpResponse("更新成功")            # else:            #     return render(request, "multi_edit.html", {"formset": formset})        return render(request, "multi_edit.html", {
"formset": formset}) formset = formset_class(initial=models.Permission.objects.all() .values("id", "title", "url", "name", "menu_id", "pid_id")) return render(request, "multi_edit.html", {
"formset": formset})
def multi_edit(request): 完整版

这里要提一句: 前端中 每一行 就是一个form 。 进行保存的时候并没有说,多个form中,有一个出错的,其他的也不进行保存。

而是 出错的这条form  不会进行保存。  其他的没有出错的, 并不会受到影响。
还有就是  类的 反射。 是一个很重要的, 知识点,很重要的一个思想。  多多复习!

最后提一下 formset_class = formset_factory(UpdateMultiPermissionForm, extra=0)
这个formset_factory 默认会渲染一个form对象。 所以用的时候  extra 改成0. 就行了!

 

转载于:https://www.cnblogs.com/chengege/p/10719062.html

你可能感兴趣的文章
Unity3D初学心得
查看>>
学破解 <二> PE格式之IMAGE_NT_HEADERS
查看>>
laravel homestead
查看>>
https和http共存的nginx简单配置
查看>>
利用WGET下载文件,并保存到指定目录
查看>>
AO代码:VB6代码迁移到NET的几大理由(摘自ESRI文档片段)
查看>>
HDOJ 1518 Square
查看>>
Finance 网站收集
查看>>
如何使用Git 下载GitHub的东西
查看>>
C#实现联合体
查看>>
[BZOJ 1085] [SCOI2005] 骑士精神 [ IDA* 搜索 ]
查看>>
nignx 502错误不能使用/的路径方式 即pathinfo
查看>>
java APIs for database -------- JDBC (2)<statement>
查看>>
Xpath
查看>>
LoadRunner 参数化之 连接数据库进行参数化
查看>>
bugku秋名山老司机+写博客的第一天
查看>>
小程序,用js获取当前系统时间并显示
查看>>
数据库sql的主要关键字的执行顺序
查看>>
Linux之Libcurl库的介绍与应用20170509
查看>>
通过sqlserver日志恢复误删除的数据
查看>>