首页 > 解决方案 > Django过滤通用表单通过用户名从基于通用类的视图中选择属性或预填充并隐藏表单选择属性

问题描述

我需要为非员工用户限制 Django 表单的选择字段中的选项。

所以这些是我的models.py:

#!/usr/bin/python3
from django.db import models
from django.urls import reverse


class Extension(models.Model):
    username = models.CharField(primary_key=True, max_length=200, help_text='')
    callerid = models.CharField(max_length=200, help_text='')
    extension = models.CharField(max_length=3, help_text='')
    firstname = models.CharField(max_length=200, help_text='')
    lastname = models.CharField(max_length=200, help_text='')
    password = models.CharField(max_length=200, help_text='')
    context = models.ForeignKey('Context', on_delete=models.SET_NULL, null=True)

    def get_absolute_url(self):
        return reverse('extension-detail', args=[str(self.username)])

    def my_get_absolute_url(self):
        return reverse('my-extension-detail', args=[str(self.username)])

    def __str__(self):
        return self.username


class Context(models.Model):
    name = models.CharField(primary_key=True, max_length=200, help_text='')
    countryprefix = models.CharField(max_length=200, help_text='')
    cityprefix = models.CharField(max_length=200, help_text='')
    number = models.CharField(max_length=200, help_text='')
    extensionsfrom = models.CharField(max_length=200, help_text='')
    extensionstill = models.CharField(max_length=200, help_text='')
    portscount = models.CharField(max_length=200, help_text='')

    def get_absolute_url(self):
        return reverse('context-detail', args=[str(self.name)])

    def my_get_absolute_url(self):
        return reverse('my-context-detail', args=[str(self.name)])

    def __str__(self):
        return self.name

视图.py:

#!/usr/bin/python3
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
from django.contrib.auth.models import Permission
from catalog.models import Extension, Context
from django.shortcuts import render
from django.urls import reverse_lazy
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.views.generic.detail import DetailView
from django.views.generic.list import ListView


