Я хочу, чтобы расширенный пользователь (поставщик) мог видеть только свои продукты, заказы и клиентов на панели мониторинга

#python #django

#python #django

Вопрос:

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

Невозможно запросить «имя дистрибьютора»: должен быть экземпляр «User».

Вид панели мониторинга

 def dashboard(request):
    orders = Order.objects.filter(Distributor__user=request.user.Distributor)
    customers = Customer.objects.all()

    total_customers = customers.count()

    total_orders = orders.count()
    Completed = orders.filter(status='Completed').count()
    OnShipping = orders.filter(status='OnShipping').count()

    context = {'orders': orders, 'customers': customers, 'total_customers': total_customers,
               'total_orders': total_orders, 'Completed': Completed,
               'OnShipping': OnShipping}

    return render(request, 'dashboard.html', context)
  

Пользовательская модель дистрибьютора

 class User(AbstractUser):
    is_distributor = models.BooleanField(default=False)
    is_customer = models.BooleanField(default=False)


class Distributor(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='Distributor', primary_key=True)
    name = models.CharField(max_length=200, null=True)
    first_name = models.CharField(blank=True, max_length=150)
    last_name = models.CharField(blank=True, max_length=150)
    phone = PhoneNumberField(max_length=200, null=True)
    email = models.CharField(max_length=200, null=True)
    Tax_compliance_certificate = models.FileField(upload_to='distaxcerts/', null=False, blank=False)
    profile_pic = models.ImageField(upload_to='profile/', default="profile1.png", null=True, blank=True)
    date_created = models.DateTimeField(auto_now_add=True, null=True)
    till_no = models.CharField(max_length=20, null=True, blank=True)

    def __str__(self):
        return self.user.username

    def user_name(self):
        return self.user.first_name   ' '   self.user.last_name   ' ['   self.user.username   '] '

    def image_tag(self):
        return mark_safe('<img src="{}" height="50"/>'.format(self.profile_pic.url))

    image_tag.short_description = 'Image'
  

Модель продукта

 class Product(models.Model):
    delivery = (
        ('Daily', 'Daily'),
        ('Bi-Weekly', 'Bi-Weekly'),
        ('Weekly', 'Weekly'),
        ('Monthly', 'Monthly'),
        ('Quarterly', 'Quarterly'),
        ('Semi-Annually', 'Semi-Annually'),
        ('Annually', 'Annually'),
        ('Custom', 'Custom'),
    )
    VARIANTS = (
        ('None', 'None'),
        ('Weight', 'Weight'),
        ('Size', 'Size'),
        ('Color', 'Color'),
        ('Size-Color', 'Size-Color'),

    )
    category = models.ForeignKey(Category, on_delete=models.CASCADE)  # many to one relation with Category
    title = models.CharField(max_length=150)
    keywords = models.CharField(max_length=255)
    promote = models.BooleanField(default=False)
    description = models.TextField(max_length=255)
    image = models.ImageField(upload_to='images/', null=False)
    price = models.DecimalField(max_digits=12, decimal_places=2, default=0)
    minamount = models.IntegerField(default=3)
    amount = models.IntegerField(default=0)
    delivery = models.CharField(max_length=200, null=True, choices=delivery)
    detail = RichTextUploadingField()
    variant = models.CharField(max_length=10, choices=VARIANTS, default='None')

    slug = models.SlugField(null=False, unique=True)
    create_at = models.DateTimeField(auto_now_add=True)
    update_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.title

    # method to create a fake table field in read only mode
    def image_tag(self):
        if self.image.url is not None:
            return mark_safe('<img src="{}" height="50"/>'.format(self.image.url))
        else:
            return ""

    def get_absolute_url(self):
        return reverse('category_detail', kwargs={'slug': self.slug})

    def averagereview(self):
        reviews = Comment.objects.filter(product=self, status='True').aggregate(avarage=Avg('rate'))
        avg = 0
        if reviews["average"] is not None:
            avg = float(reviews["average"])
        return avg

    def countreview(self):
        reviews = Comment.objects.filter(product=self, status='True').aggregate(count=Count('id'))
        cnt = 0
        if reviews["count"] is not None:
            cnt = int(reviews["count"])
        return cnt
  

Модель заказа

 class Order(models.Model):
    STATUS = (
        ('New', 'New'),
        ('Accepted', 'Accepted'),
        ('Preparing', 'Preparing'),
        ('OnShipping', 'OnShipping'),
        ('Completed', 'Completed'),
        ('Canceled', 'Canceled'),
    )
    Distributor = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE,
                                       null=True)
    Customer = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE,
                                 null=True, related_name='customer_client')
    code = models.CharField(max_length=5, editable=False)
    first_name = models.CharField(max_length=10)
    last_name = models.CharField(max_length=10)
    phone = models.CharField(blank=True, max_length=20)
    address = models.CharField(blank=True, max_length=150)
    city = models.CharField(blank=True, max_length=20)
    country = models.CharField(blank=True, max_length=20)
    total = models.FloatField()
    status = models.CharField(max_length=10, choices=STATUS, default='New')
    ip = models.CharField(blank=True, max_length=20)
    adminnote = models.CharField(blank=True, max_length=100)
    create_at = models.DateTimeField(auto_now_add=True)
    update_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.code
  

Ответ №1:

Я думаю, вы немного неправильно поняли ссылку на внешний ключ в Django.
Когда вы делаете что-то подобное:

 class Order(models.Model):
    distributor = models.OneToOneField(settings.AUTH_USER_MODEL, 
        on_delete=models.CASCADE, null=True) 
  

distributor это экземпляр пользователя, поэтому вы должны сделать это:

 order = Order.objects.filter(distributor=request.user)