Django Queryset по нескольким внешним ключам
I am struggling with building a QuerySet to get all objects belonging to the current logged-in user. The bills are assigned to a Customer
, and CustomerUser
objects are assigned to the Customer
:
┌──────┐ ┌──────────┐
│ Bill │ ───► │ Customer │
└──────┘ FK └──────────┘
▲
│
│ FK
┌──────────────┐
│ CustomerUser │
└──────────────┘
│
│ FK
▼
┌──────────────────────────┐
│ contrib.auth.models.User │
└──────────────────────────┘
Модели:
class Bill(models.Model):
date = models.DateField(blank=False)
total = models.FloatField(blank=False, null=False, default=0.0)
customer = models.ForeignKey(Customer, null=True, on_delete=models.SET_NULL)
class Customer(models.Model):
name = models.CharField(max_length=25, blank=False, null=False)
class CustomerUser(models.Model):
first_name = models.CharField(max_length=30, blank=True, null=True)
last_name = models.CharField(max_length=30, blank=True, null=True)
user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True)
Basically I want to craft a QuerySet that returns the Bill
objects the CustomerUser
has access to. Can this be done with a single QuerySet?
Сначала включите внешний ключ в модель customer с именем поля 'custom_user', связывающий с моделью customuser
class Customer(models.Model):
name = models.CharField(max_length=25, blank=False, null=False)
custom_user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, blank=True, null=True)
и затем вы можете использовать запрос как
Bill.objects.filter(customer__custom_user__user_id=logged_in_user_id)
Вы забыли включить один fk
между CustomerUser
и Customer
, поэтому я сделал некоторые предположения, но что-то вроде этого должно работать. В основном вам нужно соединить ваши модели с помощью сериализаторов и передать соответствующие related_name
.
# serializers
class BillSerializer(serializers.ModelSerializer):
class Meta:
model = Bill
fields = ('id',)
class CustomerSerializer(serializers.ModelSerializer):
bills = BillSerializer(read_only=True, many=True, source='bill_set')
class Meta:
model = Customer
fields = ('id', 'bills')
class CustomerUserSerializer(serializers.ModelSerializer):
customer = CustomerSerializer(read_only=True)
class Meta:
model = CustomerUser
fields = ('id', 'customer')
class UserSerializer(serializers.ModelSerializer):
customer_users = CustomerUserSerializer(many=True, read_only=True, source='customer_user_set')
class Meta:
model = User
fields = ('customer_users',)
# viewset
class UserViewSet(mixins.RetrieveModelMixin, GenericViewSet):
serializer_class = UserSerializer
def get_queryset(self):
user = self.request.user
queryset = super().get_queryset()
queryset = queryset.filter(pk=user.pk)
return queryset
Помните о предварительной выборке всего, что вам нужно, потому что этот select может быть довольно тяжелым.