【问题标题】:Django foreign key field not updating with selected value from React Select dropdownDjango 外键字段未使用 React Select 下拉列表中的选定值更新
【发布时间】:2021-04-15 21:09:18
【问题描述】:

我的问题跟踪器项目中有一个网页,允许项目经理将用户分配给项目。我正在使用 React Select 来允许经理从下拉列表中选择用户。当他们单击添加用户按钮时,选定的值会通过 api 调用发送到后端。我有一个名为 assignuser 的 APIView,它接收 post 请求并更新我的 Project 模型中的用户外键字段。

我是否引用了错误的值?我尝试将 selectedValue.value 发送到我的后端,但它一直显示为未定义。请记住,很明显,当您 console.log selectedValue {label: "...", value: "..."} 都在 selectedValue 中时。这也适用于发送到 manageusers.js 的 project.js 中的 SV。我只是想参考价值并将其成功发送到我的 APIView 并更新特定项目的用户。

project.js

manageusers.js

Django 后端

class assignuser(APIView):
    serializer_class = ProjectSerializer

    def post(self, request, format=None):
        serializer = self.serializer_class(data=request.data)
        if serializer.is_valid():
            user = serializer.data.get('user')
            project_name = serializer.data.get('project_name')
            project = Project.objects.get(name=project_name)
            project.user = user
            project.save(update_fields=['user'])
            return Response(ProjectSerializer(project).data, status=status.HTTP_201_CREATED)
        else:
            return HttpResponse("Incorrect Credentials")

ma​​nageusers.js

import React, { Component } from "react";
import { useState, useEffect } from "react";
import { Grid, TextField, Button, Typography } from "@material-ui/core";
import { FixedSizeList as List } from 'react-window';
import css from './style.css';
import Select from 'react-select';
import {useLocation} from "react-router";

const manageusers = () => {
  const [role, setRole] = useState([]);
  const location = useLocation();
  const [project_name, setProjectName] = useState();
  const [selectedValue, setSelectedValue] = useState()
  const rolelist = [];

  const handleChange = obj => {
      setSelectedValue(obj);
  }

  useEffect(() => {
    fetch("/api/manageroles")
    .then((response) => response.json())
    .then((data) =>{
        setRole(data)
    })
  }, [])

  const post = () => {
    const requestOptions = {
      method: "POST",
      headers: { "Content-Type": "application/json"},
      body: JSON.stringify({
        user: selectedValue,
        project_name: project_name
      }),
    };
    fetch("/api/assignuser",requestOptions)
      .then((response) => response.text())
      .then((data) =>{
       
      })
      .catch((error) => {
        console.log(error)
      });
  }

  const Name = () => {
      return (
        <div>
            <Grid item xs={3}>
                <Typography component="h5" variant="h5">
                    {setProjectName(location.state.project_name)}
                </Typography>
            </Grid>  
        </div>
      )
    
  }

      return (
          <div>  
            {role.forEach(function(element) {
                rolelist.push({ label:element.username, value: element.username })
            })}
            <Select
                value={selectedValue}
                options={rolelist}
                onChange={handleChange}
                isOptionDisabled={option => option.isDisabled}
            />
            <div class="ex1">
                {role && role.map(roles => (
                        <Grid item xs={3}>
                            <Typography component="h5" variant="h5">
                                <h5> {roles.username} </h5>
                            </Typography>
                        </Grid>
                ))}
            </div>
            <div>
                <Button onClick={() => post()}> Add User</Button>
            </div>
            <Name/>
        </div>
      );
      
  }

export default manageusers;

project.js

import React, { Component } from "react";
import { useState, useEffect } from "react";
import { Grid, TextField, Button, Typography } from "@material-ui/core";
import {
    BrowserRouter as Router,
    Link,
    Route,
    Switch,
  } from 'react-router-dom';
import Select from 'react-select';

const project = () => {
  const [name, setName] = useState();
  const [description, setDescription] = useState();
  const [projects, setProjects] = useState([]);
  const [selectedValue, setSelectedValue] = useState(null)
  const projectlist = [];
  
  const handleChange = obj => {
      setSelectedValue(obj);
  }

  const post = () => {
    const requestOptions = {
      method: "POST",
      headers: { "Content-Type": "application/json"},
      body: JSON.stringify({
        name: name,  
        description: description,
      }),
    };
    fetch("/api/newProject",requestOptions)
      .then((response) => response.json())
      .then((data) =>{
       
      })
  }

  useEffect(() => {
    fetch("/api/manageprojects")
    .then((response) => response.json())
    .then((data) =>{
        setProjects(data)
    })
  }, [])

      return (
        <div>
           {projects.forEach(function(element) {
                projectlist.push({ value: element.name })
            })}
          <body>
            <Select 
                  value={selectedValue}
                  options={projectlist}
                  onChange={handleChange}
                  isOptionDisabled={option => option.isDisabled}
              />
              <form action="#" method="POST">
                <TextField onChange={(e) => setName(e.target.value)}> </TextField>
                <br>
                </br>
                <TextField onChange={(e) => setDescription(e.target.value)}> </TextField>
                <br>
                </br>
                <Button onClick={() => post()}> Create New Project </Button>
              </form>
          </body>
          <div>
                {projects && projects.map(project => (
                    <Grid item xs={3}>
                        <Typography component="h5" variant="h5">
                            <h5> {project.name} </h5>
                            <h5> {project.description} </h5>
                        </Typography>
                    </Grid>
                ))}
          </div>
          <Link to={{
            pathname: '/manageusers',
            state: { 
                project_name: selectedValue
            }
          }}>Manage Users
          </Link>
        </div>
      );
  }
 


