Python Django如何从多对多字段获取数据?

Python Django如何从多对多字段获取数据?,python,django-models,django-forms,django-views,Python,Django Models,Django Forms,Django Views,我有一个一周产品菜单的模型。它有七个日期字段、一个用户字段(外键)和七个多个字段。我可以将数据保存到数据库中,一切正常,但有一点除外:当我试图获取所有菜单或所有用户菜单时,所有选择的产品都来自m2m字段。。。跑了。好的,代码: models.py # All info about product: name, type (name of table, more precisly), calories,... class FoodProduct(models.Model): id = m

我有一个一周产品菜单的模型。它有七个日期字段、一个用户字段(外键)和七个多个字段。我可以将数据保存到数据库中,一切正常,但有一点除外:当我试图获取所有菜单或所有用户菜单时,所有选择的产品都来自m2m字段。。。跑了。好的,代码:

models.py

# All info about product: name, type (name of table, more precisly), calories,...
class FoodProduct(models.Model):
    id = models.AutoField(primary_key=True)
    prod_name=models.CharField(max_length=300, blank=True)
    prod_type=models.CharField(max_length=300, blank=True)
    prod_calories=models.DecimalField(max_digits=6, decimal_places=2, blank=True)
    prod_proteins=models.DecimalField(max_digits=6, decimal_places=2, blank=True)
    prod_fats=models.DecimalField(max_digits=6, decimal_places=2, blank=True)
    prod_carbohydrates=models.DecimalField(max_digits=6, decimal_places=2, blank=True)
    
    def __str__(self):
        return self.prod_name
    
    food = models.Manager()

    class Meta:
        verbose_name="Продукт"
        verbose_name_plural="Продукты"
        ordering=['prod_type','prod_name']

#model of week Product menu: 7 date fields, 1 foreign key (user), 7 m2m fields that directs to the food products

class ProductMenu(models.Model):
    id = models.AutoField(primary_key=True)
    timestamp=models.DateField(auto_now_add=True)
    monday=models.DateField("Понедельник", blank=True, null=True)
    tuesday=models.DateField("Вторник", blank=True, null=True)
    wednesday=models.DateField("Среда", blank=True, null=True)
    thursday=models.DateField("Четверг", blank=True, null=True)
    friday=models.DateField("Пятница", blank=True, null=True)
    saturday=models.DateField("Суббота", blank=True, null=True)
    sunday=models.DateField("Воскресенье", blank=True, null=True)
    list_of_selected_products_monday=models.ManyToManyField('FoodProduct',verbose_name="Лист продуктов на понедельник", related_name='monday', blank=True, default=None)
    list_of_selected_products_tuesday=models.ManyToManyField('FoodProduct',verbose_name="Лист продуктов на вторник", related_name='tuesday', blank=True, default=None)
    list_of_selected_products_wednesday=models.ManyToManyField('FoodProduct',verbose_name="Лист продуктов на среду", related_name='wednesday', blank=True, default=None)
    list_of_selected_products_thursday=models.ManyToManyField('FoodProduct',verbose_name="Лист продуктов на четверг", related_name='thursday', blank=True, default=None)
    list_of_selected_products_friday=models.ManyToManyField('FoodProduct',verbose_name="Лист продуктов на пятницу", related_name='friday', blank=True, default=None)
    list_of_selected_products_saturday=models.ManyToManyField('FoodProduct',verbose_name="Лист продуктов на субботу", related_name='saturday', blank=True, default=None)
    list_of_selected_products_sunday=models.ManyToManyField('FoodProduct',verbose_name="Лист продуктов на воскресенье", related_name='sunday', blank=True, default=None)
    user=models.ForeignKey('users.CustomUser', on_delete=models.PROTECT, default=None)

    def __str__(self):
        self.name=str(self.user)+', '+str(self.timestamp)
        return self.name

    product_menu=models.Manager()

    class Meta():
        verbose_name="Меню продуктов на неделю"
        verbose_name_plural="Меню продуктов на неделю"
        ordering=["timestamp"]
        constraints = [
            models.CheckConstraint(check=models.Q(monday__iso_week_day=1, monday__isnull=False) | models.Q(monday__isnull=True), name='check_monday'),
            models.CheckConstraint(check=models.Q(tuesday__iso_week_day=2, monday__isnull=False) | models.Q(tuesday__isnull=True), name='check_tuesday'),
            models.CheckConstraint(check=models.Q(wednesday__iso_week_day=3, wednesday__isnull=False) | models.Q(wednesday__isnull=True), name='check_wednesday'),
            models.CheckConstraint(check=models.Q(thursday__iso_week_day=4, thursday__isnull=False) | models.Q(thursday__isnull=True), name='check_thursday'),
            models.CheckConstraint(check=models.Q(friday__iso_week_day=5, friday__isnull=False) | models.Q(friday__isnull=True), name='check_friday'),
            models.CheckConstraint(check=models.Q(saturday__iso_week_day=6, saturday__isnull=False) | models.Q(saturday__isnull=True), name='check_saturday'),
            models.CheckConstraint(check=models.Q(sunday__iso_week_day=7, sunday__isnull=False) | models.Q(sunday__isnull=True), name='check_sunday')
            ]
