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