Django处理表格的方式?
我正在组织一个项目,并试图尽可能多地利用开放源码库,以尽量减少完成工作所涉及的“键入”。我正在使用django、crispy表单和引导框架 我已经编写了处理一个实体的代码(添加/编辑/删除)我觉得我一定是做错了什么,因为似乎涉及到太多的代码——有20多个不同的项目将以几乎相同的方式进行管理,因此我想在我开始完成其余代码之前,我应该向社区询问我可以修复的错误 所以我有一个模型:Django处理表格的方式?,django,twitter-bootstrap,django-forms,django-crispy-forms,Django,Twitter Bootstrap,Django Forms,Django Crispy Forms,我正在组织一个项目,并试图尽可能多地利用开放源码库,以尽量减少完成工作所涉及的“键入”。我正在使用django、crispy表单和引导框架 我已经编写了处理一个实体的代码(添加/编辑/删除)我觉得我一定是做错了什么,因为似乎涉及到太多的代码——有20多个不同的项目将以几乎相同的方式进行管理,因此我想在我开始完成其余代码之前,我应该向社区询问我可以修复的错误 所以我有一个模型: class Link(models.Model): name = models.CharField(max_le
class Link(models.Model):
name = models.CharField(max_length=255, blank=False, null=False, verbose_name=_(u'Название'))
url = models.URLField(blank=False, null=False, verbose_name=_(u'Ссылка'))
project = models.ForeignKey('Project')
display_on_main_project_page = models.BooleanField(default=False, verbose_name=_(u'Показывать ссылку на главной странице проекта'))
class Meta:
app_label = 'core'
verbose_name = _(u'Ссылка')
verbose_name_plural = _(u'Ссылки')
def __unicode__(self):
return self.name
还有一张表格,上面按照手册添加了脆块:
class ProjectLinkForm(forms.Form):
id = forms.IntegerField(required=False, widget=forms.HiddenInput())
project = forms.ModelChoiceField(queryset=Project.objects.all(),required=True, widget=forms.HiddenInput())
name = forms.CharField(required=True, label=_(u'Имя ссылки'))
url = forms.URLField(required=True, label=_(u'URL ссылки'))
display_on_main_project_page = forms.BooleanField(label=_(u'Показывать на главной странице проекта'), required=False)
class Meta:
model = Link
fields = ('project','name','url','display_on_main_project_page')
def __init__(self, *args, **kwargs):
self.helper = FormHelper()
self.helper.form_class = 'horizontal-form'
self.helper.form_action = ''
self.helper.form_id = 'link_form'
self.helper.layout = Layout(
Field('name',css_class='input-block-level'),
Field('url', css_class='input-block-level')
)
super(ProjectLinkForm, self).__init__(*args, **kwargs)
和配置为服务于操作的URL:
url(r'^forms/link/add/(?P<project_id>\d+)/$','core.views.forms.link.add'),
url(r'^forms/link/edit/(?P<link_id>\d+)/$','core.views.forms.link.edit'),
url(r'^forms/link/delete/(?P<link_id>\d+)/$','core.views.forms.link.delete'),
有一个模板用于所有操作:
{% load crispy_forms_tags %}
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3>{{ links_form_title|default:"Ссылки на проект" }}</h3>
</div>
<div class="modal-body">
<p>
{% if form.action == "delete" %}
Уверены, что хотите удалить ссылку "{{ form.name.value }}"? Одно неосторожное движенье мышкой и все - не вернешь!
<div class="hide">
{% crispy form %}
</div>
{% else %}
{% crispy form %}
{% endif %}
</p>
</div>
<div class="modal-footer">
{% if form.action == "delete" %}
<a href="#" class="btn btn-danger" id="" onclick='SubmitModalForm($("#link_form"),"{{ form.submit_url }}")'>Удалить</a>
{% else %}
<a href="#" class="btn btn-primary" id="" onclick='SubmitModalForm($("#link_form"),"{{ form.submit_url }}")'>Сохранить</a>
{% endif %}
</div>
它确实可以工作,但是有太多的输入-我想我遗漏了一些东西或者只是没有得到正确的东西-请建议正确的方法。您可以轻松地删除一半的代码 你错过了又错过了 您可以有这样的URL:
from django.views import generic
urlpatterns = patterns('test_app.views',
url(r'link/create/$', generic.CreateView.as_view(model=Link),
name='link_create'),
url(r'link/(?P<pk>\d+)/update/$', generic.UpdateView.as_view(model=Link),
name='link_update'),
url(r'link/(?P<pk>\d+)/delete/$', generic.DeleteView.as_view(model=Link),
name='link_delete'),
# bonus:
url(r'link/$', generic.ListView.as_view(model=Link), name='link_list'),
url(r'link/(?P<pk>\d+)/$', generic.DetailView.as_view(model=Link),
name='link_detail'),
)
扩展Django通用视图的其他一些示例:
class PkUrlKwarg(SingleObjectMixin):
"""
Take the pk from request.GET and sets it to kwargs, useful to avoid
reversing urls from javascript
"""
def get_object(self, queryset=None):
self.kwargs[self.pk_url_kwarg] = self.request.REQUEST['pk']
return super(PkUrlKwarg, self).get_object(queryset)
class WidgetFormMixin(object):
def get_form(self, form_class):
# [snip] ok there's quite a lot (11 SLOCs) going on here in my case, since Widget* views are
# supposed to deal with any subclass of Widget
return self.object.configuration_form_instance(self.request)
def get_template_names(self):
widget_name = self.object.__class__.__name__
return [
'form_designer/widget_forms/%s.html' % widget_name,
'form_designer/widget_form.html',
]
class WidgetSecurity(object):
"""
Return a queryset of Widget that have a tab in a form which author is
request.user. For security.
"""
def get_queryset(self):
return Widget.objects.filter(tab__form__author=self.request.user)
最后,我的CRUD视图有相当多的非默认和或多或少复杂的逻辑,但仍然只有很少的代码行:
class WidgetCreateView(WidgetFormMixin, AjaxFormMixin, generic.CreateView):
form_class = WidgetForm # overridden by WidgetFormMixin.get_form, but make django happy
class WidgetUpdateView(PkUrlKwarg, WidgetSecurity, WidgetFormMixin, AjaxFormMixin, generic.UpdateView):
form_class = WidgetForm # overridden by WidgetFormMixin.get_form
class WidgetDeleteView(PkUrlKwarg, WidgetSecurity, AjaxDeleteView):
pass
这可能不是最好的答案,但它肯定会让你走上正确的轨道,并激励你
还要注意,您还应该在模型中定义
作为记录,URL:
url(r'widget/create/$',
login_required(WidgetCreateView.as_view()),
name='form_designer_widget_create'),
# the following views accept 'pk' as URL/GET argument
# this avoids reversing urls from javascript at the cost of a 4-liner mixin
url(r'widget/update/$',
login_required(WidgetUpdateView.as_view()),
name='form_designer_widget_update'),
url(r'widget/delete/$',
login_required(WidgetDeleteView.as_view()),
name='form_designer_widget_delete'),
class PkUrlKwarg(SingleObjectMixin):
"""
Take the pk from request.GET and sets it to kwargs, useful to avoid
reversing urls from javascript
"""
def get_object(self, queryset=None):
self.kwargs[self.pk_url_kwarg] = self.request.REQUEST['pk']
return super(PkUrlKwarg, self).get_object(queryset)
class WidgetFormMixin(object):
def get_form(self, form_class):
# [snip] ok there's quite a lot (11 SLOCs) going on here in my case, since Widget* views are
# supposed to deal with any subclass of Widget
return self.object.configuration_form_instance(self.request)
def get_template_names(self):
widget_name = self.object.__class__.__name__
return [
'form_designer/widget_forms/%s.html' % widget_name,
'form_designer/widget_form.html',
]
class WidgetSecurity(object):
"""
Return a queryset of Widget that have a tab in a form which author is
request.user. For security.
"""
def get_queryset(self):
return Widget.objects.filter(tab__form__author=self.request.user)
class WidgetCreateView(WidgetFormMixin, AjaxFormMixin, generic.CreateView):
form_class = WidgetForm # overridden by WidgetFormMixin.get_form, but make django happy
class WidgetUpdateView(PkUrlKwarg, WidgetSecurity, WidgetFormMixin, AjaxFormMixin, generic.UpdateView):
form_class = WidgetForm # overridden by WidgetFormMixin.get_form
class WidgetDeleteView(PkUrlKwarg, WidgetSecurity, AjaxDeleteView):
pass
url(r'widget/create/$',
login_required(WidgetCreateView.as_view()),
name='form_designer_widget_create'),
# the following views accept 'pk' as URL/GET argument
# this avoids reversing urls from javascript at the cost of a 4-liner mixin
url(r'widget/update/$',
login_required(WidgetUpdateView.as_view()),
name='form_designer_widget_update'),
url(r'widget/delete/$',
login_required(WidgetDeleteView.as_view()),
name='form_designer_widget_delete'),