所以,主要的想法是:1个用户可以有几个星期的产品菜单。约束检查所选日期是否恰好是所选的一周中的某一天(或者必须为空),但它不检查是否所有所选日期都在一周内(可能,稍后添加此约束)。我想添加约束:(date为null,m2m字段为null),但django不喜欢表达式
m2mfield\uuu为null=True
(这里也有建议吗?)

我的
forms.py

class Menu(forms.ModelForm):
    class Meta():
        model = ProductMenu
        fields = ['monday', 'tuesday', 'wednesday',
        'thursday', 'friday', 'saturday', 'sunday',
        'list_of_selected_products_monday', 
        'list_of_selected_products_tuesday',
        'list_of_selected_products_wednesday',
        'list_of_selected_products_thursday',
        'list_of_selected_products_friday',
        'list_of_selected_products_saturday',
        'list_of_selected_products_sunday'  
        ]
blah-blah-blah and main part:

user=request.user
user_product_menus=ProductMenu.product_menu.filter(user__username__iexact=user)
print(user_product_menus.values_list())

result:
<QuerySet [
(40, datetime.date(2020, 10, 23), datetime.date(2020, 10, 19), None, None, None, None, None, None, 1),

(42, datetime.date(2020, 10, 23), None, None, None, None, datetime.date(2020, 10, 23), None, None, 1)
]>
我的
view.py

class Menu(forms.ModelForm):
    class Meta():
        model = ProductMenu
        fields = ['monday', 'tuesday', 'wednesday',
        'thursday', 'friday', 'saturday', 'sunday',
        'list_of_selected_products_monday', 
        'list_of_selected_products_tuesday',
        'list_of_selected_products_wednesday',
        'list_of_selected_products_thursday',
        'list_of_selected_products_friday',
        'list_of_selected_products_saturday',
        'list_of_selected_products_sunday'  
        ]
blah-blah-blah and main part:

user=request.user
user_product_menus=ProductMenu.product_menu.filter(user__username__iexact=user)
print(user_product_menus.values_list())

result:
<QuerySet [
(40, datetime.date(2020, 10, 23), datetime.date(2020, 10, 19), None, None, None, None, None, None, 1),

(42, datetime.date(2020, 10, 23), None, None, None, None, datetime.date(2020, 10, 23), None, None, 1)
]>
废话废话和主要部分:
user=request.user
用户\产品\菜单=产品菜单.产品\菜单.过滤器(用户\用户名\ iexact=用户)
打印(用户\产品\菜单.值\列表())
结果:
第一个元素是数据库中的ID,第二个是时间戳,第三个是星期一日期,第四个是星期二,最后一个元素-用户id

我的多对多价值观在哪里?我如何访问它?它们保存在数据库中。我确实用``form.save_m2m()``正确地保存了它。保存实例后,在数据库中保存了值,屏幕如下:

我想问题在于保存数据

if request.user.is_authenticated:
            #fill the form
            form=Menu(request.POST)
            #get the user
            user=request.user
            #valid?
            if form.is_valid():
                #make an instance to save, but don't save, actually
                menu=form.save(commit=False)
                #set userfield value, I don't know why, 
                #but Menu(request.POST) doesn't fill that field
                menu.user=user
                #saving instance
                menu.save()
                #saving m2m <-------- Here is the problem? Maybe I saved instance without these fields
#and when I'm trying to get data in profile page - I'm getting only instance I saved first, but not all #data? 
#If so... how can I save it right? I can try to make a hidden field in html page and set it value through 
#javascript on load page and I can use only save() which saves and m2m fields, but that completly not #safe at all, 
#I don't wanna do this...
                form.save_m2m()
                print('example created')
            #redirect to profile page where 
            context={
            }
            return redirect('profile', username=user)
如果request.user.u经过身份验证:
#填表
表单=菜单(request.POST)
#获取用户
user=request.user
#有效吗?
如果form.is_有效():
#创建一个实例来保存,但实际上不保存
menu=form.save(commit=False)
#设置userfield值,我不知道为什么,
#但是菜单(request.POST)并没有填充该字段
menu.user=user
#保存实例
menu.save()

#保存m2m一切都很好,只是我对查询集的理解不好。 正确的行动顺序:

  • 要访问用户在某些菜单中选择的产品,我们需要获取(一般)菜单,在该菜单中我们要显示每个选择的产品。是的,简单,合乎逻辑,但我已经筋疲力尽了,不想。。。今天我花了15秒才明白我的错误
  • menu=ProductMenu.product\u menu.get(id=您选择的id或其他)
    
    我的主要错误是:我无法访问相关字段,而不获取我试图访问的特定菜单。 2) 在此对象中,您可以访问相关字段:

    products\u for\u monday=菜单。列出所选的\u产品\u monday.all()
    #或仅在一个字符串中1)+2)
    products_for_monday=ProductMenu.product_menu.get(id=#)。列出所选的_产品的_monday.all()
    
    就这些。。。是啊,傻得要命