Django-Shapeshifiter problems - django

I quite new to django and I'm working in a simple project for the University. I'm trying to use the django-shapeshifter, but just by entering like in the example they provide, I get a syntax error I have one main table connected to tow tables with manytomany relations and would like to work with a single view to deal with the forms.
The models:
class PreciosUnitarios(models.Model):
redimiento = models.ForeignKey(Rendimientos, on_delete=models.CASCADE)
mano_obra = models.ManyToManyField(ManoObra, through='PuManoObra')
material_id = models.ManyToManyField(Materiales, through='Pu_Material')
valor_mo = models.FloatField(
validators=[validate_decimals], blank=True, null=True)
valor_material = models.FloatField(
validators=[validate_decimals], blank=True, null=True)
def __str__(self) -> str:
return self.redimiento.nombre
def get_total(self):
return self.valor_mo+self.valor_material
def get_absolute_url(self):
return reverse('pu_detail', kwargs={'pk': self.pk})
def save(self, *args, **kwargs):
if self.id:
pk = self.id
v = Variables.objects.get(pk=2)
rm = self.redimiento.unidades_jornal
jc = ManoObra.objects.get(cargo='Jefe de Cuadrilla')
pu_m = Pu_Material.objects.filter(pu_id=pk)
pu_mo = PuManoObra.objects.filter(pu_id=pk)
tm = pu_m.aggregate(Sum('subtotal'))['subtotal__sum']
tmo = pu_mo.aggregate(Sum('mo_subtotal'))['mo_subtotal__sum']
tmo = (tmo + (((jc.salario*8)/208) * 0.10))/rm
total_herramientas = tmo * v.herramientas
total_seguridad = tmo * v.seguridad
subtotal = tm+tmo+total_herramientas+total_seguridad
total = subtotal / (1 - v.gastos_admin)
total = total/(1-v.utilidad)
total = total*v.iva
self.valor_mo = total * \
(tmo/(subtotal))
self.valor_material = total * \
(tm/(subtotal))
super().save(*args, **kwargs)
else:
super().save(*args, **kwargs)
class PuManoObra(models.Model):
manoObra_id = models.ForeignKey(ManoObra, on_delete=models.CASCADE)
pu_id = models.ForeignKey(
PreciosUnitarios, on_delete=models.CASCADE, null=True, blank=True)
valor_jornal = models.FloatField(
validators=[validate_decimals], null=True, blank=True)
mo_subtotal = models.FloatField(
validators=[validate_decimals], null=True, blank=True)
ctd = models.PositiveIntegerField(default=1)
def __str__(self) -> str:
return self.pu_id.redimiento.nombre + ", "+self.manoObra_id.cargo
def save(self, *args, **kwargs):
vj = self.manoObra_id.salario/26
self.valor_jornal = vj
self.mo_subtotal = self.ctd*vj
super().save(*args, **kwargs)
class Pu_Material(models.Model):
material_id = models.ForeignKey(Materiales, on_delete=models.CASCADE)
pu_id = models.ForeignKey(
PreciosUnitarios, on_delete=models.CASCADE, null=True, blank=True)
cantidad = models.PositiveIntegerField(default=1)
subtotal = models.FloatField(
validators=[validate_decimals], null=True, blank=True)
class Meta():
unique_together = [['material_id', 'pu_id']]
def __str__(self) -> str:
return self.pu_id.redimiento.nombre + ", Material: "+self.material_id.material_nombre
def save(self, *args, **kwargs):
self.subtotal = self.material_id.precio*self.cantidad
super().save(*args, **kwargs)
my forms:
class PrecioUnitarioForm(forms.ModelForm):
class Meta():
model = PreciosUnitarios
fields = ('redimiento',
# 'mano_obra',
# 'material_id',
# 'valor_mo',
# 'valor_material'
)
labels = {
'redimiento': 'Selecionar Rendimiento',
'mano_obra': 'Selecionar Mano de Obra',
'material_id': '',
'valor_mo': '',
'valor_material': '',
}
widgets = {
'redimiento': forms.Select(attrs={'class': 'form-control'}),
'mano_obra': forms.SelectMultiple(attrs={'class': 'form-control'}),
'material_id': forms.SelectMultiple(attrs={'class': 'form-control'}),
'valor_mo': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Precio del Material'}),
'valor_material': forms.TextInput(attrs={'class': 'form-control'}),
}
class PuMaterialForm(forms.ModelForm):
class Meta():
model = Pu_Material
fields = (
'material_id', 'pu_id', 'cantidad'
)
labels = {
'material_id': 'Material', 'pu_id': 'Preciounitario', 'cantidad': ''
}
widgets = {
'material_id': forms.Select(attrs={'class': 'form-control'}),
'pu_id': forms.Select(attrs={'class': 'form-control'}),
'cantidad': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Cantidad'})
}
class PuManoObraForm(forms.ModelForm):
class Meta():
model = PuManoObra
fields = (
'manoObra_id', 'pu_id', 'ctd'
)
labels = {'manoObra_id': 'Mano de Obra',
'pu_id': 'Precio Unitario',
'ctd': ''
}
widgets = {
'manoObra_id': forms.Select(attrs={'class': 'form-control'}),
'pu_id': forms.Select(attrs={'class': 'form-control'}),
'ctd': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Cantidad'})
}
the shapeshift code:
class PrecioUnitarioFormView(MultiModelFormView):
form_classes = ('PrecioUnitarioForm', 'PuMaterialForm', 'PuManoObraForm')
template_name = 'cotizacion/preciosunitarios.html'
success_url = 'cotizacion/pu_detail.html'
success_message = ''
def get_instances(self):
instances = {
'preciounitariofomr': self.request.preciosunitarios,
'pumaterialform': Pu_Material.objects.filter(
user=self.request.preciosunitarios).first(),
'pumanoobraform': PuManoObra.objects.filter(
user=self.request.preciosunitarios).first()
}
return instances
the error says that "object has no attribute name".
Anyone can help?

