Django и пользователи, вводящие данные

#django #django-models

#django #django-модели

Вопрос:

Я создаю веб-приложение, которое будет использоваться компанией для выполнения своих повседневных операций. Такие вещи, как отправка счетов, отслеживание дебиторской задолженности, отслеживание запасов (и, следовательно, продуктов). У меня есть несколько моделей, настроенных в моих различных приложениях для обработки различных частей веб-приложения. Я также буду настраивать разрешения, чтобы менеджеры могли редактировать больше полей, чем, скажем, офисный помощник.

Это подводит меня к моему вопросу. Как я могу показать все поля модели и иметь некоторые, которые можно редактировать, а некоторые — нельзя, и при этом сохранить экземпляр модели?

Например, у меня есть системная модель для систем отслеживания (мы устанавливаем ирригационные системы). Системный идентификатор является первичным ключом, и пользователю важно его видеть. Однако они не могут изменить этот идентификатор, поскольку это все испортило бы. Теперь у меня есть представление для отображения моих моделей через форму, использующую «form.as_table». Это эффективно, но просто выдает все поля модели с полями ввода, заполняющими значения, сохраненные для этого экземпляра модели. Это включает в себя поле SystemID, которое не должно быть доступно для редактирования.

Поскольку я не хочу, чтобы пользователь редактировал поле SystemID, я попытался сделать его просто меткой в html-форме, но django жалуется. Вот некоторый код:

моя модель (не вся, но часть):

 class System(models.Model):

systemID = models.CharField(max_length=10, primary_key=True, verbose_name = 'System ID')
systemOwner = models.ForeignKey (System_Owner)
installDate = models.DateField()
projectManager = models.ForeignKey(Employee, blank=True, null=True)

#more fields....
  

Затем мой взгляд на конкретный экземпляр модели:

 def system_details(request, systemID):
if request.method == 'POST':
    sysEdit = System.objects.get(pk=systemID)
    form = System_Form(request.POST, instance=sysEdit)
    if form.is_valid():
        form.save()
        return HttpResponseRedirect('/systems/')
else:
    sysView = System.objects.get(pk=systemID)
    form = System_Form(instance=sysView)

return render_to_response('pages/systems/system_details.html', {'form': form}, context_instance=RequestContext(request))
  

Теперь html-страница, которая отображает форму:

 <form action="" method="POST">
{% csrf_token %}
<table>
  {{ form.as_table }}
</table>
<input type="submit" value="Save Changes">
<input type="button" value="Cancel Changes" onclick="window.location.href='/systems/'">
</form>
  

Итак, я подумываю о том, чтобы создать две функции для html. Одна из форм предназначена для отображения только тех полей, которые пользователь может редактировать, а другая предназначена только для отображения содержимого поля (SystemID). Затем, в представлении, когда я хочу сохранить изменения, внесенные пользователем, я бы сделал:

 sysValues = System.objects.get(pk=SystemID)
form.save(commit = false)
form.pk = sysValues.sysValues.pk (or whatever the code is to assign the sysValues.pk to form.pk)
  

Есть ли более простой способ сделать это или это было бы лучшим?

Спасибо

Комментарии:

1. класс SystemForm на самом деле является важной частью всего этого. кстати, python.org/dev/peps/pep-0008

2. в дополнение к опубликованным идеям, доступным только для чтения, вы можете получить доступ к экземпляру в форме {{ form.instance.pk }} и т.д.

3. @skyl — спасибо за совет, я уже использовал метод form.instance ранее.

Ответ №1:

Единственное, что вы можете сделать, это исключить поле, которое вам не нужно в вашей форме:

 class System_Form(forms.ModelForm):
    class Meta:
        exclude = ('systemID',)
  

Другой способ заключается в использовании полей, доступных только для чтения: http://docs.djangoproject.com/en/1.3/ref/contrib/admin/#django.contrib.admin .ModelAdmin.readonly_fields как предложил @DTing

Комментарии:

1. Я думаю, что этот метод мне нравится больше всего. Это кажется самым чистым. Спасибо!!

Ответ №2:

Чтобы сделать поле доступным только для чтения, вы можете установить для атрибута widget readonly значение True.

используя ваш пример:

 class System_Form(ModelForm):
    def __init__(self, *args, **kwargs):
        super(System_Form, self).__init__(*args, **kwargs)
        self.fields['systemID'].widget.attrs['readonly'] = True

    class Meta:
        model = System
  

или исключите поля, использующие exclude или fields , из класса Meta вашей формы и при желании отобразите его в своем шаблоне следующим образом:

forms.py

 class System_Form(ModelForms):
    class Meta:
        model = System
        exclude = ('systemID',)
  

views.py

 def some_view(request, system_id):
    system = System.objects.get(pk=system_id)

    if request.method == 'POST':
        form = System_Form(request.POST, instance=system)
        if form.is_valid():
            form.save()
            return HttpResponse('Success')
    else:
        form = System_Form(instance=system)
    context = { 'system':system,
                'form':form, }
    return render_to_response('some_template.html', context,
        context_instance=RequestContext(request))
  

some_template.html

 <p>make changes for {{ system }} with ID {{ system.systemID }}</p>
<form method='post'>
    {{ form.as_p }}
    <input type='submit' value='Submit'>
</form>