简体   繁体   中英

Django Rest & React: lookup_field = 'slug' not returning item from db

I'm trying to return items from my sqlite db such that the url in the browser reflects the slug, rather than the unique post id.

I had this working before by using the primary key, whereby items were returned from the db when clicking a hyperlink for item detail - but swapping everything out for slug is not working.

I have a PostListView in react which lists my items from the db successfully, when I click on one of these the url field in the browser properly shows the slug. However, no data is returned from the db in the underlying detail view.

I am using django 2.2.1, django rest framework and react.

Back end - django and rest framework modules:

Models.py

class Post(models.Model):
    post_id = models.UUIDField(
    primary_key=True, default=uuid.uuid4, help_text='Unique ID for this post')
    title = models.CharField(max_length=100)
    content = models.TextField()
    publish_date = models.DateTimeField(auto_now=True)
    slug = models.SlugField(default='')

api/views.py

class PostListView(ListAPIView):
    queryset = Post.objects.all()
    serializer_class = PostSerializer


class PostDetailView(RetrieveAPIView):
    queryset = Post.objects.all()
    serializer_class = PostSerializer
    lookup_field = 'slug'

api/urls.py

urlpatterns = [
    path('', PostListView.as_view()),
    path('<slug>', PostDetailView.as_view()),
]

api/serializers.py

class PostSerializer(serializers.ModelSerializer):
''' Serialisers will convert our JSON from web into python model '''
class Meta:
    model = Post
    fields = ('post_id', 'slug', 'title', 'content', 'publish_date' )
    lookup_field = 'slug'

Frontend - React:

PostListView.js

class PostList extends React.Component {

    state = {
        posts: []
    }

    componentDidMount() {
        // this function gets called everytime the component is mounted(rendered)
        axios.get('http://127.0.0.1:8000/api/')
            .then(res => {
                this.setState({
                    posts: res.data
                });
            console.log(res.data);
            })
    }

    render() {
        return (
            <Post data={this.state.posts} />
        )
    }
}

Post.js

const Post = (props) => {
    const { classes, data } = props;
    return (
        <List className={classes.root}>
            {data.map((item, key) =>
              <ListItem alignItems="flex-start" key={item.post_id}>
              <ListItemText
                  primary={<a href={`/${item.slug}`}>{item.title}</a>}
                  secondary={
                  <React.Fragment>
                      <Typography component="span" className={classes.inline} color="textPrimary">
                      {item.content}
                      </Typography>
                  </React.Fragment>
                  }
              />
              </ListItem>
              )}
        </List>
    );
}

PostDetailView.js

class PostDetail extends React.Component {

    state = {
        post: {}
    }

    componentDidMount() {
        // this function gets called everytime the component is mounted(rendered)
        const slug = this.props.match.params.slug;
        axios.get(`http://127.0.0.1:8000/api/${slug}`)
            .then(res => {
                this.setState({
                    post: res.data
                });
            })
    }

    render() {
        return (
            <Card title={this.state.post.title}> 
                <p>{this.state.post.content}</p>
            </Card>
        )
    }
}

I found that I needed to change the path handling the routing to PostDetail in my BaseRouter component as follows:

const BaseRouter = () => (
<div>
    <Route exact path='/' component={PostList} />
    <Route exact path='/:postID' component={PostDetail} />
</div>

);

To

<Route exact path='/:slug' component={PostDetail} />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM