Django多对多关系更新字段

2024-10-06 12:31:45 发布

您现在位置:Python中文网/ 问答频道 /正文

我有两个模型多对多关系,我试图通过从两个模型中减去两个值来更新一个字段,并将更改保存到数据库中。在

class LeaveBalance(models.Model):
    user=models.OneToOneField(User,on_delete=models.CASCADE,primary_key=True,)
    Leave_current_balance= models.FloatField(null=True, blank=True, default=None)
    Year=models.CharField(max_length=100,default='')
    def __unicode__(self):
             return  self.Year

这是我的表格,请假后会通过电子邮件通知主管。主管可使用表格登录系统批准休假。一旦假期被批准,我想调整假期当前的余额。在

class DirectorForm(forms.ModelForm): class Meta: model=NewLeave fields=('Director_Authorization_Status','Authorized_by_Director','Date_Authorized',) widgets={ 'Date_Authorized':DateInput() }

这是一个允许主管批准休假的函数,它会抛出错误:u'leave_current_balance'

def unitDirectorForm(request,id): if request.method=='POST': getstaffid=NewLeave.objects.get(id=id) form = DirectorForm(request.POST, instance=getstaffid) if form.is_valid(): getstaffid = form.save(commit=False) getstaffid.save() total_days = getstaffid.Total_working_days current_balance = getstaffid.user.leave_balance.Leave_current_balance diff_balance = current_balance - total_days current_balance = diff_balance current_balance=form.fields['Leave_current_balance'] current_balance.save() getstaffid.leave_balance.add(current_balance) return HttpResponse('You have successfuly Authorise the leave') else: #getstaffid=NewLeave.objects.get(id=id) form=DirectorForm() #c_balance=Leave_Balance.objects.get() balance_form = leavebbalanceForm() return render(request,'managerauthorisedform.html',{'form':form})


Tags: formidtruereturnmodelsrequestcurrent主管
2条回答

你得打电话给refresh_from_db算了。像balance.refresh_from_db()从数据库中获取更新的值。在

你也可以用另一种方法来做这个。例如:

def on_balance(user_id):
    id = user_id
    c_balance = LeaveBalance.objects.get(user=id)
    current_balance = c_balance.Leave_current_balance
    t_days = NewLeave.objects.get(user=id)
    total_days = t_days.Total_working_days
    current_balance = current_balance - total_days
    balance = LeaveBalance.objects.get(user=id)
    balance.leave_balance = current_balance
    balance.save()

而上述情况不会导致组合表达式错误。在

或者简单一点:

^{pr2}$

更新-重组模型和视图

因此,如果在适当的模型/窗体/视图结构中使用上述代码,那么它就可以工作了,但是我建议您从模型开始重新构建整个代码。我给你举一个简单的工作例子(我测试了这个并成功了):

我的应用程序名在这个例子中:Myusers1,因此,如果需要,您可以将该名称更改为您的应用程序名称。在

所以模型:

from django.db import models
from django.conf import settings
from django.utils.text import slugify
from django.db.models import F
from django.urls import reverse

class Director(models.Model):
    name = models.CharField(max_length = 100, default = '', null = True, verbose_name = 'Name of Director')

    def __str__(self):
        return self.name

class Staff(models.Model):

    TYPE_CHOICES = (
    ('REGULAR', 'Regular'),
    ('MANAGER', 'Manager'),
    ('FRESH', 'Fresh'),
    )

    name = models.CharField(max_length = 100, default = '', null = True, unique=True, verbose_name = 'Name of staff member')
    birthdate = models.DateField(blank = True, verbose_name = 'Birth date')
    department = models.CharField(max_length = 100, default = '', null = True, verbose_name = 'Department')
    # department could also be a choice field from another table
    type = models.CharField(max_length = 20, choices = TYPE_CHOICES, verbose_name = 'Position Type', null = True)

    def __str__(self):
        return self.name

class LeaveBalance(models.Model):

    staff = models.ForeignKey(Staff, to_field='name', on_delete = models.CASCADE, primary_key = False)
    Leave_current_balance = models.FloatField(null = True, blank = True, default = '')
    date_updated = models.DateTimeField(auto_now_add = True, verbose_name = 'Last Updated date and time')

    def __unicode__(self):
             return  self.Leave_current_balance

class NewLeave(models.Model):

    all_staff = Staff.objects.values()
    STAFF_CHOICES = [(d['name'], d['name']) for d in all_staff]

    staff = models.CharField(max_length = 100, choices = STAFF_CHOICES)
    leave_days_to_approve_now = models.FloatField(null = True,  blank = False, default = 5.0, verbose_name = 'Leave days for approval now')

    LEAVE_CHOICES=(
    ('annual','annual'),
    ('sick','sick'),
    )

    Leave_type = models.CharField(max_length = 100, choices = LEAVE_CHOICES, blank = False, default = '', verbose_name = 'Type of leave')
    Total_working_days = models.FloatField(null = True,  blank = False, default = 200.0)

    APPROVAL_STATUS_CHOICES=(
        ('Pending','Pending'),
        ('Approved','Approved'),
        ('Rejected','Rejected'),
    )

    Director_Authorization_Status = models.CharField(max_length = 100, choices = APPROVAL_STATUS_CHOICES, default = 'Pending', blank = False)
    Date_Authorized = models.DateTimeField(auto_now_add = True, verbose_name = 'date and time of Authorization')

    all_directors = Director.objects.values()
    DIRECTOR_CHOICES = [(d['name'], d['name']) for d in all_directors]
    Authorized_by_Director = models.CharField(max_length = 100, choices = DIRECTOR_CHOICES, default = '', blank = False)

    def __unicode__(self):
        return  self.Leave_type

    def get_absolute_url(self):
        pass
        # return reverse('newleave-detail', kwargs={'pk': self.pk}) # this should be worked out too

    def save(self, *args, **kwargs):
        staff_name = self.staff
        this_staff = Staff.objects.get(name=staff_name)
        name = this_staff.name
        minus_value = self.leave_days_to_approve_now
        if (self.Director_Authorization_Status == 'Approved'):
            LeaveBalance.objects.filter(staff = name).update(Leave_current_balance=F('Leave_current_balance') - minus_value)
            return super(NewLeave, self).save(*args, **kwargs)
        else:
            return super(NewLeave, self).save(*args, **kwargs)

