如何使用来自相关模型的新信息字段注释查询集?
How to annotate a queryset with a new field of information from a related model?
我有一个模型,其中 Vehicle
table 有更多 Wheels
table。我试图在单个字段中显示相关车轮 table 中车辆和第一个车轮的信息。我已经看到 F
函数可能有用,但我找不到正确的配置让它工作。 table 通过另一个名为 colour
的字段关联,该字段在 Wheels
table.
中声明为外键
class VehicleListView(ListView):
template_name = 'vehicle.html'
queryset = Vehicle.objects.all()
queryset = queryset.annotate(wheel1_name = F('Wheels__wheel_name'))
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
return context
我想要
queryset = queryset.annotate(wheel1_name = F('Wheels__wheel_name'))
到 return 每辆车的第一个车轮名称的列表,这样我就可以遍历它并在 table.
中显示
models.py
class Vehicle(models.Model):
vehicle_id = models.AutoField(primary_key=True)
vehicle_name = models.CharField(max_length=100)
color = models.CharField(max_length=100)
class Wheels(models.Model):
wheels_id = models.AutoField(primary_key=True)
color = models.ForeignKey(Vehicle, null=True, on_delete=models.SET_NULL,
db_column='color')
wheel_name = models.CharField(max_length=100)
所以我稍微更改了你的代码,设置了数据库,创建了 2 个 Vehicle
个对象,每个对象有 2 个相关的 Wheels
个对象,所以总共有 4 个 Wheels
个对象。
我为某个 Vehicle
对象的第一个相关 Wheel
对象添加了一个函数 queries。
# models.py
class Vehicle(models.Model):
vehicle_id = models.AutoField(primary_key=True)
vehicle_name = models.CharField(max_length=100)
color = models.CharField(max_length=100)
# this function returns a slice of the resulting queryset which contains
# the first related Wheels object for each Vehicle object
def get_first_wheels(self):
return Wheels.objects.filter(color=self).order_by('wheels_id')[:1]
class Wheels(models.Model):
wheels_id = models.AutoField(primary_key=True)
color = models.ForeignKey(Vehicle, null=True, on_delete=models.SET_NULL)
wheel_name = models.CharField(max_length=100)
我使用 Django serializers to serialize the data. To get the first related Wheels
object I used a SerializerMethodField()
调用 models.py
中的 get_first_wheels()
函数,如下所示:
# serializers.py
class WheelsSerializer(serializers.ModelSerializer):
class Meta:
model = Wheels
fields = ('wheels_id', 'color', 'wheel_name')
class VehicleSerializer(serializers.ModelSerializer):
first_wheel = serializers.SerializerMethodField(read_only=True)
def get_first_wheel(self, model):
qs = model.get_first_wheels()
return WheelsSerializer(qs, many=True).data
class Meta:
model = Vehicle
fields = ('vehicle_id', 'vehicle_name', 'color', 'first_wheel')
我稍微改变了你的看法,改用了 ModelViewSet
。
# views.py
class VehicleViewSet(viewsets.ModelViewSet):
serializer_class = VehicleSerializer
queryset = Vehicle.objects.all()
我去使用 DefaultRouter()
注册端点,如下所示:
# urls.py
from rest_framework import routers
# import ViewSet here
router = routers.DefaultRouter()
router.register(r'vehicles`, views.VehicleViewSet, base_name='vehicle')
然后我运行下面的命令:
manage.py makemigrations
manage.py migrate
manage.py runserver
我创建了 2 个 Vehicle
个对象,每个对象有 2 个相关的 Wheels
个对象。
当我在浏览器中转到 http://127.0.0.1:8000/vehicles/
时,它 returns 所有 Vehicle
对象及其第一个相关的 Wheels
对象,如下所示:
[
{
"vehicle_id": 1,
"vehicle_name": "BMW",
"color": "Blue",
"first_wheel": [
{
"wheels_id": 1,
"color": 1,
"wheel_name": "BMW1"
}
]
},
{
"vehicle_id": 2,
"vehicle_name": "Ferrari",
"color": "Red",
"first_wheel": [
{
"wheels_id": 3,
"color": 2,
"wheel_name": "Ferrari1"
}
]
}
]
我有一个模型,其中 Vehicle
table 有更多 Wheels
table。我试图在单个字段中显示相关车轮 table 中车辆和第一个车轮的信息。我已经看到 F
函数可能有用,但我找不到正确的配置让它工作。 table 通过另一个名为 colour
的字段关联,该字段在 Wheels
table.
class VehicleListView(ListView):
template_name = 'vehicle.html'
queryset = Vehicle.objects.all()
queryset = queryset.annotate(wheel1_name = F('Wheels__wheel_name'))
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
return context
我想要
queryset = queryset.annotate(wheel1_name = F('Wheels__wheel_name'))
到 return 每辆车的第一个车轮名称的列表,这样我就可以遍历它并在 table.
中显示models.py
class Vehicle(models.Model):
vehicle_id = models.AutoField(primary_key=True)
vehicle_name = models.CharField(max_length=100)
color = models.CharField(max_length=100)
class Wheels(models.Model):
wheels_id = models.AutoField(primary_key=True)
color = models.ForeignKey(Vehicle, null=True, on_delete=models.SET_NULL,
db_column='color')
wheel_name = models.CharField(max_length=100)
所以我稍微更改了你的代码,设置了数据库,创建了 2 个 Vehicle
个对象,每个对象有 2 个相关的 Wheels
个对象,所以总共有 4 个 Wheels
个对象。
我为某个 Vehicle
对象的第一个相关 Wheel
对象添加了一个函数 queries。
# models.py
class Vehicle(models.Model):
vehicle_id = models.AutoField(primary_key=True)
vehicle_name = models.CharField(max_length=100)
color = models.CharField(max_length=100)
# this function returns a slice of the resulting queryset which contains
# the first related Wheels object for each Vehicle object
def get_first_wheels(self):
return Wheels.objects.filter(color=self).order_by('wheels_id')[:1]
class Wheels(models.Model):
wheels_id = models.AutoField(primary_key=True)
color = models.ForeignKey(Vehicle, null=True, on_delete=models.SET_NULL)
wheel_name = models.CharField(max_length=100)
我使用 Django serializers to serialize the data. To get the first related Wheels
object I used a SerializerMethodField()
调用 models.py
中的 get_first_wheels()
函数,如下所示:
# serializers.py
class WheelsSerializer(serializers.ModelSerializer):
class Meta:
model = Wheels
fields = ('wheels_id', 'color', 'wheel_name')
class VehicleSerializer(serializers.ModelSerializer):
first_wheel = serializers.SerializerMethodField(read_only=True)
def get_first_wheel(self, model):
qs = model.get_first_wheels()
return WheelsSerializer(qs, many=True).data
class Meta:
model = Vehicle
fields = ('vehicle_id', 'vehicle_name', 'color', 'first_wheel')
我稍微改变了你的看法,改用了 ModelViewSet
。
# views.py
class VehicleViewSet(viewsets.ModelViewSet):
serializer_class = VehicleSerializer
queryset = Vehicle.objects.all()
我去使用 DefaultRouter()
注册端点,如下所示:
# urls.py
from rest_framework import routers
# import ViewSet here
router = routers.DefaultRouter()
router.register(r'vehicles`, views.VehicleViewSet, base_name='vehicle')
然后我运行下面的命令:
manage.py makemigrations
manage.py migrate
manage.py runserver
我创建了 2 个 Vehicle
个对象,每个对象有 2 个相关的 Wheels
个对象。
当我在浏览器中转到 http://127.0.0.1:8000/vehicles/
时,它 returns 所有 Vehicle
对象及其第一个相关的 Wheels
对象,如下所示:
[
{
"vehicle_id": 1,
"vehicle_name": "BMW",
"color": "Blue",
"first_wheel": [
{
"wheels_id": 1,
"color": 1,
"wheel_name": "BMW1"
}
]
},
{
"vehicle_id": 2,
"vehicle_name": "Ferrari",
"color": "Red",
"first_wheel": [
{
"wheels_id": 3,
"color": 2,
"wheel_name": "Ferrari1"
}
]
}
]