我有一个模型,需要一个用户(ForeignKey)和一个类别(M2M),对于表单中的类别字段,我通过向其添加自定义字段(数据列表,但也有输入)扩展了其功能。 ,但是我无法保存带有类别和用户的表单。
models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
class User(AbstractUser):
pass
class Category(models.Model):
name = models.CharField(max_length=20, blank=True)
class Listings(models.Model):
title = models.CharField(max_length=64, null=False, blank=False)
description = models.CharField(max_length=64, blank=True)
bid = models.IntegerField(null=False, blank=False)
timestamp = models.DateField(db_index=True, auto_now_add=True)
image_url = models.URLField(blank=True)
category = models.ManyToManyField(Category)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
class Meta:
ordering=['timestamp', 'title']
forms.py
from auctions.models import Listings
from django import forms
class ListTextWidget(forms.TextInput):
def __init__(self, data_list, name, *args, **kwargs):
super(ListTextWidget,self).__init__(*args, **kwargs)
self._name = name
self._list = data_list
self.attrs.update({
'list':'list__%s' % self._name,
'class':'form-control'
})
def render(self, name, value, attrs=None, renderer=None):
text_html = super(ListTextWidget, self).render(name, value, attrs=attrs)
data_list = '<datalist id="list__%s">' % self._name
for item in self._list:
data_list += '<option value="%s">' % item
data_list += '</datalist>'
return (text_html + data_list)
class ListingsForm(forms.ModelForm):
category = forms.CharField()
class Meta:
model = Listings
fields = ['title', 'description', 'bid', 'image_url', 'category']
widgets = {
'title': forms.TextInput(attrs={'class':'form-control'}),
'description': forms.TextInput(attrs={'class':'form-control'}),
'bid': forms.TextInput(attrs={'class':'form-control'}),
'image_url': forms.TextInput(attrs={'class':'form-control'}),
'category': forms.TextInput(attrs={'class':'form-control'})
}
def __init__(self, *args, **kwargs):
_category_list = kwargs.pop('data_list', None)
super(ListingsForm, self).__init__(*args, **kwargs)
self.fields['category'].widget = ListTextWidget(data_list=_category_list, name='category-list')
views.py
def create_listings(request):
if request.method == "POST":
form = ListingsForm(request.POST)
if form.is_valid():
#**what to do to save category and user**
return redirect(reverse('index'))
else:
category_list = Category.objects.all().values_list('name')
form = ListingsForm(data_list=category_list)
return render(request, 'auctions/create_listings.html', {
'form': form
})
在form.save()期间,如何将所有数据保存到新列表中?
我尝试使用commit = False,但是得到ValueError:Field 'id' expected a number but got 'o'.
是否可以立即保存所有内容,还是必须创建列表,然后手动添加其余数据?
答案 0 :(得分:1)
您可以尝试以下操作,将M2M字段更改为外键,然后在表单中没有太多更改,只需删除类别,最后在视图中保存后添加用户(commit = False) models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
class User(AbstractUser):
pass
class Category(models.Model):
name = models.CharField(max_length=20, blank=True)
def __str__(self) -> str:
return self.name
class Listings(models.Model):
title = models.CharField(max_length=64, null=False, blank=False)
description = models.CharField(max_length=64, blank=True)
bid = models.IntegerField(null=False, blank=False)
timestamp = models.DateField(db_index=True, auto_now_add=True)
image_url = models.TextField(blank=True)
category = models.ForeignKey(Category, null=True, blank=True, on_delete=models.SET_NULL)
owner = models.ForeignKey(User, verbose_name="owner", on_delete=models.CASCADE, related_name='owner')
class Meta:
ordering=['-timestamp', 'title']
def __str__(self) -> str:
return self.title
forms.py
from auctions.models import Biddings, Comments, Listings
from django import forms
class ListTextWidget(forms.TextInput):
def __init__(self, data_list, name, *args, **kwargs):
super(ListTextWidget,self).__init__(*args, **kwargs)
self._name = name
self._list = data_list
self.attrs.update({
'list':'list__%s' % self._name,
'class':'form-control'
})
def render(self, name, value, attrs=None, renderer=None):
text_html = super(ListTextWidget, self).render(name, value, attrs=attrs)
data_list = '<datalist id="list__%s">' % self._name
for item in self._list:
data_list += '<option value="%s">' % item
data_list += '</datalist>'
return (text_html + data_list)
class ListingsForm(forms.ModelForm):
category = forms.CharField()
class Meta:
model = Listings
fields = ['title', 'description', 'bid', 'image_url']
widgets = {
'title': forms.TextInput(attrs={'class':'form-control'}),
'description': forms.TextInput(attrs={'class':'form-control'}),
'bid': forms.TextInput(attrs={'class':'form-control'}),
'image_url': forms.TextInput(attrs={'class':'form-control'}),
'category': forms.TextInput(attrs={'class':'form-control'})
}
def __init__(self, *args, **kwargs):
_category_list = kwargs.pop('data_list', None)
super(ListingsForm, self).__init__(*args, **kwargs)
self.fields['category'].widget = ListTextWidget(data_list=_category_list, name='category-list')
views.py 在这里,我手动绘制了字段以进行澄清
def create_listings(request):
if request.method == "POST":
form = ListingsForm(request.POST)
if form.is_valid():
title = form.cleaned_data["title"]
description = form.cleaned_data["description"]
bid = form.cleaned_data["bid"]
image_url = form.cleaned_data["image_url"]
category, created = Category.objects.get_or_create(name = form.cleaned_data["category"])
owner = request.user
listing = Listings(
title=title,
description=description,
bid=bid,
image_url=image_url,
owner=owner,
category=Category.objects.get(name = form.cleaned_data["category"])
)
listing.save()
messages.success(request, "Listing created succesfully")
return redirect(reverse('index'))
else:
category_list = Category.objects.all().values_list('name')
form = ListingsForm(data_list=category_list)
return render(request, 'auctions/create_listings.html', {
'form': form
})
我真的希望这有助于解决您的问题:)。干杯
答案 1 :(得分:0)
为什么不从django.contrib.auth.models导入用户