Python 基于book a table的在线食品配送系统数据库设计

Python 基于book a table的在线食品配送系统数据库设计,python,django,database,database-design,django-models,Python,Django,Database,Database Design,Django Models,我正在考虑开发一个在线食品配送系统以及预订一个桌子/大厅的概念。市场上只有一个竞争者。这就是为什么我想提出一个用户友好的完整功能包。我已经设计了一个数据库,但我想采纳专家的意见,了解如何扩展或简化我的数据库设计。请免费分享您对最佳数据库设计的想法 以下是我的想法: Customer user(FK) first_name last_name phone_number email address liked_restaurant(M2M) Restaurant u

我正在考虑开发一个在线食品配送系统以及预订一个桌子/大厅的概念。市场上只有一个竞争者。这就是为什么我想提出一个用户友好的完整功能包。我已经设计了一个数据库,但我想采纳专家的意见,了解如何扩展或简化我的数据库设计。请免费分享您对最佳数据库设计的想法

以下是我的想法:

Customer
  user(FK)
  first_name
  last_name
  phone_number
  email
  address
  liked_restaurant(M2M)

Restaurant
  user(FK)
  name
  city
  place
  phone_number
  email
  website
  banner
  view
  lat
  lang
  speciality
  opening_time
  closing_time
  features(M2M) # like Breakfast, Lunch, Night Life etc
  status(open or closed)
  is_parking
  is_wifi
  timings(M2M) # sunday opening&closing time, monday opening&closing time, ... etc

Category 
  menu_category 

Menu
  restaurant(FK)
  category(FK)
  name
  price
  minimum_quantity
  available
  rating 

Order
  user(FK)
  order_id(PK)
  food_id(M2M)
  restaurant_id(FK)
  quantity
  total_price


BookTable
  user(FK)
  restaurant(FK)
  quantity
  type - table/cabin/hall

Review

我应该如何用更好的设计构建我的数据库?有什么我做了错事或遗漏了吗?

正如我在评论中所说,这是一个基于意见的问题,可能有许多不同的答案。同样,这个问题并不适合像stackoverflow这样的网站

但是让我们试着帮助你

Customer
    user(FK) # why do you need this?
如果您想扩展django用户类,那么这并不能真正起作用。您将需要客户和用户之间的1:1关系。此外,在其他型号中,您应该进一步参考客户,而不是用户。 所以说:

Customer(models.Model):
    user = models.OneToOneField('User', ...)
在实体中,餐厅和所有其他实体都引用客户。我想知道为什么你有用户:餐厅1:n关系。无论如何,您应该将其更改为:

Restaurant(models.Model):
    customer = models.ForeignKey('Customer', ...)
如果可以,请使用PostgreSQL和JSON字段作为开始时间。然后你可以有这样的东西:

    timings = JSONField()
- 3 beers
- 1 coke
- 2 buffallo wings
- 1 spare ribs
- 1 nachos
JSON可能看起来像:

{
    'Monday' : {
        'opens': '10am',
        'closes': '10pm'
    },
    'Tuesday' : {
        'dayoff': true
    },
    'Wednesday': {
        'opens': '9am',
        'closes': '11pm'
    }
    # and so on
}
你可以也应该用不同的格式记录时间,但这只是一个例子。JSON可以是非常灵活的,你可以省去几天,你可以每天有不同的属性,包括休息时间。也许一家餐厅从早上9点开到下午2点,然后休息到下午5点,然后再开到晚上10点。因此,应该删除属性opening_time、closing_time和timings,即合并到此JSON字段中

将状态设置为虚拟字段。写一个获取当前时间的方法,并检查餐厅是否开门或关门。不要将其持久化到数据库中

您的实体菜单应该称为餐或菜单项。更好地思考如何命名变量。命名是非常重要的,我认为这是编程中最重要的。如果您不能正确命名类、方法或属性,您就不知道它是什么

您点的菜中有食物和餐厅。为什么?如果food_idM2M是上一款车型,您就可以在那里找到餐厅。除非你想吃牛肉汉堡、鸡秋葵汤之类的东西,而且很多不同的餐馆都有。 为什么数量是秩序的属性?当我想到秩序时,它可能是这样的:

    timings = JSONField()
- 3 beers
- 1 coke
- 2 buffallo wings
- 1 spare ribs
- 1 nachos
那么你指的是什么数量?我将使用额外字段创建一个M2M表,在Django中,您可以通过表指定,并使用所需的额外字段定义该模型:

OrderFood(models.Model):
    order_id(FK)
    food_id(FK)
    quantity
