我想为以下应用程序建模:所有者拥有不同的商店,每个商店都有一些客户和一些为该商店工作的员工;同一个员工可以在属于同一所有者的不同商店工作,也可以在属于不同所有者的商店工作。 只有所有者和员工才能登录系统,客户无法登录。 我创建了以下模型并将用户添加到不同的组(使用Django Auth系统和允许自定义用户模型的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)
...
现在,当员工或所有者使用他的电子邮件登录系统时,应用程序需要显示包含可用商店的选择框,并且用户的选择需要传递到应用程序的每个视图:如何操作我这样做?我想不能是POST,因为我在应用程序中有其他表单,应该是GET请求,但是我需要验证的每个请求都是Shop属于所有者或员工(增加查询数量) 。我已经开发了应用程序的一个重要部分(例如订单)但我回到了开头;我不知道我所做的所有模型是否应与商店或所有者相关。 任何建议表示赞赏。感谢。
答案 0 :(得分:0)
我现在我的例子可能不完美,但我认为它将澄清你应该如何使用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()
答案 1 :(得分:0)
我使用基于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
的{{3}},找到正确方向的好指针。
编辑:您仍需要选择商店,因此请撰写一个向用户显示正确选项的视图,并让其调用switch_shop(request, shop)
。如果商店是当前用户的有效商店,则会话将被设置为该商店,直到它被更改或用户退出为止。