Python 遵循教程后的m2m django实现

Python 遵循教程后的m2m django实现,python,django,python-3.x,m2m,Python,Django,Python 3.x,M2m,场景:我有一些盒子(容器)我有一些对象(样本)一个样本可以拆分为多个盒子,一个盒子可以包含多个样本 我希望能够将一个样本分配给一个盒子,并从盒子中移除一个样本 我遵循这些原则,将朋友分配给用户,并使其正常工作 def detailcontainer(request, container_id): container = get_object_or_404(Container, pk=container_id) samples = container.samples.all()

场景:我有一些盒子(容器)我有一些对象(样本)一个样本可以拆分为多个盒子,一个盒子可以包含多个样本

我希望能够将一个样本分配给一个盒子,并从盒子中移除一个样本

我遵循这些原则,将朋友分配给用户,并使其正常工作

def detailcontainer(request, container_id):
    container = get_object_or_404(Container, pk=container_id)
    samples = container.samples.all()
    # allsamples = container.samples.exclude(sample_id=samples)
    allsamples = container.samples.all()

    users = User.objects.exclude(id=request.user.id).order_by('-id')
    friend = Friend.objects.get(current_user=request.user)
    friends = friend.users.all().order_by('-id')

    container_contents = container.samples.all()
    # container_contents = Container.objects.get(current_container=samples)

    return render(request, 'container/detailcontainer.html',
    {'container':container,
    'samples':samples,
    'allsamples': allsamples,

    'users': users,
    'friends': friends,

    'container_contents': container_contents,

    })
所以我现在尝试修改代码,所以我需要将用户更改为盒子/容器,将朋友更改为示例。听起来很简单。但我对Django的怪癖和
request.user
所在的位置缺乏经验,我似乎无法获得正确的语法。下面是代码,首先是教程中的代码,然后是我重构它的尝试

我有两个其他表格/模型容器和样本,其中ContainerContent模型适用于两者之间

# models.py (tutorial)
class Friend(models.Model):
    users = models.ManyToManyField(User)
    current_user = models.ForeignKey(User, related_name='owner', null=True, on_delete = models.PROTECT)
    # container_id = models.ForeignKey(Container, null=True, on_delete = models.PROTECT)

    @classmethod
    def make_friend(cls, current_user, new_friend):
        friend, created = cls.objects.get_or_create(
            current_user=current_user
        )
        friend.users.add(new_friend)

    @classmethod
    def lose_friend(cls, current_user, new_friend):
        friend, created = cls.objects.get_or_create(
            current_user=current_user
        )
        friend.users.remove(new_friend)


# views.py
def change_friends(request, operation, pk):
    friend = User.objects.get(pk=pk)
    if operation == 'add':
        Friend.make_friend(request.user, friend)
    elif operation == 'remove':
        Friend.lose_friend(request.user, friend)

    return redirect('depot:allcontainer')


#urls.py
url(r'^container/(?P<operation>.*)/(?P<pk>\d+)/$', views.change_friends, name='change_friends'),


#html
...
        <tbody>
          {% for user in users %}
          <tr>
            {% if user not in friends %}
            <!-- we will want to add an if stmt list if not in unassigned - need to think how to do this -->
            <td>{{ container.container_id }}</td>
            <td>{{ user.username }}</td>
            <td>  <a href="{% url 'depot:change_friends' operation='add' pk=user.pk %}"  class="badge badge-primary" role="button">
              <!-- container=container.container_id -->
              <!-- container=container.container_id -->
              <!-- <button type="button" class="btn btn-success">add</button> -->
              >>
            </a></td>
            {% endif %}
          </tr>
          {% endfor %}
        </tbody>
...

...
      <tbody>
      <tr>
          {% for friend in friends %}
          <td><a href="{% url 'depot:change_friends'  operation='remove' pk=friend.pk %}" class="badge badge-primary" role="button">
            <<
          </a></td>
          <td>{{ friend.username }}</td>
        </tr>
        {% endfor %}
      </tbody>
...

它应该会导致问题,因为
请求
没有任何名为container的属性。在您的教程示例中,它使用
request.user
获得了登录用户,因为django(通过中间件)将登录用户实例分配给
请求

由于在
change\u container
view方法中已经有
sample
container
对象,您可以这样尝试:

if operation == 'add':
    ContainerContents.add_to_container(container, sample)
elif operation == 'remove':
    ContainerContents.remove_from_container(container, sample)
更新 遗漏了一件事,您还需要在
将\u添加到\u容器中
从\u容器中删除\u
方法中进行更改:

    @classmethod
    def add_to_container(cls, current_container, new_sample):
        container, created = cls.objects.get_or_create(
            current_container=current_container
        )
        container.sample.add(new_sample)

    @classmethod
    def remove_from_container(cls, current_container, new_sample):
        container, created = cls.objects.get_or_create(
            current_container=current_container
        )
        container.sample.remove(new_sample)
因为sample是一个在
CurrentContainer
sample
模型之间建立连接的多字段

更新2
您没有在获取的对象中引用m2m字段。您需要按如下方式处理
示例
字段:

models.py:

@classmethod
def将_添加到_容器(cls、当前_容器、新_示例):
ContainerContent,created=cls.objects.get\u或\u create(
当前容器=当前容器
)
ContainerContent.sample.add(新样本)
@类方法
def从_容器中移除_(cls、当前_容器、新_样本):
ContainerContent,created=cls.objects.get\u或\u create(
当前容器=当前容器
)
容器内容。样本。移除(新样本)
并为模型方法设置适当的变量:

views.py

def change_容器(请求、操作、主键、fk=''、样本id=''):
container=container.objects.get(pk=pk)
sample=sample.objects.get(pk=fk)
#sample=Container.objects.get(Container.sample\u id=sample\u id)
如果操作==“添加”:
容器内容。将容器添加到容器(容器,样本)
elif操作==“删除”:
容器内容。从容器(容器、样品)中移除容器
返回重定向('depot:allcontainer')

您是否尝试了
容器内容。添加到容器(容器,示例)
?我添加了一个更新以包含控制页面的视图。我只是在本地测试了它,它工作正常。你还有问题吗?它会产生什么错误?没有错误,但该项没有从列表中删除。这会产生错误:
“ContainerContents”对象没有属性“remove”
我测试了外壳中的示例和容器,它们都分配了对象。@GaryNobles请参阅我的回答的更新部分OK,因此,重定向正在工作,但数据没有更改,我在这里添加了更新代码:您需要在“从容器中删除”方法(与添加方法相同)的顶部添加
@classmethod
。请更改
。从容器中删除(示例,容器)
。从容器中删除(容器,示例)
我检查并清理了代码,出现了一些表命名问题。我查看了数据库,在表中,当我单击添加样本时容器被成功添加,但我得到错误
ContainerSamples没有样本。
在跟踪中显示
sample\u id'
以下是当前代码:(如果找到解决方案,我将更新问题)
if operation == 'add':
    ContainerContents.add_to_container(container, sample)
elif operation == 'remove':
    ContainerContents.remove_from_container(container, sample)
    @classmethod
    def add_to_container(cls, current_container, new_sample):
        container, created = cls.objects.get_or_create(
            current_container=current_container
        )
        container.sample.add(new_sample)

    @classmethod
    def remove_from_container(cls, current_container, new_sample):
        container, created = cls.objects.get_or_create(
            current_container=current_container
        )
        container.sample.remove(new_sample)
@classmethod
def remove_from_container(cls, current_container, new_sample):
     from app_name.models import ContainerSample

     c_sample = ContainerSample.objects.get(container=current_container, sample=new_sample)
     c_sample.delete()