【问题标题】:Django rest framework queryset passing problemDjango rest框架查询集传递问题
【发布时间】:2021-09-13 10:24:01
【问题描述】:

我有几天遇到问题但从未得到任何解决方案,我尝试了不同的方法但没有成功。我想在同一个视图或路径中传递多个查询集。

@api_view(['GET'])
def getProduct(request, pk):
    product = Product.objects.get(_id=pk)
    related = Product.objects.filter(category=product.category).exclude(_id=pk).order_by('?')[:4]
    print(related)
    serializer = ProductSerializer(product, many=False)
    return Response(serializer.data)
    

我想在同一视图中传递与此处相关的相关产品查询集。在第一部分中,我将展示正在运行的产品详细信息,在下一部分中,我想展示相关但现在我该如何应用它??

我得到了一些解决方案,告诉我去使用序列化程序并在那里进行更改。但我不这么认为,因为我在那里尝试过,但这是怎么可能的。所以任何人都有更好的解决方案。我的相关对象具有相同的序列化程序,即 productserializer。但最终它是相关产品。

#这是我的序列化程序类

class ProductSerializer(serializers.ModelSerializer):
    user = serializers.SerializerMethodField(read_only=True)
    class Meta:
        model = Product
        fields = '__all__'

    def get_user(self, obj):
        user = obj.user
        serializer = VendorSerializer(user, many=False)
        return serializer.data

#这是我的产品型号

class Product(models.Model):

    brand_choices = [

        ('TVS', 'TVS'),
        ('Hero', 'Hero'),
        ('Yamaha', 'TVS'),
        ('Minister', 'Minister'),
        ('Walton', 'Walton'),
        ('Suzuki', 'Suzuki'),

    ]

    user = models.ForeignKey(Vendor, on_delete=models.CASCADE)
    name = models.CharField(max_length=220)
    image = models.ImageField(null=True, blank=True)
    brand = models.CharField(max_length=220, null=True, blank=True, choices=brand_choices)
    category = models.ForeignKey(Subcategory, on_delete=models.CASCADE)
    description = models.TextField(max_length=10000)
    rating = models.DecimalField(max_digits=7, decimal_places=2, blank=True, null=True)
    numReviews = models.IntegerField(null=True, blank=True, default=0)
    old_price = models.DecimalField(max_digits=11, decimal_places=2)
    discount = models.IntegerField(blank=True, null=True)
    price = models.DecimalField(max_digits=12, decimal_places=2, blank=True, null=True)
    countInStock = models.IntegerField(blank=True, null=True, default=0)
    createdAt = models.DateTimeField(auto_now_add=True)
    short_description = models.CharField(max_length=2000, blank=True, null=True)
    brandImage = models.ImageField(null=True, blank=True)
    isStorm = models.BooleanField(blank=True, null=True, default=False)
    _id = models.AutoField(primary_key=True, editable=False)
    

    def save(self, *args, **kwargs):
        self.price = Decimal(self.old_price * (100 - self.discount) / 100)
        return super(Product, self).save(*args, **kwargs)
    

    class Meta:
        ordering = ['-createdAt']


    def __str__(self):
        return self.name

这是我更新的序列化程序代码

class ProductWithRelatedSerializer(ProductSerializer):
    related = serializers.SerializerMethodField(read_only=True)
    
    class Meta:
        model = Product
        fields = '__all__'

    def get_related(self, obj, pk):
        product = Product.objects.all()
        related = Product.objects.filter(category=
            product.category).exclude(_id=pk).order_by('?')[:4].select_related('Product')[:4]
        ps = ProductSerializer(related, many=True)
        return ps.data

这是我的看法

@api_view(['GET'])
def getProduct(request, pk):
    product = Product.objects.get(_id=pk)
    # related = Product.objects.filter(category=product.category).exclude(_id=pk).order_by('?')[:4]
    # print(related)
    serializer = ProductWithRelatedSerializer(product, many=False)
    return Response(serializer.data)
    

更新的序列化器

class ProductWithRelatedSerializer(ProductSerializer):
    related = serializers.SerializerMethodField(read_only=True)
    
    class Meta:
        model = Product
        fields = '__all__'

    def get_related(self, obj):
        product = Product.objects.all()
        related = Product.objects.filter(category=
            product.category).exclude(_id=obj.pk).order_by('?')[:4].select_related('Product')[:4]
        ps = ProductSerializer(related, many=True)
        return ps.data

#product details page我用react你能帮我检查一下吗