Related

Django UpdateView Two Seperate Form Save (included inlineformset_factory)

I have a specific problem with my forms. I think it would be better to share my codes instead of explaining the problem in detail.
However, to explain in a nutshell; inside my model I have field OneToOneField and model of that field has inlineformset_factory form. My new model also has a form and I want to save both forms.
I get the following error when I want to save the offer update form:
TypeError at /ru/mytarget/offer-update/T2GTTT053E9/
AdminOfferUpdateView.form_invalid() missing 2 required positional arguments: 'request_form' and 'request_item_formset'
Models:
request.py
class RequestModel(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name="customer_requests")
id = ShortUUIDField(primary_key=True, length=10, max_length=10, prefix="T", alphabet="ARGET0123456789", unique=True, editable=False)
status = models.BooleanField(default=True)
request_title = models.CharField(max_length=300)
......
updated_on = models.DateTimeField(auto_now=True)
published_date = models.DateTimeField(default=timezone.now)
def __str__(self):
return str(self.request_title)
class Meta:
verbose_name_plural = "Requests"
verbose_name = "Request"
def get_absolute_url(self):
return reverse('mytarget:customer_request_details', kwargs={'pk': self.id})
class RequestItem(models.Model):
request_model = models.ForeignKey(RequestModel, on_delete=models.CASCADE, related_name="request_items")
product_name = models.CharField(max_length=300)
......
offer.py
class OfferModel(models.Model):
request_model_name = models.OneToOneField(RequestModel, on_delete=models.CASCADE, primary_key=True)
status = models.BooleanField(default=True)
offer_validity = models.CharField(max_length=50, blank=True)
......
updated_on = models.DateTimeField(auto_now=True)
published_date = models.DateTimeField(default=timezone.now)
def __str__(self):
return str(self.request_model_name)
class Meta:
verbose_name_plural = "Offers"
verbose_name = "Offer"
def get_absolute_url(self):
return reverse('mytarget:admin_offer_update', kwargs={'pk': self.request_model_name})
Forms:
request_create_form.py
class CustomerRequestForm(forms.ModelForm):
disabled_fields = ("customer",)
class Meta:
model = RequestModel
fields = ("customer", "request_title", "delivery_time", "shipping_country", "shipping_address",
"preferred_currency", "shipping_term", "delivery_term")
widgets = {
'request_title': TextInput(attrs={'class': 'form-control tableFormInputs',
'placeholder': _('Example: Printers, Toner, and Cartridges')}),
......
}
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('customer')
super(CustomerRequestForm, self).__init__(*args, **kwargs)
self.fields['preferred_currency'].queryset = self.fields['preferred_currency'].queryset.translated().order_by("translations__currency_name")
self.fields['shipping_term'].queryset = self.fields['shipping_term'].queryset.translated().order_by("translations__shipping_term")
for field in self.disabled_fields:
self.fields[field].widget = forms.HiddenInput()
self.fields[field].disabled = True
class CustomerRequestItemForm(forms.ModelForm):
class Meta:
model = RequestItem
fields = ("product_name", "product_info", "target_price", "price", "quantity", "dimensions", "net_weight", "gross_weight",
"hs_or_tn_ved_code", "brand", "manufacturer", "origin_country", "manufacturer_address")
exclude = ()
widgets = {
'product_name': TextInput(attrs={'class': 'form-control tableFormInputs'}),
......
}
RequestItemInlineFormset = inlineformset_factory(RequestModel, RequestItem,
form=CustomerRequestItemForm,
extra=1,
can_delete=True
)
offer_update_form.py
class AdminOfferUpdateForm(forms.ModelForm):
disabled_fields = ()
hidden_fields = ("request_model_name",)
request_title = forms.CharField(required=False, widget=TextInput(attrs={'class': 'form-control tableFormInputs', 'placeholder': _('Example: Printers, Toner, and Cartridges')}))
......
class Meta:
model = OfferModel
fields = ("request_model_name", "offer_validity", ......
)
widgets = {'offer_validity': TextInput(attrs={'class': 'form-control tableFormInputs'}),
......
'is_detailed_offer': CheckboxInput(attrs={'class': 'form-check-input'}),
}
def __init__(self, *args, **kwargs):
super(AdminOfferUpdateForm, self).__init__(*args, **kwargs)
self.fields["preferred_currency"].choices = [(c.id, c.currency_name) for c in Currency.objects.all()]
self.fields["shipping_term"].choices = [(st.id, st.shipping_term) for st in ShippingTerm.objects.all()]
self.fields["delivery_term"].choices = [(dt.id, dt.delivery_term) for dt in DeliveryTerms.objects.all()]
self.fields["request_statuses"].choices = [(r.id, r.status) for r in RequestStatus.objects.all()]
for field in self.disabled_fields:
self.fields[field].disabled = True
for field in self.hidden_fields:
self.fields[field].widget = forms.HiddenInput()
Views:
offer_update_view.py
#method_decorator([login_required(login_url=reverse_lazy("accounts:signin")), user_is_superuser], name='dispatch')
class AdminOfferUpdateView(UpdateView):
model = OfferModel
form_class = AdminOfferUpdateForm
template_name = "mytarget/admin_offer_update.html"
def get_context_data(self, **kwargs):
context = super(AdminOfferUpdateView, self).get_context_data(**kwargs)
if self.request.POST:
context['request_form'] = AdminOfferUpdateForm(self.request.POST, instance=self.object.request_model_name)
context['request_item_formset'] = RequestItemInlineFormset(self.request.POST, instance=self.object.request_model_name)
else:
context['request_form'] = AdminOfferUpdateForm(instance=self.object.request_model_name)
context['request_item_formset'] = RequestItemInlineFormset(instance=self.object.request_model_name)
return context
def form_valid(self, form):
context = self.get_context_data()
request_form = context['request_form']
request_item_formset = context['request_item_formset']
with transaction.atomic():
self.object = form.save()
if request_form.is_valid() and request_item_formset.is_valid():
request_form.instance = self.object.request_model_name
request_form.save()
request_item_formset.instance = self.object.request_model_name
request_item_formset.save(commit=False)
for ri in request_item_formset:
ri.save(commit=False)
request_item_formset.save()
return super(AdminOfferUpdateView, self).form_valid(form)
def form_invalid(self, form, request_form, request_item_formset):
return self.render_to_response(
self.get_context_data(form=form, request_form=request_form, request_item_formset=request_item_formset)
)
def get_initial(self):
self.object = self.get_object()
if self.object:
return {"request_model": self.object.request_model_name, "request_item_formset": self.object.request_model_name}
return super().initial.copy()
def get_success_url(self):
return reverse('mytarget:admin_offer_update', kwargs={'pk': self.object.id})
I solved my problem. I created a button function that creates a new model with inheritance of other model fields. In this way, there is no need to edit the form of the other model inside the form of my current model.

