首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >有效的Django数据库建模

有效的Django数据库建模
EN

Stack Overflow用户
提问于 2014-03-09 19:22:03
回答 2查看 141关注 0票数 0

我想建立以下应用模型:一个老板有不同的商店,每个商店都有一些顾客和一些雇员为该商店工作;同一个雇员可以在属于同一个老板的不同商店工作,也可以在属于不同老板的商店工作。只有所有者和员工才能登录到系统,客户不能登录。我创建了以下模型并将用户添加到不同的组(使用Django Auth system和允许自定义用户模型的1.6.2版本),但我关注应用程序正在执行的查询数量,我对建模不太确定。最大的困难是,如果店主有不同的商店,当店主登录到他需要选择与哪个商店一起工作的系统时,也能够添加相关的员工和客户(只有店主可以添加员工和客户)。

代码语言:javascript
复制
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin

class CustomUser(AbstractBaseUser, PermissionsMixin):

    email = models.CharField(max_length=254,
        unique=True)
    firstname = models.CharField(max_length=64)
    lastname = models.CharField(max_length=64)
    ...
    objects = CustomUserManager()

    USERNAME_FIELD = 'email'
    ...        

class Shop(models.Model):
    name = models.CharField(...)
    city = ...
    address = ...

class Customer(models.Model):
    shop = models.ForeignKey(Shop)
    ...

class Employee(CustomUser):
    shops = models.ManyToManyField(Shop)
    ...

class Owner(CustomUser):
    shops = models.ManyToManyField(Shop)
    ...

现在,当员工或所有者用电子邮件登录到系统时,应用程序需要显示一个带有可用商店的选择框,用户的选择需要传递到应用程序的每个视图:我如何做到这一点?我想不可能是一个帖子,因为我会在应用程序中有其他的表单,应该是一个GET请求,但是我需要验证的每一个请求都是商店的所有者或雇员的(越来越多的查询)。我已经开发了应用程序的很大一部分(例如,订单),但我要回到开始阶段;我不知道我所做的所有模型都应该与商店或所有者相关。如有任何建议,敬请见谅。谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-03-09 22:38:42

我使用基于Django的身份验证中间件的会话和自定义中间件解决了类似的问题:

shop/middleware.py

代码语言:javascript
复制
from django.utils.functional import SimpleLazyObject
from <appname> import shop

def get_shop(request):
    if not hasattr(request, '_cached_shop'):
        request._cached_shop = shop.get_shop(request)
    return request._cached_shop


class ShopMiddleware(object):
    def process_request(self, request):
        assert hasattr(request, 'session'), "The Shop middleware requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.sessions.middleware.SessionMiddleware'."

        request.shop = SimpleLazyObject(lambda: get_shop(request))

shop/__init__.py

代码语言:javascript
复制
from django.core.exceptions import ObjectDoesNotExist
from <appname>.shop.models import Shop

SHOP_SESSION_KEY = '_session_shop_id'

def get_shop(request):
    try:
        shop_id = request.session[SHOP_SESSION_KEY]
        shop = Shop.objects.get(id=shop_id)
        return shop
    except (KeyError, ObjectDoesNotExist):
        return None

def switch_shop(request, shop):
    if not isinstance(request.user, CustomUser):
        request.session[SHOP_SESSION_KEY] = None
    if request.user.shops.filter(id=shop.id).exists():
        request.session[SHOP_SESSION_KEY] = shop.id

然后,只需将ShopMiddleware添加到您的中间件类中,如果选择其中一个,request.shop将始终指向当前的商店。

在我的例子中,我还编写了一个类似于login_required的视图包装器,它可以重定向到允许在需要而不是选择的时候选择商店的页面。看看login_required源代码,找出一个正确方向的好指针。

编辑:您仍然需要选择一个商店,所以编写一个视图,向用户提供正确的选项,然后让它调用switch_shop(request, shop)。如果该商店是当前用户的有效商店,则会话将设置为该商店,直到它被更改或用户注销为止。

票数 0
EN

Stack Overflow用户

发布于 2014-03-09 21:08:10

我现在的例子可能是不完美的,但我认为它会澄清您应该如何使用Django来实现这个目标。(同时阅读以下内容:https://docs.djangoproject.com/en/1.6/topics/db/managers/)

代码语言:javascript
复制
class ShopsUser(AbstractBaseUser, PermissionsMixin):

    email = models.CharField(max_length=254,
        unique=True)
    firstname = models.CharField(max_length=64)
    lastname = models.CharField(max_length=64)
    ...
    objects = CustomUserManager()

    USERNAME_FIELD = 'email'
    ...
    priviledge_flag = models.CharField(choices=(('o', 'owner'), ('e', 'employe'), ('c', 'customer'))

class Customer(models.Model):
    shop = models.ForeignKey(Shop)

class Shop(models.Model):
    customers = models.ForeignKey(Customer, related_name='shops')
    admins = models.ManyToMany(ShopsUser, related_name='managed_shops')

现在,您可以使用视图中的登录用户(使用会话)查找所有数据:

代码语言:javascript
复制
class SomeView(View):
    def get(self, *args, **kwargs):
        admin = self.request.user
        all_singed_in_admin_shops = admin.managed_shops.all()
        first_shop = all_singed_in_admin_shops[0]
        first_shop_customers = first_shop.customers.all()
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22286908

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档