Python Django post请求正在返回模型表单的querydict而不是对象id

Python Django post请求正在返回模型表单的querydict而不是对象id,python,django,django-forms,django-templates,Python,Django,Django Forms,Django Templates,我有模型 class CollectionForm(forms.ModelForm): Medicine_Name = forms.ModelChoiceField(queryset=Medicine.objects.all()) class Meta: model = Medicine fields = ['Number_Of_Boxes', 'Last_Collected'] def __init__(self, user =

我有模型

class CollectionForm(forms.ModelForm):
    Medicine_Name = forms.ModelChoiceField(queryset=Medicine.objects.all())
   
    class Meta:
        model = Medicine
        fields = ['Number_Of_Boxes', 'Last_Collected']

    def __init__(self, user = None, *args, **kwargs):
        super().__init__(*args, **kwargs)
        
        if user:
            self.fields['Medicine_Name'].queryset=Medicine.objects.filter(User_Associated=user)
以及处理表单的视图:

def update(request, *args, **kwargs):
     

        
    if request.method == 'POST':
        qd = request.POST['chosen_medicine']
       
        instance = Medicine.objects.get(id=qd)    
        form = CollectionForm(request.POST,  instance=instance)
       
        if form.is_valid():                 
            instance = form.save(commit=False)                
            instance.save()
    else:
        form = CollectionForm() 
    context = {'form': form,
            'meds': Medicine.objects.filter(User_Associated=request.user),
    }

    return render(request, 'tracker/medicine_collection.html', context )
表单的模板如下所示:

<form method="POST" action = ''>
    {% csrf_token %}
    <label for="Medicine_Name">Medicine Name</label>
    <select class = "form-control" id = "Medicine_Name"  name = "chosen_medicine">
        {% for med in meds %}
          
            <option value = '{{med.auto_id}}'>{{ med.Medicine_Name }}</option>
        {% endfor %}
    
    </select>
           
    {{form.Number_Of_Boxes  }}
    
    {{form.Last_Collected }}
    
  
    <button class="btn btn-outline-info" type="submit">Create</button>
</form>

{%csrf_令牌%}
药名
{med中的med百分比为%}
{{med.Medicine_Name}
{%endfor%}
{{form.Number{u-Of-u-box}}
{{form.Last_Collected}}
创造
我正在尝试获取用户从下拉列表中选择的药品名称的id。为此,我在视图中有一个获取id的POST请求。但是,在提交表单时,我收到了错误:

Field 'id' expected a number but got <QueryDict: {'csrfmiddlewaretoken': ['rrkPEpuZqxWQ9TS4lLMRDwAQ7xZAOUVZl8iHLVfZJ8gEfKundDMvDh9oWp42l1Jf'], 'chosen_medicine': ['1'], 'Number_Of_Boxes': ['3'], 'Last_Collected': ['03/16/2020']}>.
字段“id”应为一个数字,但未找到。

如何确保POST请求实际获得ID,而不是包含表单所有字段的querydict?

一些快速而混乱的方法可能会奏效

data = dict(qd.iterlists())
instance = Medicine.objects.get(id=int(data.get('chosen_medicine')[0]))

但在我看来,如果你只需要一个id,你甚至不应该发布一个完整的查询集。

一些快速而混乱的东西可能会奏效

data = dict(qd.iterlists())
instance = Medicine.objects.get(id=int(data.get('chosen_medicine')[0]))

但在我看来,如果您只需要一个id,甚至不应该发布整个查询集。

您可以定义构造函数,以便位置参数仍然保留:

class CollectionForm(forms.ModelForm):
   
    class Meta:
        model = Medicine
        fields = ['Number_Of_Boxes', 'Last_Collected']

    def __init__(self, *args, user=None, **kwargs):
        super().__init__(*args, **kwargs)
        
        if user:
            self.fields['Medicine_Name'].queryset=Medicine.objects.filter(
                User_Associated=user
            )
类集合表单(forms.ModelForm):
类元:
模型=医学
字段=[“盒子的数量”,“上次收集的数量”]
定义初始化(self,*args,user=None,**kwargs):
super()
如果用户:
self.fields['Medicine\u Name'].queryset=Medicine.objects.filter(
用户\u关联=用户
)
然后在视图中,将用户作为命名参数传递:

def update(request, *args, **kwargs):
    if request.method == 'POST':
        qd = request.POST['chosen_medicine']
        instance = Medicine.objects.get(id=qd)    
        form = CollectionForm(request.POST, instance=instance, user=request.user)
       
        if form.is_valid():                 
            instance = form.save()
    else:
        form = CollectionForm(user=request.user)
    context = {'form': form,
            'meds': Medicine.objects.filter(User_Associated=request.user),
    }
    return render(request, 'tracker/medicine_collection.html', context)
def更新(请求,*args,**kwargs):
如果request.method==“POST”:
qd=请求.发布['selected_medicine']
实例=Medicine.objects.get(id=qd)
form=CollectionForm(request.POST,instance=instance,user=request.user)
如果form.is_有效():
instance=form.save()
其他:
表单=集合表单(用户=请求.用户)
上下文={'form':form,
“meds”:Medicine.objects.filter(User_Associated=request.User),
}
返回渲染(请求“tracker/medicine\u collection.html”上下文)
HTML看起来也很“奇怪”,尤其是属性周围的间距:

<form method="POST" action="">
    {% csrf_token %}
    <label for="Medicine_Name">Medicine Name</label>
    <select class="form-control" id="Medicine_Name" name="chosen_medicine">
        {% for med in meds %}
            <option value="{{ med.id }}">{{ med.Medicine_Name }}</option>
        {% endfor %}
    </select>    
    {{ form.Number_Of_Boxes  }}
    {{ form.Last_Collected }}
    <button class="btn btn-outline-info" type="submit">Create</button>
</form>

{%csrf_令牌%}
药名
{med中的med百分比为%}
{{med.Medicine_Name}
{%endfor%}
{{form.Number{u-Of-u-box}}
{{form.Last_Collected}}
创造

注意:如果POST请求成功,您应该 实施。 这样可以避免在用户刷新日志时发出相同的POST请求 浏览器


您可以定义构造函数,以便位置参数仍然保留:

class CollectionForm(forms.ModelForm):
   
    class Meta:
        model = Medicine
        fields = ['Number_Of_Boxes', 'Last_Collected']

    def __init__(self, *args, user=None, **kwargs):
        super().__init__(*args, **kwargs)
        
        if user:
            self.fields['Medicine_Name'].queryset=Medicine.objects.filter(
                User_Associated=user
            )
类集合表单(forms.ModelForm):
类元:
模型=医学
字段=[“盒子的数量”,“上次收集的数量”]
定义初始化(self,*args,user=None,**kwargs):
super()
如果用户:
self.fields['Medicine\u Name'].queryset=Medicine.objects.filter(
用户\u关联=用户
)
然后在视图中,将用户作为命名参数传递:

def update(request, *args, **kwargs):
    if request.method == 'POST':
        qd = request.POST['chosen_medicine']
        instance = Medicine.objects.get(id=qd)    
        form = CollectionForm(request.POST, instance=instance, user=request.user)
       
        if form.is_valid():                 
            instance = form.save()
    else:
        form = CollectionForm(user=request.user)
    context = {'form': form,
            'meds': Medicine.objects.filter(User_Associated=request.user),
    }
    return render(request, 'tracker/medicine_collection.html', context)
def更新(请求,*args,**kwargs):
如果request.method==“POST”:
qd=请求.发布['selected_medicine']
实例=Medicine.objects.get(id=qd)
form=CollectionForm(request.POST,instance=instance,user=request.user)
如果form.is_有效():
instance=form.save()
其他:
表单=集合表单(用户=请求.用户)
上下文={'form':form,
“meds”:Medicine.objects.filter(User_Associated=request.User),
}
返回渲染(请求“tracker/medicine\u collection.html”上下文)
HTML看起来也很“奇怪”,尤其是属性周围的间距:

<form method="POST" action="">
    {% csrf_token %}
    <label for="Medicine_Name">Medicine Name</label>
    <select class="form-control" id="Medicine_Name" name="chosen_medicine">
        {% for med in meds %}
            <option value="{{ med.id }}">{{ med.Medicine_Name }}</option>
        {% endfor %}
    </select>    
    {{ form.Number_Of_Boxes  }}
    {{ form.Last_Collected }}
    <button class="btn btn-outline-info" type="submit">Create</button>
</form>

{%csrf_令牌%}
药名
{med中的med百分比为%}
{{med.Medicine_Name}
{%endfor%}
{{form.Number{u-Of-u-box}}
{{form.Last_Collected}}
创造

注意:如果POST请求成功,您应该 实施。 这样可以避免在用户刷新日志时发出相同的POST请求 浏览器


request.POST
user
参数捕获。那么,我的init方法中的问题是否在表单中?我如何解决这个问题呢?
request.POST
user
参数捕获。我的init方法中的问题也在表单中吗?我该如何解决这个问题呢?嗯,我需要在我的视图中发布所有要处理的字段,但我最初只需要id来定义实例。有没有一种很好的方法可以将它们分开,而不将它们一起发布到querydict中?好吧,我需要在我的视图中发布所有要处理的字段,但我最初只需要id来定义实例。有没有一种很好的方法可以将它们分开,而不让它们一起发布在查询信息中?我实现了你的代码,但是现在我得到了错误
字段“id”期望一个数字,但得到了“”。
因此它不再发布“选择的药物”。然后,这意味着你的
选择的药物
从HTML表单中没有返回值(它返回了空的stringas值)。但是表单与此无关,因此这是模板中的一个错误。HTML中的间距看起来也很奇怪(如果不是无效的话)@Smasher640:这不应该是
med.id
作为值吗?@Smasher640:注意它确实发布了一些东西,因为否则它会引发一个
KeyError
。很好,这样做之后它就像预期的那样工作。我实现了你的代码,但我现在得到的错误
字段“id”应该是一个数字,但得到了“”。
所以它不再有效了r张贴“选择的药物”。那么它的意思是你的
选择的药物