django slick report and nested categories

I am using in django the following models.py:
class Expense(models.Model):
name = models.CharField(max_length=50)
date = models.DateField(unique=False, blank=False)
slug = models.SlugField(unique=True, null=True, default='')
price = models.DecimalField(default=0.0, blank=True, max_digits = 20, decimal_places = 2)
category = models.ForeignKey(
'Category',
related_name="Expense",
on_delete=models.CASCADE
)
account = models.ForeignKey(Account, on_delete=models.CASCADE, verbose_name=u"Account", help_text=u"account")
def __str__(self):
return '{},{},{}'.format(self.name, self.date, self.price)
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
super(Expense,self).save(*args, **kwargs)
def get_absolute_url(self):
return self.slug
class Category(MPTTModel):
name = models.CharField(max_length=200)
slug = models.SlugField(unique=True, null=True, default='')
parent = TreeForeignKey(
'self',
blank=True,
null=True,
related_name='child',
on_delete=models.CASCADE
)
class Meta:
unique_together = ('slug', 'parent',)
verbose_name_plural = "categories"
def __str__(self):
full_path = [self.name]
k = self.parent
while k is not None:
full_path.append(k.name)
k = k.parent
return ' -> '.join(full_path[::-1])
The TreeForeignKey allows me to define nested categories, such as Home -> Electricity and so on.
I am using the following Slick Report view.py:
class TotalExpenses(SlickReportView):
report_model = Expense
date_field = 'date'
group_by = 'category'
columns = ['name', SlickReportField.create(method=Sum, field='price', name='price__sum', verbose_name=('Total category $'))]
charts_settings = [
{
'type': 'bar',
'data_source': 'price__sum',
'title_source': 'name',
},
]
It works but I would like to sum only level 1 categories. Do you know how this might be possible?

