管理员的 Django 管理员自定义保存功能与普通员工用户不同

Posted

技术标签:

【中文标题】管理员的 Django 管理员自定义保存功能与普通员工用户不同【英文标题】:Django Admin Customise Save Function for Admin to be different than regular Staff User 【发布时间】:2018-09-26 16:29:58 【问题描述】:

我想为管理员运行自定义保存功能,该功能必须不同于常规管理员。原因是我从模型中隐藏了一个字段(parking_off)。我正在做一个停车应用程序,经理希望为员工用户隐藏一个字段,因此他们以某种方式调整了我的整个代码。

我怎样才能让这个保存功能只为管理员运行? park_off 字段仅对管理员可见。

  def save(self):
        list = []
        d = self.parking_on
        while d <= self.parking_off:
            list.append(
                Parking(user=self.user,
                        email=self.email,
                        parking_on=d,
                        parking_off=d,
                        location=self.location
                        )
            )
            d = d + timedelta(days=1)
        Parking.objects.bulk_create(list)

请在下面找到我的模型:

from django.db import models
from django.conf import settings
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
from datetime import datetime, timedelta, time
from django.core.exceptions import NON_FIELD_ERRORS

today = datetime.now().date()
tomorrow = today + timedelta(1)
now = datetime.now()
l = now.hour
m = int(now.strftime("%H"))


class ParkingManager(models.Manager):
    def active(self, *args, **kwargs):
        return super(ParkingManager, self).filter(draft=False).filter(parking_on__lte=datetime.now())


class Parking(models.Model):
    PARKING_PLOT = (
        ('P1', 'Parking #1'),('P2', 'Parking #2'), ('P3', 'Parking #3'), 
        ('P4', 'Parking #4'),('P5', 'Parking #5'), ('P6', 'Parking #5'), 
        ('P7', 'Parking #7'),('P8', 'Parking #8'), ('P9', 'Parking #9'), 
        ('P10', 'Parking #10'),('P11', 'Parking #11'), ('P12', 'Parking #12'), 
        ('P13', 'Parking #13'),('P14', 'Parking #14'), ('P15', 'Parking #15')

    )
    user = models.ForeignKey(settings.AUTH_USER_MODEL,
                             blank=True, null=True, default=1, on_delete=True)
    email = models.EmailField(blank=True, null=True)
    parking_on = models.DateField(auto_now=False, auto_now_add=False, blank=True, null=True,
                                  help_text='Alege data cand doresti sa vii in office',)
    parking_off = models.DateField(auto_now=False, auto_now_add=False, blank=True, null=True,
                                   help_text='Alege Data Plecarii')
    numar_masina = models.CharField(max_length=8, default="IF77WXV", blank=True, null=True,
                                    help_text='Introdu Numarul Masinii')
    location = models.CharField(max_length=3, blank=True, default="P1", null=True, choices=PARKING_PLOT,
                                help_text='Alege Locul de Parcare Dorit')
    updated = models.DateTimeField(
        auto_now=True, auto_now_add=False, blank=True, null=True)
    timestamp = models.DateTimeField(
        auto_now=False, auto_now_add=True, blank=True, null=True)
    # coming_hour = models.TimeField(default=time(
    #     9, 00), auto_now=False, auto_now_add=False, help_text='Alege Ora Venirii')
    # departure_hour = models.TimeField(default=time(
    #     18, 00), auto_now=False, auto_now_add=False, help_text='Alege Ora Plecarii')
    objects = ParkingManager()

    def __str__(self):
        return self.location + " | " + str(self.parking_on) + " | " + str(self.parking_off)

    class Meta:
        verbose_name_plural = "parking"
        ordering = ["-parking_on"]
        unique_together = ("parking_on", "location")

    def clean(self):
        if self.parking_on == today:  # merge--vedem dak parcam azi
            raise ValidationError(
                'parking_on': _('Please book for a date starting tomorrow'))
        if self.parking_off < self.parking_on:  # merge-vedem daca bookam in trecut
            raise ValidationError(
                'parking_off': _('You cant book for a past date!'))

    def validate_unique(self, exclude=None):
        try:
            super(Parking, self).validate_unique()
        except ValidationError as e:
            raise ValidationError(
                'location': 
                _("Dear " + str(self.user) +
                                  " seems that the parking places " + str(self.location) +
                                  " you want to book, is already taken on " + str(self.parking_on) + " !" +
                                  " Please select another date or other parking location! "
                                  ))

    def save(self):
        list = []
        d = self.parking_on
        while d <= self.parking_off:
            list.append(
                Parking(user=self.user,
                        email=self.email,
                        parking_on=d,
                        parking_off=d,
                        location=self.location
                        )
            )
            d = d + timedelta(days=1)
        Parking.objects.bulk_create(list)

