#python #django #django-views #django-templates
#python #django #django-представления #django-шаблоны
Вопрос:
Мне нужно создать две модели из одного шаблона. Создание модели продукта — это нормально. Модель продукта имеет отношение ManyToOne к ProductVariant. Но у меня возникла проблема при создании модели ProductVariant. request.POST.getlist('names')
это дает мне такой результат ['name1','name2
] и то же самое касается всех. Я хочу создать объект ProductVariant с каждым значением. Как я могу это сделать? Также я думаю, что есть проблема при построении a HStoreField
. request.POST.getlist('attributes')
выдает значение, подобное этому ['a:b','x:z']
, поэтому я преобразовал его в dictionary (но не уверен, что это работает).
Обновить:
Я хочу attributes
, names
… у всех будет одинаковое количество элементов в списке. Например, если имя ['a','b','c']
, то вес также будет иметь 3 значения в списке [12,15,23]
, подобном этому. Я хочу создать ProductVariant
объект 3 раза, так как в каждом списке будет 3 элемента в списке. Первый объект будет иметь значения полей из первого элемента списка, name=a,weight=12..
а для второго значения объекта будут name=b, weight=15
такими.
Как это будет возможно? Или я должен изменить логику? Есть предложения? Модели
class ProductVariant(models.Model):
name = models.CharField(max_length=255, blank=False, null=False)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
attributes = HStoreField()
price = models.FloatField(blank=False, null=False, default=0.0)
число просмотров
product = product_form.save()
attributes = request.POST.getlist('attributes')
names = request.POST.getlist('name')
up = request.POST.getlist('price')
weight = request.POST.getlist('weight')
print(names, 'names')
# converting attributes into the dictionary for the HStore field
for attribute in attributes:
attributes_dict = {}
key, value = attribute.split(':')
attributes_dict[key] = value
ProductVariant.objects.create(name=name,...) # for each value I want to create this.
Ответ №1:
Ответ на обновление:
names = ['a', 'b', 'c']
weights = [12, 15, 23]
params = zip(names, weights)
products = [ProductVariant(name=param[0], weight=param[1]) for param in params]
ProductVariant.objects.bulk_create(products)
Комментарии:
1. пожалуйста, обратитесь к публикации 1 ответа, если у вас есть несколько методов, вместо публикации нескольких ответов
Ответ №2:
Я не согласен с этим подходом, но если вы действительно хотите сделать это таким образом, zip
ing будет таким, как указал @forkcs.
Я бы использовал Django, чтобы помочь мне как можно больше, прежде чем я туда доберусь, пожалуйста, внесите это изменение. float ! = деньги
class ProductVariant(models.Model):
name = models.CharField(max_length=255, blank=False, null=False)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
attributes = HStoreField()
price = models.DecimalField(blank=False, null=False, default=0, max_digits=6, decimal_places=2)
Как только это будет сделано, форма должна выглядеть следующим образом:
class ProductVariantForm(forms.ModelForm):
class Meta:
fields = ('name', 'product', 'attributes', 'price')
model = ProductVariant
ProductVariantFormSet = formset_factory(ProductVariantForm)
Обратите внимание, что мне не нужно анализировать / очищать / форматировать attributes
? Это потому, что Django сделал это за меня 😉
И вы можете использовать это следующим образом, если вы изменяете свои поля и не используете одно и то же имя несколько раз: (вместо того, чтобы все ваши поля назывались «атрибутами», вы называете их «form-X-attributes», где X — число 0-бесконечность, пример)
product = product_form.save()
formset = ProductVariantFormSet(data=request.POST)
if formset.is_valid():
instances = []
for form in formset:
if form.is_valid(): # this could probably be removed
instances.append(form.save())
Для дополнительного кредита вы также можете сделать: (это не должно иметь большого значения)
product = product_form.save()
formset = ProductVariantFormSet(data=request.POST)
if formset.is_valid():
instances = []
for form in formset:
if form.is_valid(): # this could probably be removed
instances.append(form.save(save=False))
ProductVariant.objects.bulk_create(instances)
Что вы получаете? СТАНДАРТЫ!!! И разделение! Все, кто знает Django, знают, что вы сделали. Вся ваша чистая логика будет размещена в нужном месте (форме), и вы будете менее подвержены ошибкам.
Ps. я написал тесты для вас. https://gist.github.com/kingbuzzman/937a9d207bd937d1b2bb22249ae6bdb2#file-formset_example-py-L142 Если вам нужна дополнительная информация о моем подходе, обратитесь к документации https://docs.djangoproject.com/en/3.1/topics/forms/formsets /
Комментарии:
1. Будут ли какие-либо проблемы,
zip
поскольку это только что решило мою проблему. В любом случае спасибо за информацию, и я тоже попробую этот способ.2. Да, есть проблема, вам приходится слишком много выполнять вручную, заботиться об очистке, проверке ошибок … и т.д. Кроме этого, проблем нет 😜
3. @helloworld я предлагаю вам взглянуть на youtu.be/Uwuv05aZ6ug?t=361 — первая часть выступления — это то, что имеет отношение к тому, что я предлагаю — речь идет о законе Миллера (в целом выступление отличное).
Ответ №3:
Что касается атрибутов, их можно было бы сократить до одной строки следующим образом:
attributes_dict = dict(map(lambda x: x.split(':'), attributes))
Чтобы создать несколько объектов, вы должны либо выполнять итерации и создавать по одному объекту за раз, либо использовать bulk_create
:
for name in names:
ProductVariant.objects.create(name=name,...)
Или
ProductVariant.objects.bulk_create([ProductVariant(name=name) for name in names])
Комментарии:
1. Я должен использовать
for loop
не только для name, но и для других значений.2. Могу ли я использовать другие циклы после массового создания
for name in names
?3. Нравится это?
ProductVariant.objects.bulk_create([ProductVariant(name=name, price=p) for name in names for p in up])
4. Тогда сформулируйте свой вопрос лучше. Вы можете использовать все, что хотите, в цикле for, никто и ничто вас не держит. Пожалуйста, прочитайте документы: docs.djangoproject.com/en/3.1/ref/models/querysets/#bulk-create
5. Затем еще раз лучше опишите свою проблему. Обновите сообщение, укажите проблему, покажите журналы, объясните желаемый результат.
Ответ №4:
Наилучшей практикой для этого является использование bulk_create
метода.
product_variants = [ProductVariant(name=name) for name in names]
ProductVariant.objects.bulk_create(product_variants)