在上面,您可以看到我创建了一个DirectorStaff模型,在这个模型中,您可以在管理后端设置任意数量的职员和控制器。我创建了staff模型,因为可能不是所有的员工都是用户,所以我认为将他们与用户分开放在DB中会更好一些。在

重要信息:首先创建Director和Staff模型,然后立即迁移,因为其他两个表将依赖于它们。然后可以创建其他两个模型。在

我也不认为在LeaveBalance模型中,你应该保留比我放在那里的更多的东西。例如,我认为年份字段是多余的,因为您总是可以根据数据库中想要的日期和日期范围进行筛选。在

然后是视图(我只直接从模型中使用简单视图)。使用这些视图类,您不必创建表单,因为它是从模型自动创建的,您可以使用不同的函数/方法在视图和模型类中处理它们。在

from django.shortcuts import render, redirect
from django.http import HttpResponseRedirect, HttpResponse, HttpRequest
from django.urls import reverse
from django.views import View
from django.views.generic.detail import DetailView
from django.views.generic import ListView, TemplateView
from django.template import loader
from .models import NewLeave
from django.views.generic.edit import FormView, CreateView, DeleteView, UpdateView
from django.urls import reverse_lazy

class NewLeaveCreate(CreateView):
    model = NewLeave
    fields = '__all__'

    def form_valid(self, form):
        super().form_valid(form)
        auth_status = form.cleaned_data['Director_Authorization_Status']
        if (auth_status == 'Approved'):
            return redirect('Myusers1:success_page')
        elif (auth_status == 'Pending'):
            return redirect('Myusers1:pending_success')
        else:
            return redirect('Myusers1:rejected_success')

class NewLeaveUpdate(UpdateView):
    model = NewLeave
    fields = '__all__'

class NewLeaveDelete(DeleteView):
    model = NewLeave
    success_url = reverse_lazy('newleave-list')

class NewLeaveDetail(DetailView):
    model = NewLeave
    template_name = 'myusers1/newleave_detail.html'
    context_object_name = 'newleave'
    queryset = NewLeave.objects.all()

    def get_context_data(self, **kwargs):
            context = super(NewLeaveDetail, self).get_context_data(**kwargs)
            context['leave_details'] = NewLeave.objects.filter(pk=pk)
            return context

class Success(TemplateView):
    template_name = "authorizationsuccess.html"

class pending_success(TemplateView):
    template_name = "pendingsuccess.html"

class rejected_success(TemplateView):
    template_name = "rejectedsuccess.html"

然后进来网址.py我定义了所需的URL:

from django.urls import path, re_path
from . import views
from . import models

app_name = 'Myusers1'

urlpatterns = [
path('newleave/add/', views.NewLeaveCreate.as_view(), name='newleave-add'),
path('newleave/<int:pk>/', views.NewLeaveUpdate.as_view(), name='newleave-update'),
path('newleave/<int:pk>/delete/', views.NewLeaveDelete.as_view(), name='newleave-delete'),
# path('newleave/add/<int:pk>/', views.NewLeaveDetail.as_view(), name='newleave-detail'),
path('newleave/add/success/', views.Success.as_view(), name='success_page'),
path('newleave/add/pendingleaves/', views.pending_success.as_view(), name='pending_success'),
path('newleave/add/rejectedleaves/', views.rejected_success.as_view(), name='rejected_success'),
]

我还没有计算出所有的url路径。在

模板就像newleave_form.html

{% extends 'myusers1/base.html' %}

{% block content %}

<div class"container">
  <div class="col col-lg-2">
    <h2>New Leave Form</h2>
    <form method="post">
      {% csrf_token %}
      {{ form }} 
      <button type="submit">Authorize</button>
    </form>
  </div>
</div>

{% endblock %}

并且当他们提交一个新的休假表单时,至少应该有3个不同的重定向模板,authorized, pending, and rejected模板。我只给出一个简单的授权成功模板:

{% extends 'myusers1/base.html' %}

{% block content %}
  <h2>Thank you! The authorization of leave was successful</h2>

  <div class="col-xs-12 .col-md-8"><li><a href="{% url 'Myusers1:index' %}"> Back to Home </a> </li></div>
{% endblock %}

不要忘记迁移,然后在管理员py。然后,您应该在数据库中创建一些人员和几个控制器来尝试上述操作。我希望上面的内容能给你一些方向来完成你的项目。我只想给你们举一个非常简单的例子。(您必须创建所有其他必要的模板和视图)。在

如果你创建了一个新的应用程序来尝试上述的,那么在你的项目主网址.py文件,你应该引用(包括)你的应用程序的网址这样添加一个额外的一行到你的项目'网址.py文件。然后你的所有新的应用程序URL必须在你的应用程序的网址.py文件:

这就是你的主要项目网址.py看起来是这样的:

urlpatterns = [
    path('admin/', admin.site.urls),
    path('myusers1/', include('Myusers1.urls')),
    # so in your case:
    path('myapp/', include('myapp.urls')),
]

(您必须将Myusers1更改为您的应用程序名,)

当然,我们可以用Django的模型管理器做很多其他事情:https://docs.djangoproject.com/en/2.1/topics/db/managers/

相关问题 更多 >