管理员:

from django.contrib import admin
from .models import Parking
from django.contrib import messages


def remove_from_fieldsets(fieldsets, fields):
        for fieldset in fieldsets:
            for field in fields:
                if field in fieldset[1]['fields']:
                    new_fields = []
                    for new_field in fieldset[1]['fields']:
                        if not new_field in fields:
                            new_fields.append(new_field)

                    fieldset[1]['fields'] = tuple(new_fields)
                    break
class ParkingModelAdmin(admin.ModelAdmin):
    list_display = ["user", "location",
                    "parking_on"]
    list_display_links = [ "location"]
    list_editable = [ "parking_on"]
    list_filter = ["parking_on", "location", "email"]
    search_fields = ["location", "parking_on"]
    date_hierarchy = 'parking_on'

    class Meta: 

        model = Parking


    def get_form(self, request, obj=None, **kwargs):
        form = super().get_form(request, obj, **kwargs)
        if not obj:
            user = request.user
            form.base_fields['user'].initial = user
            form.base_fields['email'].initial = user.email
        return form 

    def save_model(self, request, obj, form, change):
        # add an additional message
        user = request.user
        messages.info(request, "Dear " + str(user)+ " "+ " please note that your parking plot has been reserved")
        super(ParkingModelAdmin, self).save_model(request, obj, form, change)


    def get_fieldsets(self, request, obj=None):
        fieldsets = super(ParkingModelAdmin, self).get_fieldsets(request, obj)

        if not request.user.is_superuser:
            remove_from_fieldsets(fieldsets, ('parking_off',))

        return fieldsets

admin.site.register(Parking, ParkingModelAdmin)

因为我为非管理员消除了 park_off 字段,所以我收到如下错误,这是正常的,因为该字段不存在

TypeError at /admin/parcare/parking/add/ 
'<' not supported between instances of 'NoneType' and 'datetime.date'

我也尝试过尝试,但没有成功:

def save(self):
        try:
            list = []
            d = self.parking_on
            while d <= self.parking_off:
                list.append(
                    Parking(user=self.user,
                            email=self.email,
                            parking_on=d,
                            parking_off=d,
                            location=self.location
                            )
                )
                d = d + timedelta(days=1)
            Parking.objects.bulk_create(list)
        except:
            parking_off=self.parking_on
            list = []
            d = self.parking_on
            while d <= parking_off:
                list.append(
                    Parking(user=self.user,
                            email=self.email,
                            parking_on=d,
                            parking_off=d,
                            location=self.location
                            )
                )
                d = d + timedelta(days=1)
            Parking.objects.bulk_create(list)

还有:

def save(self, request, obj, form, change):
    if request.user.is_superuser:
            list = []
            d = self.parking_on
            while d <= self.parking_off:
                list.append(
                    Parking(user=self.user,
                            email=self.email,
                            parking_on=d,
                            parking_off=d,
                            location=self.location
                            )
                )
                d = d + timedelta(days=1)
            Parking.objects.bulk_create(list)
    else:
        super().save(request, obj, form, change)

也尝试过:

 def save_model_clean(self, request, obj, form, change):
     if not request.user.is_superuser:
         if self.parking_off != self.parking_on:
             raise ValidationError(
                 'parking_off': _('You cant book for a future date!'))
         obj.save()

【问题讨论】:

【参考方案1】:

你做了正确的事,如果你从管理面板保存数据,只需覆盖你的 save_model 以合并这两个东西:

def save_model(self, request, obj, form, change):
    user = request.user
    if user.is_superuser:
        list = []
        d = obj.parking_on
        while d <= obj.parking_off:
            list.append(
                Parking(user=obj.user,
                        email=obj.email,
                        parking_on=d,
                        parking_off=d,
                        location=obj.location
                        )
            )
            d = d + timedelta(days=1)
        Parking.objects.bulk_create(list)
        messages.info(request, "your_custom_message")
    else:
        messages.info(request, "Dear " + str(user)+ " "+ " please note that your parking plot has been reserved")
        super().save_model(request, obj, form, change)

这应该足以满足您的需要。

【讨论】:

谢谢!它仍然在节省。它不检查用户是否不是管理员并且是员工

以上是关于管理员的 Django 管理员自定义保存功能与普通员工用户不同的主要内容,如果未能解决你的问题,请参考以下文章

Django站点管理

django模型中的自定义保存方法

在已过滤的查询集上使用 Django 自定义管理器功能

自定义路由组件,Django的admin后台管理,DRF的三大认证,jwt认证

Django 1.6 管理面板自定义

管理员中的 Django 自定义用户模型应用程序级别权限管理