Skip to content

Instantly share code, notes, and snippets.

@rahit
Last active December 16, 2015 16:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rahit/946e1c076dac9269552f to your computer and use it in GitHub Desktop.
Save rahit/946e1c076dac9269552f to your computer and use it in GitHub Desktop.
Dynamic form field based on another model's entries and save them in a m2m way in Django
from myapp.models import Attribute, Item, ItemAttribute
from django.forms import ModelForm, HiddenInput, IntegerField, CharField
class ItemForm(ModelForm):
class Meta():
model = Item
exclude = ['attributes']
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request')
super(ItemForm, self).__init__(*args, **kwargs);
# Getting all attributes
attributes = Attribute.objects.all()
# Dynamically adding form field for each attribute
for attr in attributes:
# hardcodingly using char field type.
# In future it will be dynamicly handled by the type
# specified in attribute_type
self.fields[attr.attribute] = CharField(required=True)
from __future__ import unicode_literals
from django.db import models
class Attribute(models.Model):
TYPE_CHOICES = (
('text', 'text'),
('number', 'number')
)
attribute = models.CharField(primary_key=True, max_length=50)
attribute_type = models.CharField(max_length=20, choices=TYPE_CHOICES)
def __str__(self): # __unicode__ on Python 2
return self.attribute
class Item(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=50)
attributes = models.ManyToManyField(Attribute, through='ItemAttribute')
def __str__(self): # __unicode__ on Python 2
return self.id
class ItemAttribute(models.Model):
id = models.AutoField(primary_key=True)
item = models.ForeignKey(Item, on_delete=models.CASCADE)
attribute = models.ForeignKey(Attribute, on_delete=models.CASCADE)
value = models.CharField(max_length=250)
from django.core.urlresolvers import reverse_lazy
from myapp.forms import ItemForm
from myapp.models import Item, ItemAttribute, Attribute
class ItemCreate(FormView):
form_class = ItemForm
template_name = 'myapp/item_form.html'
success_url = reverse_lazy('item_list')
# add the request to the kwargs
def get_form_kwargs(self):
kwargs = super(ItemCreate, self).get_form_kwargs()
kwargs['request'] = self.request
return kwargs
def form_valid(self, form):
item = form.save(commit = True)
attributes = Attribute.objects.all()
for attr in attributes:
value = self.request.POST.get(attr.attribute)
item_attribute = ItemAttribute.objects.create(item=item, attribute=attr, value=value)
return super(ItemCreate, self).form_valid(form)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment