Django поле обновления многие ко многим отношениям - PullRequest
0 голосов
/ 09 февраля 2019

У меня есть две модели отношения многие ко многим, я пытаюсь обновить поле, вычитая два значения из двух моделей и сохраняя изменения в БД.

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 NewLeave(models.Model):
	user=models.ForeignKey(User,default='',on_delete=models.CASCADE)
       	leave_balance=models.ManyToManyField(Leave_Balance)
        leave=(
        ('annual','annual'),
        ('sick','sick'),

    	)

  	Leave_type=models.CharField(max_length=100,choices=leave,blank=False,default='')

        Total_working_days=models.FloatField(null=True,  blank=False)
        DirAuth=(
            ('Pending','Pending'),
            ('Approved','Approved'),
            ('Rejected','Rejected'),
        )

    	Director_Authorization_Status=models.CharField(max_length=100,choices=DirAuth,default='Pending',blank=False)
	Date_Authorized=models.DateField(null=True,blank=False)
	Authorized_by_Director=models.CharField(max_length=100,default='',blank=False)

        def __unicode__(self):
            return  self.Leave_type

вот моя форма, когда отправляется отпуск, директор уведомляется по электронной почте.Директор может войти в систему, чтобы подтвердить отпуск, используя форму.как только отпуск будет одобрен, я хочу настроить Leave_current_balance.

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})

Ответы [ 2 ]

0 голосов
/ 10 февраля 2019

Вы можете заставить это работать и по-другому.Например:

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()

И вышеупомянутое не вызывает ошибку комбинированного выражения.

Или чуть проще:

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
    c_balance.leave_balance = current_balance
    c_balance.save()

ОБНОВЛЕНИЕ - реструктуризация моделей и представлений

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

Мое имя приложения в этом примере: 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)

В приведенном выше примере вы можете видеть, что я создал Директор и Персонал Модель, в которой вы можете установить столько персонала и директоров, сколько вы хотите в административной части.Я создал модель персонала, потому что, возможно, не все сотрудники будут пользователями, поэтому я думаю, что лучше хранить их отдельно в базе данных от пользователей.

Важно: сначаласоздайте модели «Директор» и «Персонал», а затем мигрируйте немедленно, поскольку две другие таблицы будут зависеть от них.Затем вы можете создать две другие модели.

Я также не думаю, что в LeaveBalance Model вы должны хранить больше вещей, чем я положил туда.Я думаю, что поле "Год", например, избыточно, поскольку вы всегда можете отфильтровать по дате и диапазону даты в базе данных, которую вы хотите.

Затем представления (я использовал простые представления только непосредственно изМодели).При использовании этих классов представлений вам не нужно создавать формы, поскольку они автоматически создаются из моделей, и вы можете обрабатывать их с помощью различных функций / методов, таких как формы в представлениях и в классах модели.

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"

Затем в urls.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 различных шаблона перенаправления, когда они отправляют форму NewLeave, 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 %}

Не забудьте перенести , а затем зарегистрировать модели в admin.py .Затем вы должны создать несколько сотрудников в базе данных и несколько директоров, чтобы попробовать выше.Я надеюсь, что вышеизложенное может дать вам некоторое направление для достижения цели вашего проекта.С этим я просто хотел привести очень простой пример.(Вы должны создать все другие необходимые шаблоны и представления).

Если вы создаете новое приложение для проверки вышеперечисленного, то в главном файле вашего проекта urls.py вы должны ссылаться (включать) на URL своего приложения следующим образом, добавив одну дополнительную строку в файл urls.py своего проекта.Затем все ваши новые URL-адреса приложения должны быть определены в файле urls.py вашего приложения:

Вот так будет выглядеть urls.py вашего основного проекта:

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

(у вас естьчтобы изменить Myusers1 на название вашего приложения,)

И, конечно, мы могли бы сделать много других вещей с помощью Model Manager в Django: https://docs.djangoproject.com/en/2.1/topics/db/managers/

0 голосов
/ 09 февраля 2019

Вы должны позвонить refresh_from_db на баланс.например balance.refresh_from_db(), чтобы получить обновленные значения из базы данных.

...