Skip to main content
 首页 » 编程设计

python之在 Python3 Django 的 ManyToMany 关系中不工作 .add() 函数

2024年10月01日33lautakyan007

现在我正在使用 Django 中的 ManyToManyField 设计数据模型。

我想让每个 session 都有不同的乐器,

i.e)

A have a bass.

B have a drum.

所以,我测试了下一个代码

from django.test import TestCase 
from Session.models import Instrument 
from Applicants.models import MyUser 
from Session.models import Session 
 
class InstTest(TestCase): 
    def setUp(self): 
        i1 = Instrument.objects.create(name='bass') 
        i1.save() 
        i2 = Instrument.objects.create(name='guitar') 
        i2.save() 
        i3 = Instrument.objects.create(name='drum') 
        i3.save() 
 
        u1 = MyUser.objects.create(email='a@gmail.com', nickname='A') 
        u1.save() 
        u2 = MyUser.objects.create(email='b@gmail.com', nickname='B') 
        u2.save() 
 
        s1 = Session.objects.create(players=u1) 
        s1.save() 
        s1.instruments.add(i1) 
 
        s2 = Session.objects.create(players=u2) 
        s2.save() 
        s2.instruments.create(name='drum') 
 
    def test_example(self): 
        bass = Instrument.objects.get(name='bass') 
        guitar = Instrument.objects.get(name='guitar') 
        user = MyUser.objects.get(nickname='A') 
        session = Session.objects.get(players=user) 
        self.assertEqual('bass', bass.name) 
        self.assertEqual('A', session.players.nickname) 
 
        # My problem is in this line 
        self.assertEqual('bass', session.instruments.name) 

这是 Pycharm 中的结果

/home/user/vEnv/bin/python /home/user/pycharm-2016.3.2/helpers/pydev/pydevd.py --multiproc --qt-support --client 127.0.0.1 --port 40507 --file /home/user/pycharm-2016.3.2/helpers/pycharm/django_test_manage.py test BandMaker.tests.InstTest.test_example /home/user/PycharmProjects/Project 
Testing started at --:-- PM ... 
warning: Debugger speedups using cython not found. Run '"/home/user/vEnv/bin/python" "/home/user/pycharm-2016.3.2/helpers/pydev/setup_cython.py" build_ext --inplace' to build. 
pydev debugger: process 4984 is connecting 
 
Connected to pydev debugger (build 163.10154.50) 
Creating test database for alias 'default'... 
 
Failure 
Traceback (most recent call last): 
  File "/home/user/PycharmProjects/project/BandMaker/tests.py", line 31, in test_example 
    self.assertEqual('bass', player.instruments.name) 
AssertionError: 'bass' != None 
 
Destroying test database for alias 'default'... 
 
Process finished with exit code 1 

我尝试以其他方式进行测试,例如 s1.instruments.create(name='bass') ,但我只能看到 'bass' != None 。

我不明白为什么 s1.instruments.add(i1) 不工作。 所以我需要谁来帮助我。

还有,这里是其他模型类。

/Session/models.py

from django.db import models 
from Applicants.models import MyUser 
 
# Create your models here. 
class Session(models.Model): 
    players = models.ForeignKey( 
        MyUser, 
        verbose_name='own user info', 
        related_name='%(app_label)s_%(class)s_related' 
    ) 
 
    instruments = models.ManyToManyField( 
        'Session.Instrument', 
        verbose_name='Session Instrument List', 
        related_name='%(app_label)s_%(class)s_instruments' 
    ) 
 
class Instrument(models.Model): 
    name = models.CharField(max_length=50, verbose_name='instrument name') 

自定义用户类

from django.db import models 
from django.contrib.auth.models import ( 
    BaseUserManager, AbstractBaseUser 
) 
 
class MyUserManager(BaseUserManager): 
    def create_user(self, email, nickname, password=None): 
        """ 
        Creates and saves a User with the given email, date of 
        birth and password. 
        """ 
        if not email: 
            raise ValueError('Users must have an email address') 
 
        user = self.model( 
            email=self.normalize_email(email), 
            nickname=nickname, 
        ) 
 
        user.set_password(password) 
        user.save(using=self._db) 
        return user 
 
    def create_superuser(self, email, nickname, password): 
        """ 
        Creates and saves a superuser with the given email, date of 
        birth and password. 
        """ 
        user = self.create_user( 
            email=email, 
            password=password, 
            nickname=nickname, 
        ) 
        user.is_admin = True 
        user.save(using=self._db) 
        return user 
 
 
class MyUser(AbstractBaseUser): 
    email = models.EmailField( 
        verbose_name='email', 
        max_length=255, 
        unique=True, 
    ) 
    nickname = models.CharField( 
        verbose_name='nickname', 
        max_length=50, 
        blank=False, 
        unique=False, 
        default='unknown' 
    ) 
    is_active = models.BooleanField(default=True) 
    is_admin = models.BooleanField(default=False) 
 
    objects = MyUserManager() 
 
    USERNAME_FIELD = 'email'    # When username is required, You must use this field! 
    REQUIRED_FIELDS = ['nickname'] 
 
    def get_full_name(self): 
        # The user is identified by their email address 
        return self.email 
 
    def get_short_name(self): 
        # The user is identified by their email address 
        return self.email 
 
    def __str__(self):              # __unicode__ on Python 2 
        return self.email 
 
    def has_perm(self, perm, obj=None): 
        "Does the user have a specific permission?" 
        # Simplest possible answer: Yes, always 
        return True 
 
    def has_module_perms(self, app_label): 
        "Does the user have permissions to view the app `app_label`?" 
        # Simplest possible answer: Yes, always 
        return True 
 
    @property 
    def is_staff(self): 
        "Is the user a member of staff?" 
        # Simplest possible answer: All admins are staff 
        return self.is_admin 

请您参考如下方法:

问题是您测试 session 是否有仪器的方式:

self.assertEqual('bass', session.instruments.name)

session.instruments 没有属性名称,它是一个 ManyToMany 对象。

我认为这个测试应该可行:

self.assertEqual('bass', session.instruments.all()[0].name)