class ExtensionCreate(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
    model = Extension
    fields = '__all__'
    permission_required = 'catalog.add_extension'


class ExtensionUpdate(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
    model = Extension
    fields = '__all__'
    permission_required = 'catalog.change_extension'


class ExtensionDelete(LoginRequiredMixin, PermissionRequiredMixin, DeleteView):
    model = Extension
    success_url = reverse_lazy('extensions')
    permission_required = 'catalog.delete_extension'

网址.py:

#!/usr/bin/python3
from . import views
from django.urls import path


urlpatterns = [
    path('', views.index, name='index'),
    path('extensions/', views.ExtensionListView.as_view(), name='extensions'),
    path('extension/<str:pk>', views.ExtensionDetailView.as_view(), name='extension-detail'),
    path('extension/create/', views.ExtensionCreate.as_view(), name='extension-create'),
    path('extension/<str:pk>/update/', views.ExtensionUpdate.as_view(), name='extension-update'),
    path('extension/<str:pk>/delete/', views.ExtensionDelete.as_view(), name='extension-delete'),
    path('myextensions/', views.ExtensionsByUserListView.as_view(), name='my-extensions'),
    path('myextension/<str:pk>', views.ExtensionsByUserDetailView.as_view(), name='my-extension-detail'),
    path('contexts/', views.ContextListView.as_view(), name='contexts'),
    path('context/<str:pk>', views.ContextDetailView.as_view(), name='context-detail'),
    path('context/create/', views.ContextCreate.as_view(), name='context-create'),
    path('context/<str:pk>/update/', views.ContextUpdate.as_view(), name='context-update'),
    path('context/<str:pk>/delete/', views.ContextDelete.as_view(), name='context-delete'),
    path('mycontexts/', views.ContextByUserListView.as_view(), name='my-contexts'),
    path('mycontext/<str:pk>', views.ContextByUserDetailView.as_view(), name='my-context-detail'),
]

模板:

{% extends "base_generic.html" %}

{% block content %}
  <form action="" method="post">
    {% csrf_token %}
    <table>
    {{ form.as_table }}
    </table>
    <input type="submit" value="Submit">
  </form>
{% endblock %}

这是它的样子: 在此处输入图像描述

用户名始终与上下文之一相同。
只有员工用户可以创建新上下文和新用户。
然后用户应该添加他们的扩展。

虽然员工应该能够在创建新扩展时选择上下文,但客户应该只能在列表中查看或选择他们的上下文。

因此需要过滤非员工成员的 Select-attribute,以便只有用户的上下文可见,这等于他的用户名。

或者,我想使用用户名(=自己的上下文)预填充和隐藏上下文表单字段

我怎样才能以最简单的方式做到这一点?

到目前为止,这是我自己尝试过的:

就像这个方法中描述的那样:https ://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Forms#Renew-book_form_using_a_Form_and_function_view我在forms.py中定义了一个表单:

#!/usr/bin/python3
from django import forms
class MyExtensionCreateForm(forms.Form):
    # username = forms.CharField(help_text="")
    # callerid = forms.CharField(help_text="")
    # context = forms.CharField(help_text="")

    firstname = forms.CharField(help_text="")
    lastname = forms.CharField(help_text="")
    extension = forms.CharField(help_text="")
    password = forms.CharField(help_text="")

    def clean_data(self):
        data = self.cleaned_data
        # Remember to always return the cleaned data.
        return data

然后我将以下内容添加到views.py:

from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.urls import reverse
from catalog.forms import MyExtensionCreateForm

def MyExtensionCreate(request):
    # extension = get_object_or_404(Extension)
    # If this is a POST request then process the Form data
    if request.method == 'POST':
        # Create a form instance and populate it with data from the request (binding):
        form = MyExtensionCreateForm(request.POST)
        # Check if the form is valid:
        if form.is_valid():
            # process the data in form.cleaned_data as required
            form.firstname = form.cleaned_data['firstname']
            form.lastname = form.cleaned_data['lastname']
            form.extension = form.cleaned_data['extension']
            form.password = form.cleaned_data['password']
            # Prepopulated Fields
            form.context = request.user
            form.callerid = str(form.cleaned_data['firstname'])+" "+str(form.cleaned_data['lastname'])+" "+str(form.cleaned_data['extension'])
            form.username = str(request.user)+"_"+str(form.cleaned_data['extension'])
            form.save()
            # redirect to a new URL:
            return HttpResponseRedirect(reverse('my-extensions'))
    # If this is a GET (or any other method) create the default form.
    else:
        form = MyExtensionCreateForm({'context': request.user})
    context = {
        'form': form,
    }
    return render(request, 'catalog/extension_form-by-user.html', context)

# class MyExtensionCreate(LoginRequiredMixin, CreateView):
#     model = Extension
#     fields = '__all__'
#     form_class = MyExtensionCreateForm


然后我在urls.py中为 URL 模式添加了一个新 URL,并将新链接添加到base_generic.html

path('myextensions/create/', views.MyExtensionCreate, name='my-extension-create'),
<li><a href="{% url 'my-extension-create' %}">Add Extension</a></li>

我可以查看表单,如果我将上下文字段添加到可见表单字段中,我可以看到上下文最初将使用登录的用户名填充(参见下面的第一张图片)。但是只要我提交表单,无论我尝试什么,我都会得到错误,所以基本上GET是有效的,但POST不是真的。

见下图:

在此处输入图像描述 在此处输入图像描述 在此处输入图像描述

标签: pythondjangodjango-modelsdjango-formsdjango-generic-views

解决方案


我能够通过 ModelForm 中的用户名过滤选项,但从那以后我无法再将表单保存到数据库中。这是新的堆栈帖子,其中包含此帖子的解决方案和新的问题/问题。 Django:保存表单不起作用(ModelForm 通过 request.user 过滤 ForeignKey 选择)


推荐阅读