import React, { useState, useEffect } from 'react'
import { Link } from 'react-router-dom'
import { Row, Col, Image, ListGroup, Form, Button, Card, Modal } from 'react-bootstrap'
import Rating from '../components/Rating'
import Loader from '../components/Loader'
import Message from '../components/Message'
import products from '../products'
import { useDispatch, useSelector } from 'react-redux'
import { listProductDetails } from '../actions/productActions'
import { productDetailsReducer } from '../reducers/productReducers'
import {InlineShareButtons} from 'sharethis-reactjs';
import {InlineFollowButtons} from 'sharethis-reactjs';
import { addToCart, removeFromCart } from '../actions/cartActions'
import { LinkContainer } from 'react-router-bootstrap'
import { Container} from 'react-floating-action-button'


function ProductScreen({ match, history }) {
    
    const cart = useSelector(state => state.cart)
    const { cartItems } = cart

    const removeFromCartHandler = (id) => {
        dispatch(removeFromCart(id))
    }

    const checkoutHandler = () => {
        history.push('/login?redirect=shipping')
    }

    const [show, setShow] = useState(false);
  
    const handleClose = () => setShow(false);

    const handleShow = () => setShow(true);

    const [qty, setQty] = useState(1)

    const dispatch = useDispatch()

    const productDetails = useSelector(state => state.productDetails)
    const {loading, error, product, related} = productDetails

    useEffect(() => {
        dispatch(listProductDetails(match.params.id))
    }, [dispatch, match])

    const addToCartHandler = () => {
        history.push(`/cart/${match.params.id}?qty=${qty}`)
    }
    
    return (
        <div>
            <Container>
             
                <Button
                    tooltip="Cart"
                    icon=""
                    rotate={true}
                    onClick={handleShow}
                    className="btn btn-primary btn-circle btn-xl"><i className="fas fa-shopping-cart" style={{fontSize:23}}><sup className='shanto'>{cartItems.length}</sup></i></Button>
            </Container>

            <Link to='/' className='btn btn-light my-3'><strong>Go Back</strong></Link>
            {loading ?
                <Loader />
                : error
                    ? <Message variant='danger'>{error}</Message>
                :(
                            <Row>
                                <Col md={6}>
                                    
                                    <Image src={product.image} alt={product.name} fluid />
                                </Col>
                                
                               
                            
                                <Col md={3}>
                                    <ListGroup variant="flush">
                                        <ListGroup.Item>
                                            <h3>{product.name}</h3>
                                        </ListGroup.Item>

                                        <ListGroup.Item>
                                            <h3>{related.id}</h3>
                                        </ListGroup.Item>


                                        <ListGroup.Item>
                                            Old Price: <strong className="tk">৳</strong><del> {product.old_price} </del>
                                        </ListGroup.Item>

                                        <ListGroup.Item >
                                            Discount: <b>{product.discount}%</b>
                                        </ListGroup.Item>

                                        <ListGroup.Item>
                                            Price: <strong className="tk">৳</strong> {product.price}
                                        </ListGroup.Item>


                                        <ListGroup.Item style={{color: 'red'}}>
                                            <p><b>{product.short_description}</b></p> 
                                        </ListGroup.Item>


 

【问题讨论】:

    标签: django django-rest-framework


    【解决方案1】:

    您可以实现一个ProductWithRelatedSerializer,利用ProductSerializer 对产品进行序列化。因此,我们从ProductSerializer 继承:

    class ProductWithRelatedSerializer(ProductSerializer):
        related = serializers.SerializerMethodField(read_only=True)
    
        def get_related(self, obj):
            related = Product.objects.filter(
                category_id=obj.category_id
            ).exclude(_id=obj.pk).order_by('?').select_related('user')[:4]
            ps = ProductSerializer(related, many=True)
            return ps.data

    .select_related(…) [Django-doc] 不是必需的,但会为相关产品提升ProductSerializerget_user 方法。

    这将因此返回如下响应:

    {
        /* … */
        "user": {
            …
        },
        related: [
             { "user": { … } },
             { "user": { … } },
             { "user": { … } },
             { "user": { … } }
        ]
    }

    【讨论】:

    • 那我怎么在前端查看呢??
    • data.related 是序列化产品列表。因此,它为“外部”产品添加了一个额外的字段related,您可以枚举列表以呈现相关产品,就像您呈现所选产品一样。
    • 我的意思是我的视图文件是什么,在这个序列化程序中它说产品和 pk 未定义所以我查询了 product = Product.objects.all() 然后调用产品对象和 pk我将它作为参数传递,但它说缺少一个位置参数
    • @SohanurRahmanShanto16209570:您将视图中的 serializer = ProductSerializer(product, many=False) 替换为 serializer = ProductWithRelatedSerializer(product, many=False)
    • 兄弟非常感谢您的努力。但这给了我错误,例如找不到产品并且缺少位置参数 pk
    猜你喜欢
    • 2016-08-06
    • 1970-01-01
    • 2020-10-20
    • 2015-05-08
    • 2014-09-19
    • 1970-01-01
    • 2016-01-10
    • 2014-12-19
    • 1970-01-01
    相关资源
    最近更新 更多