我可以写得更多,但那只是暂时的。我希望这对你有点帮助。 把一切都写在纸上。画你的实体,而不是写名字,画一个草图。画出顾客、餐馆、桌子、食物,给他们分配属性,并思考他们所处的关系

编辑:

检查JSONField的文档:

我将把框架作为标准关系数据库,并将所有灵活的属性放在JSON中。根据餐厅的不同,可以认为菜单非常不同。快餐外卖可以有:

{
    'Burgers': [
        'Hamburger',
        'Cheesburger'
    ],
    'Beverages': [
        'Coke',
        'Fanta'
    ]
}
{
    'Entrees': [
        ... whatever
    ],
    'Main courses': [
         {'Poultry': [ ... ]},
         {'Beef': [ ... ]},
         {'Fish': [ ... ]}
    ],
    'Deserts': [
        ... whatever
    ],
    'Beverages': [
        {'Wines': [
            {'White': [...]},
            {'Red': [...]}
        },
        {'Aperitifs': [...]},
        {'Beers': [...]}
    ]
}
一家高贵的法国餐厅可以有:

{
    'Burgers': [
        'Hamburger',
        'Cheesburger'
    ],
    'Beverages': [
        'Coke',
        'Fanta'
    ]
}
{
    'Entrees': [
        ... whatever
    ],
    'Main courses': [
         {'Poultry': [ ... ]},
         {'Beef': [ ... ]},
         {'Fish': [ ... ]}
    ],
    'Deserts': [
        ... whatever
    ],
    'Beverages': [
        {'Wines': [
            {'White': [...]},
            {'Red': [...]}
        },
        {'Aperitifs': [...]},
        {'Beers': [...]}
    ]
}
编辑:解释虚拟模型字段

“虚拟模型”字段表示模型实体具有一个属性,该属性未持久化到数据库,因此在数据库表中不作为列存在

例如:

import calendar
from datetime import datetime

Restaurant(models.Model):
    timings = JSONField()

    # illustrational code, not for production
    def _get_status(self):
        now = datetime.now()
        weekday = calendar.day_name[now.weekday()]
        if self.timings.get(weekday, False):
             open = self.timings[weekday].get('opens', 0)
             close = self.timings[weekday].get('closes', 0)
             if now.hour() >= open && now.hour() < close:
                 status = 'open'
             else:
                 status = 'closed'
        else:
             status = 'closed'
        return status

    status = property(_get_status)
    status.short_description('Status open-closed')

对于状态,表中不会有列。您不会将该值保存在数据库中,因为它取决于当前时刻。所以你要检查餐厅现在是否开门。您可以获取当前工作日和当前小时,并将其与JSONField中的值进行比较。

这是一个基于意见的问题,但我会尝试给出我的2美分。它看起来不错,但是您应该修复实体顺序-属性顺序_idPK是多余的。Django会自动设置主键,除非您真的想自己设置。实体审查了哪些属性?这里你需要一些属性。我还没有考虑过复习。关于订单号,这是我的错误,我想用随机数生成订单号。这更适合CodeReview。很抱歉,我不能删除这个问题,因为@cezar善意地陈述了他的观点。我第一次在codeReview上发帖,但我在这里也看到了这样的问题,所以我问了。我真的为此道歉。谢谢你的详细解释。我感谢你的好意帮助我。关于地位虚拟化,我不太清楚。最后一个问题,餐食的设计非常混乱,因为餐食可以有蔬菜、无蔬菜、糖果等类别,也可以有意大利、印度、法国等菜肴。所以我的问题是,杰森菲尔德最好像你所展示的那样解释杰森菲尔德的这种情况或情况
换张桌子。我对更好分类的膳食设计感到困惑,因此我们可以建立更好的过滤系统。是的,这令人困惑。也许它不仅仅是一顿饭,也可以是一种饮料。我认为菜单是一个实体,它本身就是餐厅的财产。菜单上会有食物或饮料。因此,你必须想出一个跨越餐饮的名字,目前我称之为MenuItem。菜单可以是中国菜或印度菜,也可以是葡萄酒、法国菜或意大利菜。你看,这是非常灵活或方案。因此,我建议将PostgreSQL与JSON结合使用,这将为您提供最好的关系数据库和面向文档的数据库。首先是重要的事情,然后添加你能想到的所有属性。试着组织它们。这不是一件容易的工作,在你达到目标之前需要多次重复。也许你会开始写代码,然后意识到这不是最好的解决方案,你会重新安排你的实体。这是一项乏味的工作,不会有简单、简短和直接的答案。