Django 通过用户名从基于 class 的通用视图中过滤通用表单 Select 属性,或者预填充并隐藏表单 Select-属性

Django filter generic form Select attribute from generic class-based view by Username or prepopulate and hide the form Select-attribute

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

这些是我的 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

views.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'

urls.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 上下文,但客户应该只能在列表中看到或 select 他们的上下文。

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

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

我怎样才能以最简单的方式完成这两项工作?

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

如本指南中所述: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 模式,并将新的 Link 添加到 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 不是真的。

见下图:

我能够在 ModelForm 中按用户名过滤选项,但从那以后我无法再将表单保存到数据库中。 这是新堆栈 Post,分辨率为 Post,新堆栈 Question/Problem。