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
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.
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?
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)
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)
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.