export default project;

项目模型

class Project(models.Model):
    name = models.CharField(max_length=50, unique=True)
    description = models.CharField(max_length=50, unique=True)
    user = models.ForeignKey(Users, null=True, blank=True, 
    on_delete=models.CASCADE)

【问题讨论】:

    标签: reactjs django django-models django-rest-framework react-select


    【解决方案1】:

    你可以这样做

    class assignuser(APIView):
        serializer_class = ProjectSerializer
    
        def post(self, request, format=None):
            serializer = self.serializer_class(data=request.data)
            if serializer.is_valid():
                project = serializer.validated_data.get("project_name")
                project.user = serializer.validated_data.get("user")
                project.save()
                return Response(ProjectSerializer(project).data, status=status.HTTP_201_CREATED)
            else:
                return HttpResponse("Incorrect Credentials")
    
    fetch("/api/assignuser",requestOptions)
          .then((response) => response.text())
          .then((data) =>{
             setRole([...role, data])    
          })
          .catch((error) => {
            console.log(error)
          });
    

    或者您可以在不从后端获取新数据的情况下添加新值,

    为什么我要提供这个选项,当您将数据发送到后端时,它将自动为该用户保存,并且当用户重新加载时,将出现的页面的值保持不变

      const post = () => {
        const requestOptions = {
          method: "POST",
          headers: { "Content-Type": "application/json"},
          body: JSON.stringify({
            user: selectedValue,
            project_name: project_name
          }),
        };
        fetch("/api/assignuser",requestOptions)
          .then((response) => response.text())
          .then((data) =>{
            setRole([...role, {label: project_name, value: project_name}])
          })
          .catch((error) => {
            console.log(error)
          });
      }
    

    base.js

    const Base = () => {
      const [selectedValue, setSelectedValue] = React.useState()
      return (
        <div>
           <ManagerUser selectedValue={selectedValue} setProjectName={setSelectedValue}/>
           <Project selectedValue={selectedValue} setProjectName={setSelectedValue}/>
       </div>
      )
    }
    

    项目.js

    import React, { Component } from "react";
    import { useState, useEffect } from "react";
    import { Grid, TextField, Button, Typography } from "@material-ui/core";
    import {
        BrowserRouter as Router,
        Link,
        Route,
        Switch,
      } from 'react-router-dom';
    import Select from 'react-select';
    
    const project = (props) => {
      const {selectedValue,setSelectedValue} = props
      const [name, setName] = useState();
      const [description, setDescription] = useState();
      const [projects, setProjects] = useState([]);
      const projectlist = [];
      
      const handleChange = obj => {
          setSelectedValue(obj);
      }
    
      const post = () => {
        const requestOptions = {
          method: "POST",
          headers: { "Content-Type": "application/json"},
          body: JSON.stringify({
            name: name,  
            description: description,
          }),
        };
        fetch("/api/newProject",requestOptions)
          .then((response) => response.json())
          .then((data) =>{
           
          })
      }
    
      useEffect(() => {
        fetch("/api/manageprojects")
        .then((response) => response.json())
        .then((data) =>{
            setProjects(data)
        })
      }, [])
    
          return (
            <div>
               {projects.forEach(function(element) {
                    projectlist.push({ value: element.name })
                })}
              <body>
                <Select 
                      value={selectedValue}
                      options={projectlist}
                      onChange={handleChange}
                      isOptionDisabled={option => option.isDisabled}
                  />
                  <form action="#" method="POST">
                    <TextField onChange={(e) => setName(e.target.value)}> </TextField>
                    <br>
                    </br>
                    <TextField onChange={(e) => setDescription(e.target.value)}> </TextField>
                    <br>
                    </br>
                    <Button onClick={() => post()}> Create New Project </Button>
                  </form>
              </body>
              <div>
                    {projects && projects.map(project => (
                        <Grid item xs={3}>
                            <Typography component="h5" variant="h5">
                                <h5> {project.name} </h5>
                                <h5> {project.description} </h5>
                            </Typography>
                        </Grid>
                    ))}
              </div>
              <Link to={{
                pathname: '/manageusers',
                state: { 
                    project_name: selectedValue
                }
              }}>Manage Users
              </Link>
            </div>
          );
      }
     
    
    
    export default project;
    

    【讨论】:

    • validated_data 是做什么的?
    • 所以我试图从我的前端获取选定的值,将其发送给 assignuser,并在我的项目模型中使用该选定值设置名为 user 的外键。您刚刚获取查询集中的最后一个项目并返回它的代码。
    • 还是没有运气,我在上面进行了编辑以澄清我在说什么
    • 也许你的意思是,当用户点击按钮时,它会自动出现在下拉列表中?
    • 可能是这样的
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-02
    • 1970-01-01
    • 1970-01-01
    • 2019-07-29
    • 2015-04-24
    • 1970-01-01
    • 2023-03-13
    相关资源
    最近更新 更多