我在Django 1.11上有一个ModelForm
,并且正在将一些字段移至另一个模型。调用make_migrations
会导致错误,因为这些字段在当前模型中不存在。我在表单中添加了一些字段,但是其中一个字段是TranslatedField
,因此当前有2个字段,将来可能会更多,具体取决于语言的数量。该字段的名称为city,目前我收到一条错误消息“ Unknown field(s) (city_en, city_he) specified for SiteProfile
”(因为我使用的是“ en”和“ he”这两种语言),但我想使用以下方式动态创建所有字段for循环遍历我们在项目中使用的语言。我可以覆盖__new__
方法(这是一种很好的编程方法)还是其他方法?我不希望对特定的字段名称(city_en
和city_he
)进行硬编码,因为它们将来可能会更改,具体取决于我们使用的语言种类。
您可以在GitHub上看到我当前的commit(无效)。
以及该分支的当前code。
我想知道什么是定义动态字段列表的最佳编程方法(所有字段都相同,将只使用其中一个,而其他__init__
方法中将其删除)一个ModelForm,其中的字段保存在另一个模型中(有2个模型,但只有一个表单)。
由于运行make_migrations时出现此错误,我仍然没有提交迁移。
(我定义了一个命令make_migrations
,它仅执行makemigrations
)
表单(我尝试覆盖__new__
):
class SpeedyMatchProfileBaseForm(DeleteUnneededFieldsMixin, forms.ModelForm):
user_fields = (
'diet',
'smoking_status',
'marital_status',
*(to_attribute(name='city', language_code=language_code) for language_code, language_name in django_settings.LANGUAGES),
)
validators = {
'height': [speedy_match_accounts_validators.validate_height],
'diet': [speedy_match_accounts_validators.validate_diet],
'smoking_status': [speedy_match_accounts_validators.validate_smoking_status],
'marital_status': [speedy_match_accounts_validators.validate_marital_status],
**{to_attribute(name='profile_description', language_code=language_code): [speedy_match_accounts_validators.validate_profile_description] for language_code, language_name in django_settings.LANGUAGES},
**{to_attribute(name='city', language_code=language_code): [speedy_match_accounts_validators.validate_city] for language_code, language_name in django_settings.LANGUAGES},
**{to_attribute(name='children', language_code=language_code): [speedy_match_accounts_validators.validate_children] for language_code, language_name in django_settings.LANGUAGES},
**{to_attribute(name='more_children', language_code=language_code): [speedy_match_accounts_validators.validate_more_children] for language_code, language_name in django_settings.LANGUAGES},
**{to_attribute(name='match_description', language_code=language_code): [speedy_match_accounts_validators.validate_match_description] for language_code, language_name in django_settings.LANGUAGES},
'gender_to_match': [speedy_match_accounts_validators.validate_gender_to_match],
'min_age_match': [speedy_match_accounts_validators.validate_min_age_match],
'max_age_match': [speedy_match_accounts_validators.validate_max_age_match],
'diet_match': [speedy_match_accounts_validators.validate_diet_match],
'smoking_status_match': [speedy_match_accounts_validators.validate_smoking_status_match],
'marital_status_match': [speedy_match_accounts_validators.validate_marital_status_match],
}
# ~~~~ TODO: diet choices depend on the current user's gender. Also same for smoking status and marital status.
diet = forms.ChoiceField(choices=User.DIET_VALID_CHOICES, widget=forms.RadioSelect(), label=_('My diet'))
smoking_status = forms.ChoiceField(choices=User.SMOKING_STATUS_VALID_CHOICES, widget=forms.RadioSelect(), label=_('My smoking status'))
marital_status = forms.ChoiceField(choices=User.MARITAL_STATUS_VALID_CHOICES, widget=forms.RadioSelect(), label=_('My marital status'))
photo = forms.ImageField(required=False, widget=CustomPhotoWidget, label=_('Add profile picture'))
class Meta:
model = SpeedyMatchSiteProfile
fields = (
'photo',
*(to_attribute(name='profile_description', language_code=language_code) for language_code, language_name in django_settings.LANGUAGES),
*(to_attribute(name='city', language_code=language_code) for language_code, language_name in django_settings.LANGUAGES),
'height',
*(to_attribute(name='children', language_code=language_code) for language_code, language_name in django_settings.LANGUAGES),
*(to_attribute(name='more_children', language_code=language_code) for language_code, language_name in django_settings.LANGUAGES),
'diet',
'smoking_status',
'marital_status',
'gender_to_match',
*(to_attribute(name='match_description', language_code=language_code) for language_code, language_name in django_settings.LANGUAGES),
'min_age_match',
'max_age_match',
'diet_match',
'smoking_status_match',
'marital_status_match',
)
widgets = {
'smoking_status': forms.RadioSelect(),
'marital_status': forms.RadioSelect(),
**{to_attribute(name='profile_description', language_code=language_code): forms.Textarea(attrs={'rows': 3, 'cols': 25}) for language_code, language_name in django_settings.LANGUAGES},
**{to_attribute(name='city', language_code=language_code): forms.TextInput() for language_code, language_name in django_settings.LANGUAGES},
**{to_attribute(name='children', language_code=language_code): forms.TextInput() for language_code, language_name in django_settings.LANGUAGES},
**{to_attribute(name='more_children', language_code=language_code): forms.TextInput() for language_code, language_name in django_settings.LANGUAGES},
**{to_attribute(name='match_description', language_code=language_code): forms.Textarea(attrs={'rows': 3, 'cols': 25}) for language_code, language_name in django_settings.LANGUAGES},
'diet_match': CustomJsonWidget(choices=User.DIET_VALID_CHOICES),
'smoking_status_match': CustomJsonWidget(choices=User.SMOKING_STATUS_VALID_CHOICES),
'marital_status_match': CustomJsonWidget(choices=User.MARITAL_STATUS_VALID_CHOICES),
}
@staticmethod
def __new__(cls, *args, **kwargs):
for language_code, language_name in django_settings.LANGUAGES:
setattr(cls, to_attribute(name='city', language_code=language_code), forms.CharField(label=_('city or locality'), max_length=120))
return super().__new__(*args, **kwargs)
def __init__(self, *args, **kwargs):
self.step = kwargs.pop('step', None)
super().__init__(*args, **kwargs)
self.delete_unneeded_fields()
if ('gender_to_match' in self.fields):
self.fields['gender_to_match'] = forms.MultipleChoiceField(choices=User.GENDER_CHOICES, widget=forms.CheckboxSelectMultiple)
if ('photo' in self.fields):
self.fields['photo'].widget.attrs['user'] = self.instance.user
if ('diet' in self.fields):
update_form_field_choices(field=self.fields['diet'], choices=self.instance.user.get_diet_choices())
self.fields['diet'].initial = self.instance.user.diet
if ('smoking_status' in self.fields):
update_form_field_choices(field=self.fields['smoking_status'], choices=self.instance.user.get_smoking_status_choices())
self.fields['smoking_status'].initial = self.instance.user.smoking_status
if ('marital_status' in self.fields):
update_form_field_choices(field=self.fields['marital_status'], choices=self.instance.user.get_marital_status_choices())
self.fields['marital_status'].initial = self.instance.user.marital_status
if ('diet_match' in self.fields):
update_form_field_choices(field=self.fields['diet_match'], choices=self.instance.get_diet_match_choices())
if ('smoking_status_match' in self.fields):
update_form_field_choices(field=self.fields['smoking_status_match'], choices=self.instance.get_smoking_status_match_choices())
if ('marital_status_match' in self.fields):
update_form_field_choices(field=self.fields['marital_status_match'], choices=self.instance.get_marital_status_match_choices())
for field_name, field in self.fields.items():
if (field_name in self.validators):
field.validators.extend(self.validators[field_name])
field.required = True
答案 0 :(得分:1)
更新2: ... ...但是,该字段被创建为表单中的最后一个字段,我希望它位于中间。有没有办法在中间添加此字段?
来自https://docs.djangoproject.com/en/2.1/ref/forms/api/#notes-on-field-ordering:
如果
Error: Package: glibc-2.12-1.212.el6_10.3.i686 (updates) Requires: glibc-common = 2.12-1.212.el6_10.3 Installed: glibc-common-2.17-55.el6.x86_64 (installed) glibc-common = 2.17-55.el6 Available: glibc-common-2.12-1.80.el6.x86_64 (centos6u3) glibc-common = 2.12-1.80.el6 Available: glibc-common-2.12-1.212.el6.x86_64 (base) glibc-common = 2.12-1.212.el6 Available: glibc-common-2.12-1.212.el6_10.3.x86_64 (updates) glibc-common = 2.12-1.212.el6_10.3 You could try using --skip-broken to work around the problem ** Found 2 pre-existing rpmdb problem(s), 'yum check' output follows: glibc-2.12-1.209.el6_9.2.i686 has missing requires of glibc-common = ('0', '2.12', '1.209.el6_9.2') glibc-2.17-55.el6.x86_64 is a duplicate with glibc-2.12-1.209.el6_9.2.i686
是字段名称的列表,则按照列表指定的顺序对字段进行排序,并根据默认顺序附加其余字段。 ...您可以随时使用
field_order
和order_fields()
中的字段名称列表重新排列字段。
field_order
答案 1 :(得分:0)
我不知道这是否有帮助,但是我有一个调查应用程序,其中不同的用户希望在背景信息表上获得不同的信息。我通过json文件提供。因此,在表单中,我有
[{
"fieldset" : "Basic Information",
"fields" : [
{
"field" : "form_filler",
"div" : ["form_filler_other"]
},{
"field" : "child_dob"
},{
"field" : "age"
},{
"field" : "sex"
},{
"field" : "country",
"div" : ["zip_code"]
},{
"field" : "birth_order"
}, {
"field" : "multi_birth_boolean",
"div" : ["multi_birth"]
}, {
"field" : "birth_weight_kg",
"choices" : [
{
"key" : "",
"value" : "--------"
},{
"key" : "1.0",
"value" : "Henry 1"
},{
"key" : "2.0",
"value" : "Weight 2"
},{
"key" : "3.0",
"value" : "Weight 3"
},{
"key" : "4.0",
"value" : "Weight 4"
}
],
"widget_type" : "Select"
}, {
"field" : "born_on_due_date",
"div" : ["early_or_late", "due_date_diff"]
}
]
}, { ...
}]
我的json文件如下所示:
field
div
键是一个输入字段,div
列表中的项目也是如此。在这种情况下,当选择字段(BooleanField)时,{{1}}列表中的字段必须完成,这是我通过clean方法所做的。
我的所有字段都在模型中指定,因此您只能选择要使用的字段
答案 2 :(得分:0)
真的很难理解您到底有什么问题。如果您可以回答我在下面提出的问题,那将非常有帮助。
我正在将几个字段移至另一个模型
哪些字段?从哪个型号?要哪个型号?
我假设您将city
字段从User
模型移到SiteProfile
。
调用
make_migrations
会导致错误,因为这些字段没有 当前模型中存在
什么错误? current model
指的是什么? SiteProfile
?将字段从一种模型转移到另一种模型应该是完全可行的。
我环顾了您的存储库。特别是您尝试从django-modeltranslation
迁移到django-translated-fields
的分支。并且还在Github上的django-translated-fields
存储库中找到了您的问题。
很遗憾,我无法完全理解您遇到的问题。 我认为您的问题可以分为两个独立的问题。
所以也许我们可以从迁移开始。 当您说迁移不起作用时,您是什么意思。你能告诉我这些错误吗?
答案 3 :(得分:0)
如果您希望每次更改模型时都动态地在ModelForm中显示模型的所有字段,则可以进行检查。 (我已经尝试过,它可以工作。)
在 forms.py
中created_at = models.DateTimeField(auto_now_add=True)
django.core.exceptions.FieldError: 'created_at' cannot be specified for Episode model form as it is a non-editable field
-----大警告-------
它将显示不可编辑字段的错误,例如(如果您可以更改功能以排除这些类型的字段,请编辑答案。):
auto_now_add=True
如果您从其中删除import SwiftUI
import UIKit
import AVFoundation
class PreviewView: UIView {
private var captureSession: AVCaptureSession?
init() {
super.init(frame: .zero)
var allowedAccess = false
let blocker = DispatchGroup()
blocker.enter()
AVCaptureDevice.requestAccess(for: .video) { flag in
allowedAccess = flag
blocker.leave()
}
blocker.wait()
if !allowedAccess {
print("!!! NO ACCESS TO CAMERA")
return
}
// setup session
let session = AVCaptureSession()
session.beginConfiguration()
let videoDevice = AVCaptureDevice.default(.builtInWideAngleCamera,
for: .video, position: .unspecified) //alternate AVCaptureDevice.default(for: .video)
guard videoDevice != nil, let videoDeviceInput = try? AVCaptureDeviceInput(device: videoDevice!), session.canAddInput(videoDeviceInput) else {
print("!!! NO CAMERA DETECTED")
return
}
session.addInput(videoDeviceInput)
session.commitConfiguration()
self.captureSession = session
}
override class var layerClass: AnyClass {
AVCaptureVideoPreviewLayer.self
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
var videoPreviewLayer: AVCaptureVideoPreviewLayer {
return layer as! AVCaptureVideoPreviewLayer
}
override func didMoveToSuperview() {
super.didMoveToSuperview()
if nil != self.superview {
self.videoPreviewLayer.session = self.captureSession
self.videoPreviewLayer.videoGravity = .resizeAspect
self.captureSession?.startRunning()
} else {
self.captureSession?.stopRunning()
}
}
}
struct PreviewHolder: UIViewRepresentable {
func makeUIView(context: UIViewRepresentableContext<PreviewHolder>) -> PreviewView {
PreviewView()
}
func updateUIView(_ uiView: PreviewView, context: UIViewRepresentableContext<PreviewHolder>) {
}
typealias UIViewType = PreviewView
}
struct DemoVideoStreaming: View {
var body: some View {
VStack {
PreviewHolder()
}.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .center)
}
}
,它将起作用。
注意
它将为所有选项的ForiegnKeyField创建下拉列表。