Django:m2m关系创建两行而不是一行

时间:2018-12-06 17:39:19

标签: django many-to-many django-orm

我以这种方式扩展了UserModel:

def read_wave(filename):

    fp=wave.open(filename,'r') 
    nchannels=fp.getnchannels()
    framerate=fp.getframerate()
    nframes=fp.getnframes()
    sampwidth=fp.getsampwidth()

    z_str=fp.readframes(nframes)
    fp.close()

    dtype_map={1:np.uint8,2:np.uint16}
    ys=np.frombuffer(z_str,dtype=dtype_map[sampwidth])

    waveObject=Wave(ys,framerate=framerate)

    return waveObject


class Wave:

    def __init__(self,ys,ts=None,framerate=None):

        # ys:wave array
        # ts:array of time


        self.ys=np.asanyarray(ys)
        self.framerate=framerate

        if ts is None:
            self.ts =np.arange(len(ys))/self.framerate
        else:
            self.ts=ts

    def make_spectrum(self):

        n=len(self.ys);
        d=1/self.framerate;

        hs = np.fft.rfft(self.ys)
        fs = np.fft.rfftfreq(n, d)



        return Spectrum(hs,fs,self.framerate)

class Spectrum:

    def __init__(self,hs,fs,framerate):

        # hs : array of amplitudes (real or complex)
        # fs : array of frequencies

        self.hs=np.asanyarray(hs)
        self.fs=np.asanyarray(fs)
        self.framerate=framerate

    @property
    def amps(self):
        return np.absolute(self.hs)

    def plot(self, high=None):

       plt.plot(self.fs, self.amps)

data=read_wave('hate.wav') <br>
spectrum=data.make_spectrum()<br>
spectrum.plot()<br>

但是我对应该如何添加/删除关注者感到困惑。我创建了一个视图:

# users/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models

class CustomUser(AbstractUser):
    # add additional fields in here
    credit = models.IntegerField(default=200)
    follow = models.ManyToManyField('self', related_name='follow')
    def __str__(self):
        return self.username

问题:

假设@login_required def follow(request, user_id): user = get_object_or_404(CustomUser, pk=user_id) if CustomUser.objects.filter(follow=user.pk).exists(): request.user.follow.remove(user) else: request.user.follow.add(user) return redirect('profil', user_id) 为1,而request.user.pk为2。

对于user_id部分(在add中),我希望数据库中包含elsefrom_customuser_id=1的新行,但是它将创建两行:

  • 一个to_customuser_id=2from_customuser_id=1符合预期的

  • 一个我不需要的from_customuser_id=2from_customuser_id=2

对于from_customuser_id=1部分(在remove中),我希望它仅删除行

  • iffrom_customuser_id=1

但是它删除了两行。

我阅读了doc about django models relations,但没有找到解决此问题的方法。

问题:

如何更新我的代码,以使from_customuser_id=2方法仅用addfrom_customuser_id=1from_customuser_id=2方法插入一行以删除该行(假设当前用户的ID为1)。


不确定是否相关,但出于完整性考虑,这是我urls.py的相关部分:

remove

这就是我在模板中称呼它们的方式:

path('follow/<int:user_id>', views.follow, name='follow'),
path('unfollow/<int:user_id>', views.follow, name='unfollow'),

1 个答案:

答案 0 :(得分:1)

当您具有ManyToManyField时,它实际上会在两个对象之间创建一个关系。这也使您可以进行反向查找。

例如:

class Person(models.Model):
    name = model.CharField(max_length=100)

class Pet(models.Model):
    owners = models.ManyToMany(Person, related_name="pets")
    name = model.CharField(max_length=100)

bob = Person.objects.create(name="Bob")
john = Person.objects.create(name="John")
kitty_kat = Pet.objects.create(name="Kitty Kat")
kitty_kat.owners.set([bob, john])

根据这些模型,一只宠物可以由多个人拥有,而一个人可以拥有多个宠物。所以如果我这样做

bob.pets.all()          # I get kitty kat
kitty_kay.owners.all()  # I get bob & john

当该关系应该在同一模型上时,最终将创建两个关系。一为正常,一为相反。

例如:

class Person(models.Model):
    name = model.CharField(max_length=100)
    followers = models.ManyToManyField('self', related_name='follow') 

bob = Person.objects.create(name="Bob")
john = Person.objects.create(name="John")
john.followers.add(bob)

bob.follow.all()       # I get john... notice I use follow and not followers
john.followers.all()   # I get bob

为避免这种情况,您可以将symmetrical=False传递到该字段,然后将创建一行一行

followers = models.ManyToManyField('self', related_name='+', symmetrical=False)

related_name设置为以+开头的任何内容也将防止反向查找(在这种情况下您不需要)