【问题标题】:How to save a Model Form with a foreign key of User to django models如何将具有用户外键的模型表单保存到 django 模型
【发布时间】:2019-08-02 14:25:30
【问题描述】:

我正在尝试将用户 API 密钥保存到具有 User 外键的 Django 模型中,这样每组唯一的 API 密钥在数据库中都有一个与它们相关联的唯一用户。 如果用户没有关联的 API 密钥,我希望当用户单击“帐户”时出现 api 密钥输入表单,如果用户确实具有关联的 API 密钥,则显示“您的密钥已输入”的消息。

我正在使用内置的 Django 用户模型,并在 forms.py 中创建了自己的模型表单。

我尝试在模型表单和元类中包含用户无济于事。 在保存之前,我尝试将密钥和密码作为参数传递给模型和表单。 在将用户添加到 form.user 之前,我尝试使用提交设置为 False 的表单实例。 我曾尝试查找最新的 Django 文档,但其内容分散且难以理解。

我故意省略了这个问题不必要的导入。

这是我的 Models.py

from django.db import models
from django.contrib.auth.models import User
from django.conf import settings

# Create your models here.

class UserApiDetails(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, default=None)
    key = models.CharField(max_length=32)
    password = models.CharField(max_length=32)

    def __str__(self):
        out = "key: " + str(self.key) + '\n' + "Password: " + str(self.password)
        return out

     # this is the method that checks if the user has existing API keys
    def keys_exist(self): 
        if UserApiDetails.objects.filter(pk=User).exists():
            return True
        else:
            return False

这是我的 forms.py

from django import forms
from .models import UserApiDetails

class ApiKeysForm(forms.ModelForm):
    key = forms.CharField(max_length=200, label="Api Key")
    password = forms.CharField(max_length=200, widget=forms.PasswordInput, label="Api password")

    class Meta:
        model = UserApiDetails
        fields = {'password', 'key', }

这是我的views.py

from django.shortcuts import render, redirect
from .models import UserApiDetails  # tables in database from models.py
from django.http import JsonResponse, HttpResponse
from django.contrib.auth.models import User
from . import forms
from .forms import ApiKeysForm  # the forms that will get data & pass to views
from django.template.loader import render_to_string

import sys

sys.path.insert(1, '/Development applications/python dev/TradingBot')
# backend imports
from Main import update, trade # methods in bot
from API_comm import ConnAPI  # conn API class used to set keys & session AUTH


# Create your views here.

def account_request(request):
    if request.method == 'POST':

        form = forms.ApiKeysForm(request.POST)
        if form.is_valid():
            key = form.cleaned_data.get('key')
            password = form.cleaned_data.get('password')
            instance = form.save(commit=False)
            instance.user = request.user
            instance.save()
            c = {
                "key": key,
                "password": password
            }

            result = ConnAPI.set_keys(key, password)  # gets the return from the set keys method
            messages.success(request, result)  # a toast to display if the api conn was successful or not
            return redirect("main:homepage")
    else:
        form = forms.ApiKeysForm(request.POST)

    context = {
        "form": form,
    }

    return render(request,
                  "main/account.html",
                  context)

这是我的 account.html 模板

{% extends "main/header.html" %}
{% block content%}

{% if UserApiDetails.keys_exist %}

<div class="row1">
    <h2>Your Api Keys have already been entered.</h2>
    <div class="col s12 m8 14">
        <p></p>
    </div>

</div>

{% else %}

<div class="row2">
    <form class="col s12 " action="/account/" method="POST">
        {% csrf_token %}
        {{form.as_p}}

        <div class="col s12 m6 14">
            <button class="btn" type="submit">Submit Api Keys</button>
        </div>

    </form>
</div>

{% endif %}

{% endblock %}

编辑 我已经设法用唯一用户保存了 API 详细信息,但我正在努力确保每个用户只输入一组密钥。

当确实拥有与其帐户关联的 API 密钥的用户单击“帐户”时,仍会显示表单,而不是 div ID 为“Row1”的 HTML。

【问题讨论】:

    标签: python html django django-models django-forms


    【解决方案1】:

    您的代码存在一些问题,您正在混合实例和类:

    • 首先您的keys_exist() 函数是错误的,因为您在查询的过滤器中使用了pk=User,这没有任何意义。 User 是类用户,pk 是您的 UserApiDetails 实例的主键,因此它们永远不可能相等。您需要针对User 进行测试instance

      @classmethod
      def keys_exist(cls, user):
          return cls.objects.filter(user=user).exists()
      

      注意:在你的 User 模型上写这个方法会更干净,但你似乎没有自定义 User 并且正在使用普通的 Django 用户模型,所以在这种情况下这很好。

    • 其次,由于您需要将用户作为参数传递给函数,因此您不能直接在模板中调用它。因此,要么将结果添加到您的上下文中(并在您的模板中使用它),要么创建一个自定义模板过滤器。我将展示第一种方法。在您看来,像这样定义您的上下文:

      context = {'form': form, 'has_keys': UserApiDetails.keys_exist(request.user)}
      

      然后在您的模板中,您只需检查{% if has_keys %}

    【讨论】:

      【解决方案2】:

      我已经设法解决了这个问题:

      我首先必须在 models.py 中更改我的 keys_exist() 方法,如下所示:

      def keys_exist(request):  # had to pass request to use request.user in the filter
          if UserApiDetails.objects.filter(user=request.user).exists():  # where foreign key = current logged user
              print("User has API details")
              return True
          else:
              print("User does not have API details")
              return False
      

      然后我必须将以下内容添加到我的 account_request() 视图中:

          if models.keys_exist(request): # pass request to use in modely.py
              context = {
                  "form": form,
                  "exists": True,
              }
          else:
              context = {
                  "form": form,
                  "exists": False,
              }
      

      确保在调用 .keys_exist()

      传递请求

      最后我更改了 account.html 模板中的 if 语句

      {% if exists  %}  <!-- Do not use the double braces or == true within the code blocks -->
      .
      .
      .
      {% else %}     <!-- ensure this is not elif -->
      .
      .
      .
      {% endif %}
      
      
      

      【讨论】:

        猜你喜欢
        • 2023-03-29
        • 1970-01-01
        • 2020-10-16
        • 2020-11-07
        • 1970-01-01
        • 2021-10-29
        • 2012-08-04
        • 1970-01-01
        • 2020-02-29
        相关资源
        最近更新 更多