我想建立以下应用模型:一个老板有不同的商店,每个商店都有一些顾客和一些雇员为该商店工作;同一个雇员可以在属于同一个老板的不同商店工作,也可以在属于不同老板的商店工作。只有所有者和员工才能登录到系统,客户不能登录。我创建了以下模型并将用户添加到不同的组(使用Django Auth system和允许自定义用户模型的1.6.2版本),但我关注应用程序正在执行的查询数量,我对建模不太确定。最大的困难是,如果店主有不同的商店,当店主登录到他需要选择与哪个商店一起工作的系统时,也能够添加相关的员工和客户(只有店主可以添加员工和客户)。
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请求,但是我需要验证的每一个请求都是商店的所有者或雇员的(越来越多的查询)。我已经开发了应用程序的很大一部分(例如,订单),但我要回到开始阶段;我不知道我所做的所有模型都应该与商店或所有者相关。如有任何建议,敬请见谅。谢谢。
发布于 2014-03-09 22:38:42
我使用基于Django的身份验证中间件的会话和自定义中间件解决了类似的问题:
shop/middleware.py
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
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)。如果该商店是当前用户的有效商店,则会话将设置为该商店,直到它被更改或用户注销为止。
发布于 2014-03-09 21:08:10
我现在的例子可能是不完美的,但我认为它会澄清您应该如何使用Django来实现这个目标。(同时阅读以下内容:https://docs.djangoproject.com/en/1.6/topics/db/managers/)
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')现在,您可以使用视图中的登录用户(使用会话)查找所有数据:
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()https://stackoverflow.com/questions/22286908
复制相似问题