django - 如何在 Django 2.0+ 中简单有效地创建相关对象?
问题描述
我想找到一种简单而可靠的方法来创建子对象。我认为这是一个简单的问题,可能使用 Django 关系管理器或相关对象引用来解决。
我过去已经让它工作了(通过支付某人的费用来帮助我解决这个问题),但我觉得有一种更简单的方法可以让我逃脱。
这对我的views.py有效
class MainVisitForm(SingleObjectMixin, FormView):
template_name = "clincher/visit_form.html"
form_class = VisitForm
model = Main
def post(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return HttpResponseForbidden()
self.object = self.get_object()
form=self.get_form()
form.fk_visit_user = self.request.user
form.fk_visit_main = Main.objects.get(id=self.kwargs['pk'])
#added this to save form as we are mixxing the two forms and Models
# as the approch of singleObjectMixin is we should get object from DB as per request url as a primary key
#and we have defined model as a Main but taking the form view of VistForm as the probem occures
# as i think
if form.is_valid():
instance = Main()
instance.firstname = form.cleaned_data['firstname']
instance.middelname = form.cleaned_data['middlename']
instance.lastname = form.cleaned_data['lastname']
instance.date_of_birth = form.cleaned_data['date_of_birth']
instance.sex = form.cleaned_data['sex']
instance.address = form.cleaned_data['address']
instance.save()
return super().post(request, *args, **kwargs)
def get_success_url(self):
return reverse('clincher:main_detail', kwargs={'pk': self.object.pk})
基本上,当用户在“主”对象的详细信息页面中时,我希望他们能够创建一个子对象(访问对象)。最终 1 名患者将进行多次就诊(1:m 关系)。每次患者访问该文档时,将添加 1 次与该人相关的新访问。稍后,我将显示该患者的就诊列表(但不是此问题的主题)。
模型.py
class Main(models.Model):
firstname = models.CharField(max_length = 256, verbose_name=('First Name'))
middlename = models.CharField(max_length=256, verbose_name=('Middle Name'))
lastname = models.CharField(max_length=256, verbose_name=('Last Name'))
date_of_birth = models.DateField()
age = models.CharField(max_length=4)
sex_list = (
(str(1), 'Female'),
(str(2), 'Male'),
(str(3), 'Other'),
(str(4), 'Unknown'),)
sex = models.CharField(max_length = 24, choices=sex_list, verbose_name='Sex')
address = models.TextField(max_length = 256)
@property
def full_name(self):
#"Returns the person's full name."
return '%s %s' % (self.firstname, self.lastname)
#Redirects after form is submitted using primary key
def get_absolute_url(self):
return reverse('clincher:main_detail', kwargs={'pk': self.pk})
def __str__(self):
return self.firstname + ' ' + self.lastname +' - ' + str(self.date_of_birth)
class Visit(models.Model):
fk_visit_main = models.ForeignKey(Main, on_delete=models.CASCADE, verbose_name=('Patient Name'))
visit_date = models.DateField(auto_now = True, editable=True)
fk_visit_user = models.ForeignKey(User, on_delete=models.PROTECT, verbose_name=('Practitioner'), max_length=500)
visit_label = models.CharField(max_length=256, blank=True, null=True)
visit_type = models.CharField(
max_length=256,
default=1, verbose_name='Type of Visit')
visit_progress_notes = models.TextField(max_length=10000,
blank=True, verbose_name='Progress Notes')
outcomes = models.BooleanField(default=False)
def __str__(self):
return '%s %s' % (self.visit_date, self.visit_label)
def get_absolute_url(self):
return reverse('clincher:main_detail', kwargs={'pk': self.pk})
表格.py
class VisitForm(forms.Form):
visit_types_list = (
(str(1), 'Consultation'),
(str(2), 'Procedure'),
(str(3), 'Administrative'),)
visit_type = forms.ChoiceField(choices=visit_types_list)
visit_label = forms.CharField(label='Visit Label', max_length=100)
progress_note = forms.CharField(widget=forms.Textarea)
def form_valid(self, form):
form.instance.fk_visit_user = self.request.user
form.instance.fk_visit_main = Main.objects.get(id=self.kwargs['pk'])
return super().form_valid(form)
因此,我应该最终得到一个具有父对象主键的子记录/对象。
上面的代码有效,但我确信有一种简单的 Django-ey 方式可以更简单、更健壮地做事。我认为我的解决方案应该在 Django 关系管理器中找到,但我找不到有效的解决方案。我在 Fiver 上付钱给一个人,我认为他没有尽可能简单地做到这一点。
解决方案
检查 django InlineFormset:https ://docs.djangoproject.com/en/2.2/topics/forms/modelforms/#inline-formsets
如果您希望能够添加删除表单集动态结帐(基于 Jquery): https ://github.com/elo80ka/django-dynamic-formset
如果您使用基于类的视图,则必须在其中添加 inlineformsetget_context_data()
并form_valid()
检查是否存在formset.is_valid()
,然后将其保存到数据库中。
编辑:这是基于您的评论的代码
表格.py
class VisitForm(forms.ModelForm);
class Meta:
model = Visit
fields = [
'visit_type',
'visit_label',
'visit_progress_notes'
]
视图.py
class CreateVisitView(CreateView):
model = Visit
form_class = VisitForm
template_name = "clincher/visit_form.html"
#one of the first function called in class based view, best place to manage conditional access
def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return HttpResponseForbidden()
return super(CreateVisitView,self).dispatch(request, *args, **kwargs)
def form_valid(self, form):
visit = form.save(commit=False)
visit.fk_visit_user = self.request.username
visit.fk_visit_main = get_object_or_404(Main, pk=self.kwargs.get('pk'))
visit.save()
return super(CreateVisitView,self).form_valid(form)
模型.py
class Main(models.Model):
SEX_LIST_CHOICE = (
(str(1), 'Female'),
(str(2), 'Male'),
(str(3), 'Other'),
(str(4), 'Unknown'),
)
firstname = models.CharField(max_length = 256, verbose_name=('First Name'))
middlename = models.CharField(max_length=256, verbose_name=('Middle Name'))
lastname = models.CharField(max_length=256, verbose_name=('Last Name'))
date_of_birth = models.DateField()
age = models.PositiveSmallIntegerField()
sex = models.CharField(max_length = 24, choices=SEX_LIST_CHOICE, verbose_name='Sex')
address = models.TextField(max_length = 256)
@property
def full_name(self):
#"Returns the person's full name."
return '%s %s' % (self.firstname, self.lastname)
#Redirects after form is submitted using primary key
def get_absolute_url(self):
return reverse('clincher:main_detail', kwargs={'pk': self.pk})
def __str__(self):
return self.firstname + ' ' + self.lastname +' - ' + str(self.date_of_birth)
class Visit(models.Model):
VISIT_TYPE_CHOICE = (
(str(1), 'Consultation'),
(str(2), 'Procedure'),
(str(3), 'Administrative'),)
fk_visit_main = models.ForeignKey(Main, on_delete=models.CASCADE, verbose_name=('Patient Name'))
visit_date = models.DateField(auto_now = True, editable=True)
fk_visit_user = models.ForeignKey(User, on_delete=models.PROTECT, verbose_name=('Practitioner'), max_length=500)
visit_label = models.CharField(max_length=256, blank=True, null=True)
#you are storing the type of visit as an
visit_type = models.CharField(
max_length=256,
default=1,
verbose_name='Type of Visit',
choices=VISIT_TYPE_CHOICE
)
visit_progress_notes = models.TextField(max_length=10000,
blank=True, verbose_name='Progress Notes')
outcomes = models.BooleanField(default=False)
def __str__(self):
return '%s %s' % (self.visit_date, self.visit_label)
def get_absolute_url(self):
return reverse('clincher:main_detail', kwargs={'pk': self.pk})
推荐阅读
- activemq-artemis - 如何从服务器获取队列列表?
- javascript - 在具有多个功能的模块的文件之间共享变量。
- mysql - 在scala中编写脚本以连接两个mysql表并创建一个对象(quill)
- sql - 插入语法错误从excel导入数据
- android - android:descendantFocusability="afterDescendants" 更改布局(似乎滚动)
- eclipse - 如果 module-info.java 存在,Eclipse 2018-09 找不到测试类
- javascript - 实时服务器上的间歇性 AJAX 错误
- react-native - React Native 如何拥有沉浸式模态
- javascript - 不使用 jQuery 发送不和谐 webhook
- amazon-web-services - Elasticsearch:集群上的 503 错误 - 未发现主服务器