Поле внешнего ключа Django не обновляется выбранным значением из выпадающего списка React Select

#reactjs #django #django-models #django-rest-framework #react-select

#reactjs #django #django-модели #django-rest-framework #реагировать-выбрать

Вопрос:

У меня есть веб-страница в моем проекте отслеживания проблем, которая позволяет менеджеру проекта назначать пользователя проекту. Я использую React Select, чтобы позволить менеджеру выбирать пользователя из выпадающего списка. Когда они нажимают кнопку «Добавить пользователя», выбранное значение отправляется на серверную часть через вызов api. У меня есть APIView с именем assignuser, который принимает post-запрос и обновляет поле внешнего ключа пользователя в моей модели проекта.

Я неправильно ссылаюсь на выбранное значение? Я попытался отправить SelectedValue.значение для моего бэкэнда, но оно продолжает отображаться как неопределенное. Имейте в виду, очевидно, при консоли.оба значения журнала SelectedValue {label: "...", value: "..."} находятся в SelectedValue. Это также относится к SV в project.js это отправляется в manageusers.js . Я просто пытаюсь ссылаться на значение и успешно отправлять его в мой 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")
 

manageusers.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 amp;amp; 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 amp;amp; 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)
 

Ответ №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>
  )
}
 

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 = (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 amp;amp; 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;
 

Комментарии:

1. что делает validated_data?

2. Итак, я пытаюсь взять выбранное значение из моего интерфейса, отправить его назначающему пользователю и установить внешний ключ с именем user в моей модели проекта с этим выбранным значением. Этот код, который у вас есть, только что получает последний проект в наборе запросов и возвращает его.

3. по-прежнему безуспешно, я внес правку выше, чтобы уточнить, о чем я говорил

4. может быть, вы имеете в виду, что когда пользователь нажимает кнопку, она автоматически появляется в выпадающем списке?

5. может быть , вот так