Python Django如何从多对多字段获取数据?
我有一个一周产品菜单的模型。它有七个日期字段、一个用户字段(外键)和七个多个字段。我可以将数据保存到数据库中,一切正常,但有一点除外:当我试图获取所有菜单或所有用户菜单时,所有选择的产品都来自m2m字段。。。跑了。好的,代码: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
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()
就这些。。。是啊,傻得要命