社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Django

M2M Django在遵循教程后的实现

Spatial Digger • 5 年前 • 1535 次点击  

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

我希望能够将一个样本分配给一个框,并从一个框中删除一个样本。

我跟着这些 tutorials 57-59 ,为用户分配朋友,并使其正常工作。

所以我现在尝试修改代码,所以我需要将用户改为盒子/容器,并将朋友改为示例。听起来很简单。但我对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>
...

以下是我的尝试:

# models.py
class ContainerContents(models.Model):
    sample = models.ManyToManyField('Sample')
    current_container = models.ForeignKey(Container, null=True, on_delete = models.PROTECT)

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

        @classmethod
        def remove_from_container(cls, current_container, new_sample):
            sample, created = cls.objects.get_or_create(
                current_container=current_container
            )
            sample.remove(new_sample)

# views.py - this one is causing me issues, the request.____
def change_container(request, operation, pk, fk='', sample_id=''):
    container = Container.objects.get(pk=pk)
    sample = Sample.objects.get(pk=fk)
    # sample = Container.objects.get(container.sample_id=sample_id)
    if operation == 'add':
        ContainerContents.add_to_container(request.container, container)
    elif operation == 'remove':
        ContainerContents.remove_from_container(request.container, container)

    return redirect('depot:allcontainer')

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

我怀疑我需要在这里传递容器ID,否则容器之间就没有任何区别。

# html
    <tbody>
      {% for unassigned in container_contents %}
      <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>{{ unassigned.area_easting }}.
          {{ unassigned.area_northing }}.
          {{ unassigned.context_number }}.
          {{ unassigned.sample_number }}</td>
          <td>{{ unassigned.sample_id }}</td>
          <td></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 contents in container_contents %}
        <td><a href="{% url 'depot:change_container'  operation='remove' pk=container.container_id fk=contents.sample_id  %}" class="badge badge-primary" role="button">
          <!-- <button type="button" class="btn btn-default">remove</button> -->
          <<
        </a></td>
        <td>{{ contents.sample_id }}</td>
        <td>{{ contents.area_easting }}.
          {{ contents.area_northing }}.
          {{ contents.context_number }}.
          {{ contents.sample_number }}</td>
        </tr>
        {% endfor %}
      </tbody>
...       

---更新---

我应该包括生成页面的视图,而不是用户/朋友仍然包含在其中,一旦我使其工作,它就会被删除。

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,

    })
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/39049
 
1535 次点击  
文章 [ 2 ]  |  最新文章 5 年前
Gasanov
Reply   •   1 楼
Gasanov    6 年前

您没有在提取的对象中引用M2M字段。你需要解决 sample 字段如下:

型号.py:

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

@classmethod
def remove_from_container(cls, current_container, new_sample):
    containerContents, created = cls.objects.get_or_create(
        current_container=current_container
    )
    containerContents.sample.remove(new_sample)

并为模型方法设置适当的变量:

视图.py

def change_container(request, operation, pk, fk='', sample_id=''):
    container = Container.objects.get(pk=pk)
    sample = Sample.objects.get(pk=fk)
    # sample = Container.objects.get(container.sample_id=sample_id)
    if operation == 'add':
        ContainerContents.add_to_container(container, sample)
    elif operation == 'remove':
        ContainerContents.remove_from_container(container, sample)

    return redirect('depot:allcontainer')
ruddra
Reply   •   2 楼
ruddra    5 年前

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

你已经有了 sample container 您的 change_container 查看方法,您可以这样尝试:

if operation == 'add':
    ContainerContents.add_to_container(container, sample)
elif operation == 'remove':
    ContainerContents.remove_from_container(container, sample)

更新

错过了一件事,你需要在里面换车 add_to_container remove_from_container 方法也一样:

    @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

@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()