attribute error in django. django.db.models has no attribute

I am trying to write the code so that a user in the system can view complaint registered by others on this page but not their own complaints. This is the code, but I don't understand what's wrong:
views.py:
class OtherPeoplesComplaints(TemplateView):
model = Complaint
form_class = ComplaintForm
template_name = 'userComplaints.html'
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
context["complaints"] = models.Complaint.objects.exclude(
profile__user = self.request.user
)
models.py:
class Complaint(models.Model):
user = models.ForeignKey(User, on_delete= models.CASCADE, null = True, blank=True)
id = models.AutoField(blank=False, primary_key=True)
reportnumber = models.CharField(max_length=500 ,null = True, blank= False)
eventdate = models.DateField(null=True, blank=False)
event_type = models.CharField(max_length=300, null=True, blank=True)
device_problem = models.CharField(max_length=300, null=True, blank=True)
manufacturer = models.CharField(max_length=300, null=True, blank=True)
product_code = models.CharField(max_length=300, null=True, blank=True)
brand_name = models.CharField(max_length = 300, null=True, blank=True)
exemption = models.CharField(max_length=300, null=True, blank=True)
patient_problem = models.CharField(max_length=500, null=True, blank=True)
event_text = models.TextField(null=True, blank= True)
document = models.FileField(upload_to='static/documents', blank=True, null=True)
def __str__(self):
return self.reportnumber
forms.py:
class DateInput(forms.DateInput):
input_type = 'date'
class ComplaintForm(ModelForm):
class Meta:
model = Complaint
fields = '__all__'
widgets = {
'reportnumber': forms.TextInput(attrs={'placeholder': 'Report number'}),
'event_type': forms.TextInput(attrs={'placeholder': 'Event type'}),
'eventdate': DateInput(),
'device_problem': forms.TextInput(attrs={'placeholder': 'Device Problem'}),
'event_text': forms.Textarea(attrs={'style': 'height: 130px;width:760px'}),
'manufacturer': forms.TextInput(attrs={'placeholder': 'Enter Manufacturer Name'}),
'product_code': forms.TextInput(attrs={'placeholder': 'Enter Product Code'}),
'brand_name': forms.TextInput(attrs={'placeholder': 'Enter Brand Name'}),
'exemption': forms.TextInput(attrs={'placeholder': 'Enter Exemption'}),
'patient_problem': forms.TextInput(attrs={'placeholder': 'Enter Patient Problem'}),
}
def clean(self):
cleaned_data = super(ComplaintForm, self).clean()
reportnumber = cleaned_data.get('reportnumber')
event_text = cleaned_data.get('event_text')
if not reportnumber and not event_text:
raise forms.ValidationError('You have to write something!')
return cleaned_data
In this view
class OtherPeoplesComplaints(TemplateView):
model = Complaint
form_class = ComplaintForm
template_name = 'userComplaints.html'
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
context["complaints"] = models.Complaint.objects.exclude(
profile__user = self.request.user
)
you are using this query :
context["complaints"] = models.Complaint.objects.exclude(profile__user = self.request.user)
change it to :
context["complaints"] = self.model.objects.exclude(user = self.request.user)
Explanation :
Your model is Complaint which you can access using self.model as you have defined the class variable here :
class OtherPeoplesComplaints(TemplateView):
model = Complaint
and
You want to access complaint of other users except your own, so this update in your query :
exclude(user = self.request.user)

