Я начинающий пользователь python/django, пытаюсь протестировать вложенный сериализатор и получаю 'TypeError: Direct assignment to the reverse side of a relatedset'

Я пытаюсь написать тест, чтобы показать, что я могу сериализовать клиента и передать подписки, на которые клиент подписался, в настоящее время только на одну подписку, но я верю, что то, что у меня есть, будет работать для нескольких подписок. Это мой первый раз, когда я делаю что-то на python, и я не знаю внутреннюю работу и не знаю, что я здесь напутал

Вот мой файл test_serializer.py

class CustomerSerializerTestCase(unittest.TestCase):

  def setUp(self):
    self.subscription_attributes = {
      'title': 'Tea Partay',
      'price': 50.99,
      'status': 'active',
      'frequency': 'monthly'
    }

    self.customer_attributes = {
      'first_name': 'Hai',
      'last_name': 'Sall',
      'email': 'sailt&peppa@saimall.com',
      'address': 'this place Seattle, WA',
      'subscriptions': 'self.subscription.id'
    }

    self.subscription = Subscription.objects.create(**self.subscription_attributes)
    self.serialzied_subscription = SubscriptionSerializer(instance=self.subscription)
    self.customer = Customer.objects.create(**self.customer_attributes)
    self.serialized_customer = CustomerSerializer(instance=self.customer)
    
  def test_customer_serializer_has_correct_keys(self):
    customer_att = {
      'first_name': 'pachary',
      'last_name': 'zrince',
      'email': 'Ilovelittlekatanas@hotkatana.com',
      'address': 'katana ln, maldorf, Waryland'
    }

    customer = Customer.objects.create(**customer_att)
    serialized_customer = CustomerSerializer(instance = customer)
    data = serialized_customer.data

    self.assertEqual(set(data.keys()), set(['first_name', 'last_name', 'email', 'address', 'subscriptions']))

  def test_customer_field_contents(self):
    customer_data = self.serialized_customer.data

    self.assertEqual(customer_data['first_name'], self.customer_attributes['first_name'])
    self.assertEqual(customer_data['last_name'], self.customer_attributes['last_name'])
    self.assertEqual(customer_data['email'], self.customer_attributes['email'])
    self.assertEqual(customer_data['address'], self.customer_attributes['address'])
    self.assertEqual(customer_data['subscriptions'], self.subscription_attributes['title'])
    self.assertEqual(customer_data['subscriptions'], self.subscription_attributes['price'])
    self.assertEqual(customer_data['subscriptions'], self.subscription_attributes['status'])
    self.assertEqual(customer_data['subscriptions'], self.subscription_attributes['frequency'])

Вот мой models.py

class Tea(models.Model):#has_many :subscriptions
  title = models.CharField(max_length = 100)
  description = models.CharField(max_length = 1000)
  temperature = models.IntegerField()
  brew_time = models.IntegerField()

class Customer(models.Model):#has_many :subscriptions
  first_name = models.CharField(max_length = 100)
  last_name = models.CharField(max_length = 100)
  email = models.EmailField(max_length = 300)
  address = models.CharField(max_length = 500)

class Subscription(models.Model):#belongs_to :customers, :tea
  status_choice = {
    ('active', 'active'),
    ('cancelled', 'cancelled')
  }

  title = models.CharField(max_length = 100)
  price = models.FloatField()
  status = models.CharField(max_length = 100, choices = status_choice)
  frequency = models.CharField(max_length = 100)
  customers = models.ForeignKey(Customer, related_name = 'subscriptions', blank = True, null = True, on_delete = models.CASCADE)
  teas = models.ForeignKey(Tea, blank = True, null = True, on_delete = models.CASCADE)

и Вот фактический serializer.py

class SubscriptionSerializer(serializers.ModelSerializer):
  class Meta: 
    model = Subscription
    fields = ['title', 'price', 'status', 'frequency']

class CustomerSerializer(serializers.ModelSerializer):
  subscriptions = SubscriptionSerializer(many=True)
  class Meta: 
    model = Customer 
    fields = ['first_name', 'last_name', 'email', 'address', 'subscriptions']

  def create(self, validated_data):
    subscriptions_data = validated_data.pop('subscriptions')
    customer = Customer.objects.create(**validated_data)
    for subscription_data in subscriptions_data:
      Subscription.objects.create(customer = customer, **subscription_data)
    return customer

Вот полная трассировка стека для ошибки, которую я сейчас получаю:

Traceback (most recent call last):
  File "/Users/parkerthomson/take_home_challenges/python/tea_subscription/tea_subscription_api/tests/test_serializers.py", line 77, in setUp
    self.customer = Customer.objects.create(**self.customer_attributes)
  File "/Users/parkerthomson/take_home_challenges/python/lib/python3.10/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/Users/parkerthomson/take_home_challenges/python/lib/python3.10/site-packages/django/db/models/query.py", line 669, in create
    obj = self.model(**kwargs)
  File "/Users/parkerthomson/take_home_challenges/python/lib/python3.10/site-packages/django/db/models/base.py", line 562, in __init__
    _setattr(self, prop, value)
  File "/Users/parkerthomson/take_home_challenges/python/lib/python3.10/site-packages/django/db/models/fields/related_descriptors.py", line 595, in __set__
    raise TypeError(
TypeError: Direct assignment to the reverse side of a related set is prohibited. Use subscriptions.set() instead.

Я пытаюсь написать тест, который доказывает, что клиент может быть сериализован для отображения его подписок.

Вы не можете назначить подписки непосредственно в функции Customer.objects.create - вам нужно задать ее отдельно.

Если вы удалите 'subscriptions' из self.customer_attributes, это должно сработать.

Затем вы можете обновить подписку через

Subscription.objects.filter(id=self.subscription_id).update(customers=self.customer)
Вернуться на верх