How do you limit choices in a Django Inlineformset_factory based on User?

I have a Timesheet app and I want to limit the Projects a User can allocate their time to the Projects they are working on.
MODELS My models look like this
class Project (models.Model):
name = models.CharField(
verbose_name = 'Project Title',
max_length = 80
)
code = models.CharField(
verbose_name = 'Project Code',
max_length = 15
)
supervisor = models.ForeignKey (
User,
on_delete=models.CASCADE
)
staff = models.ManyToManyField (
User,
related_name= "project_resources"
)
def __str__(self):
return u'%s' % (self.name)
class Meta:
ordering = ['name']
class Timesheet (models.Model):
user = models.ForeignKey (
User,
on_delete=models.CASCADE)
start_date = models.DateField (
verbose_name = "Start Date"
)
def __str__(self):
return u'%s | %s' % (self.user, self.start_date)
class Meta:
ordering = ['user','start_date']
class TimesheetRow (models.Model):
''' specifies a timesheet row which is unique based on Timesheet, Project and Labour Category
'''
timesheet = models.ForeignKey(
Timesheet,
on_delete=models.CASCADE
)
project = models.ForeignKey(
Project,
on_delete=models.CASCADE
)
labor = models.ForeignKey(
LaborCategory,
on_delete=models.CASCADE
)
sunday = models.DecimalField (default = 0, max_digits=4, decimal_places=2)
monday = models.DecimalField (default = 0, max_digits=4, decimal_places=2)
tuesday = models.DecimalField (default = 0, max_digits=4, decimal_places=2)
wednesday = models.DecimalField (default = 0, max_digits=4, decimal_places=2)
thursday = models.DecimalField (default = 0, max_digits=4, decimal_places=2)
friday = models.DecimalField (default = 0, max_digits=4, decimal_places=2)
saturday = models.DecimalField (default = 0, max_digits=4, decimal_places=2)
def __str__(self):
return u'%s | %s' % (self.timesheet.user, self.timesheet.start_date)
class Meta:
unique_together = ('timesheet', 'project', 'labor',)
ordering = ['timesheet', 'project','labor']
And my FORMS look like this.
class TimesheetForm(forms.ModelForm):
class Meta:
model = Timesheet
fields = ['id', 'user', 'start_date']
widgets = {
'user' : forms.HiddenInput(),
'id' : forms.HiddenInput(),
'start_date' : forms.HiddenInput(),
}
class TimesheetRowInlineForm(forms.ModelForm):
class Meta:
model = TimesheetRow
exclude =['timesheet']
widgets = {
'id' : forms.HiddenInput(),
'project' : forms.Select(attrs={'class' : 'form-control'}),
'labor' : forms.Select(attrs={'class' : 'form-control'}),
'sunday' : forms.NumberInput(attrs={'class' : 'form-control'}),
'monday' : forms.NumberInput(attrs={'class' : 'form-control'}),
'tuesday' : forms.NumberInput(attrs={'class' : 'form-control'}),
'wednesday' : forms.NumberInput(attrs={'class' : 'form-control'}),
'thursday' : forms.NumberInput(attrs={'class' : 'form-control'}),
'friday' : forms.NumberInput(attrs={'class' : 'form-control'}),
'saturday' : forms.NumberInput(attrs={'class' : 'form-control'}),
}
TimesheetRowInlineFormSet = forms.inlineformset_factory(
Timesheet,
TimesheetRow,
form=TimesheetRowInlineForm,
extra=1,
exclude = ['id'],
can_delete=True,
can_order=False)
This gives me a fine form and everything works fine through the views but I cannot work out how to limit the Projects dropdown on the TimesheetRowInlineForm to those users in staff.
For completeness, this is the VIEW
class TimesheetView (LoginRequiredMixin, UpdateView):
model = Timesheet
form_class = TimesheetForm
success_url = '/'
def get_start_date(self, *args, **kwargs):
try:
start_date = self.kwargs['start_date']
except:
today = datetime.date.today()
start_date = today - datetime.timedelta(7+ ((today.weekday()+1)%7) )
return start_date
def get_object(self, *args, **kwargs):
obj, created = Timesheet.objects.get_or_create(user=self.request.user, start_date=self.get_start_date())
return obj
def get_context_data(self, **kwargs):
data = super(TimesheetView, self).get_context_data(**kwargs)
if self.request.POST:
data['timesheetrows'] = TimesheetRowInlineFormSet(self.request.POST, instance=self.get_object())
else:
data['timesheetrows'] = TimesheetRowInlineFormSet(instance=self.get_object())
return data
def get_initial(self):
return { 'user': self.request.user,
'start_date' : self.get_start_date() }
def form_valid(self, form):
context = self.get_context_data()
timesheetrows = context['timesheetrows']
with transaction.atomic():
self.object = form.save()
if timesheetrows.is_valid():
timesheetrows.instance = self.object
timesheetrows.save()
return super(TimesheetView, self).form_valid(form)
EDIT
I've worked out how to do this within admin, namely:
class TimesheetRowAdmin(admin.ModelAdmin):
def get_model_perms(self, request):
"""
Return empty perms dict thus hiding the model from admin index.
"""
return {}
admin.site.register(TimesheetRow, TimesheetRowAdmin)
class TimesheetRowInline(admin.TabularInline):
model = TimesheetRow
can_delete = True
extra = 1
def formfield_for_foreignkey(self, db_field, request=None,**kwargs):
field = super(TimesheetRowInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
if db_field.name == 'project':
if request.user is not None:
field.queryset = field.queryset.filter(staff=request._obj_.user)
if not field.queryset:
field.queryset = field.queryset.all()
else:
field.queryset = field.queryset.none()
return field
class TimesheetAdmin(admin.ModelAdmin):
list_display = ['user', 'start_date']
ordering = ['user','start_date']
inlines = [TimesheetRowInline]
def get_form(self, request, obj=None, **kwargs):
request._obj_ = obj
return super().get_form(request, obj, **kwargs)
admin.site.register(Timesheet, TimesheetAdmin)
I still need to reflect that for a non-staff user.
Having solved it in Admin above. This is how I solved it in my view. I effectively dynamically create the form within my view.
class TimesheetView (LoginRequiredMixin, UpdateView):
model = Timesheet
form_class = TimesheetForm
success_url = '/'
def create_inline_form(self):
class DynamicTimesheetRowInlineForm (forms.ModelForm):
project = forms.ModelChoiceField(queryset=Project.objects.filter(staff=self.request.user),
widget=forms.Select(attrs={'class' : 'form-control'}))
class Meta:
model = TimesheetRow
exclude =['timesheet']
widgets = {
'id' : forms.HiddenInput(),
#'project' : forms.Select(attrs={'class' : 'form-control'}),
'labor' : forms.Select(attrs={'class' : 'form-control'}),
'sunday' : forms.NumberInput(attrs={'class' : 'form-control'}),
'monday' : forms.NumberInput(attrs={'class' : 'form-control'}),
'tuesday' : forms.NumberInput(attrs={'class' : 'form-control'}),
'wednesday' : forms.NumberInput(attrs={'class' : 'form-control'}),
'thursday' : forms.NumberInput(attrs={'class' : 'form-control'}),
'friday' : forms.NumberInput(attrs={'class' : 'form-control'}),
'saturday' : forms.NumberInput(attrs={'class' : 'form-control'}),
}
return DynamicTimesheetRowInlineForm
def get_start_date(self, *args, **kwargs):
try:
start_date = self.kwargs['start_date']
except:
today = datetime.date.today()
start_date = today - datetime.timedelta( ((today.weekday()+1)%7) )
return start_date
def get_object(self, *args, **kwargs):
obj, created = Timesheet.objects.get_or_create(user=self.request.user, start_date=self.get_start_date())
return obj
def get_context_data(self, **kwargs):
data = super(TimesheetView, self).get_context_data(**kwargs)
DynamicTimesheetRowInlineFormSet = forms.inlineformset_factory(
Timesheet,
TimesheetRow,
form=self.create_inline_form(),
extra=1,
exclude = ['id'],
can_delete=True,
can_order=False)
data['timesheetrows'] = DynamicTimesheetRowInlineFormSet(self.request.POST or None,
instance=self.get_object())
return data
def get_initial(self):
return {'user': self.request.user,
'start_date' : self.get_start_date() }
def form_valid(self, form):
context = self.get_context_data()
timesheetrows = context['timesheetrows']
print (timesheetrows.errors)
with transaction.atomic():
self.object = form.save()
if timesheetrows.is_valid():
timesheetrows.instance = self.object
timesheetrows.save()
return super(TimesheetView, self).form_valid(form)

How to pass variable as argument in Meta class in Django Form?

forms.py
class MySelect(forms.Select):
def __init__(self, *args, **kwargs):
self.variations = kwargs.pop('variations')
super(MySelect, self).__init__(*args, **kwargs)
def render_option(self, selected_choices, option_value, option_label):
return '<option whatever>...</option>'
class CartItemForm(forms.ModelForm):
class Meta:
model = CartItem
fields = (
'variation',
'width',
'height',
'quantity',
)
widgets = {
'variation': MySelect(variations=self.variation_query)
}
def __init__(self, *args, **kwargs):
product = kwargs.pop('product')
try:
cart = kwargs.pop('cart')
self.cart = cart
except:
pass
super().__init__(*args, **kwargs)
variation_field = self.fields['variation']
variation_field.queryset = Variation.objects.filter(
product=product
)
self.variation_query = Variation.objects.filter(
product=product
)
def save(self):
cart_item = super().save(commit=False)
cart_item.cart = self.cart
cart_item.save()
return cart_item
Below is where you have to pay attention to.
(in Meta class)
widgets = {
'variation': MySelect(variations=self.variation_query)
}
self.variation_query is from __init__.
How can I do this?
models.py
class CartItem(models.Model):
cart = models.ForeignKey("Cart")
variation = models.ForeignKey(Variation)
# 벽화 너비
width = models.PositiveIntegerField(
default=1,
validators=[MinValueValidator(1)],
)
class Product(TimeStampedModel):
name = models.CharField(max_length=120, unique=True)
slug = models.SlugField(null=True, blank=True)
description = models.TextField(max_length=400, blank=True)
is_active = models.BooleanField(default=True)
place_category = models.ForeignKey(
"PlaceCategory",
related_name="products_by_place", # category.products_by_place.all()
)
subject_category_set = models.ManyToManyField(
"SubjectCategory",
related_name="products_by_subject", # category.products_by_subject.all()
)
# 벽화 높이
height = models.PositiveIntegerField(
default=1,
validators=[MinValueValidator(1)],
)
quantity = models.PositiveIntegerField(
default=1,
validators=[MinValueValidator(1)],
)
class Variation(TimeStampedModel):
COLOR_CHOICES = (
('black', '흑백'),
('single', '단색'),
('multi', '컬러'),
)
price = models.DecimalField(
decimal_places=0,
max_digits=15,
blank=True,
null=True,
)
product = models.ForeignKey(Product)
color = models.CharField(
max_length=10,
choices=COLOR_CHOICES,
)
is_active = models.BooleanField(default=True)
That's not a thing you would do in Meta. You need to do the whole thing in __init__.
You're already doing that in fact, so I don't know why you want to override Meta at all.